diff --git a/Workspace_msvc/lib_com.vcxproj b/Workspace_msvc/lib_com.vcxproj
index eaea38441a3e302744915d62b36ca2cabc5e937d..f55a30abbd690261a49233e1d5cadbbb59ef1c9a 100644
--- a/Workspace_msvc/lib_com.vcxproj
+++ b/Workspace_msvc/lib_com.vcxproj
@@ -264,6 +264,7 @@
+
diff --git a/Workspace_msvc/lib_com.vcxproj.filters b/Workspace_msvc/lib_com.vcxproj.filters
index 54806691daec178e44774e69615212a3de783f2b..d46cc4712a40bc6363cc3460921e6dc9d1cac854 100644
--- a/Workspace_msvc/lib_com.vcxproj.filters
+++ b/Workspace_msvc/lib_com.vcxproj.filters
@@ -521,6 +521,8 @@
+
+
diff --git a/lib_com/cnst.h b/lib_com/cnst.h
index 8c2bb08e3cce97492ba971e151831cd1682ab08f..41a718269ce9ce639ead16003a992dcaa4c0eec4 100644
--- a/lib_com/cnst.h
+++ b/lib_com/cnst.h
@@ -165,7 +165,7 @@
#define DEC 1 /* Index for "decoder" */
#define DEC_IVAS 2 /* Index for IVAS decoder */
-
+#define OUTPUT_Q 11
enum{
NB = 0, /* Indicator of 4 kHz bandwidth */
@@ -211,9 +211,6 @@ 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() */
@@ -1684,6 +1681,7 @@ enum
#define OUTMAX_SQ_INV 0.00000000093132257461547852f /* 1/2^30 */
#define DELTA ( 1e-20f )
+#define DELTA_FX ( 1 )
#define DELTA_MANTISSA_W16 0x5e73
#define DELTA_MANTISSA_W32 0x5e728433
#define DELTA_EXPONENT (-66)
@@ -1982,6 +1980,7 @@ typedef enum _DCTTYPE
#define EPSILON 0.000000000000001f
#define EPSILON_FX 0
+#define EPSILON_FX_SMALL 1
#ifdef IVAS_FLOAT_FIXED
#define EPSILON_FIX (1)
#endif
diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h
index 87dd9a14ca4bc3320210e2aba092ffb7012f741d..cc848c7f6c02e9d9390b64688258980713f46456 100644
--- a/lib_com/ivas_cnst.h
+++ b/lib_com/ivas_cnst.h
@@ -67,9 +67,11 @@
#define INV_SQRT2 7.071067811865475e-1f /* 1/sqrt(2) */
#define INV_SQRT3 0.577350269189626f /* 1/sqrt(3) */
+#define INV_SQRT2_FX 1518500224 /* 1/sqrt(2) */
#ifdef IVAS_FLOAT_FIXED
-#define INV_SQRT2_FX 23170 /* 1/sqrt(2) Q15*/
+#define INV_SQRT2_FX_Q15 23170 /* 1/sqrt(2) Q15*/
+
#endif
#define LOG_10 2.30258509299f
diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h
index de33739c3b9a3c52e82aae26a99aa860ca2b901c..a965ac7a0d349af9b4aeee1dff9ecf99fd034a81 100644
--- a/lib_com/ivas_prot.h
+++ b/lib_com/ivas_prot.h
@@ -531,6 +531,14 @@ void synchro_synthesis(
const int16_t sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */
);
+void synchro_synthesis_fixed(
+ const int32_t ivas_total_brate, /* i : IVAS total bitrate */
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ float *output[CPE_CHANNELS], /* i/o: output synthesis signal */
+ const int16_t output_frame, /* i : Number of samples */
+ const int16_t sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */
+);
+
void stereo_tcx_init_enc(
Encoder_State *st /* i/o: encoder state structure */
);
@@ -727,7 +735,11 @@ void smooth_dft2td_transition(
const int16_t output_frame /* i : output frame length */
);
-
+void smooth_dft2td_transition_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *output_fx[CPE_CHANNELS], /* i/o: synthesis @external Fs */
+ const int16_t output_frame /* i : output frame lenght */
+);
/*! r: flag indicating a valid bitrate */
int16_t is_IVAS_bitrate(
const int32_t ivas_total_brate /* i : IVAS total bitrate */
@@ -1954,12 +1966,24 @@ void stereo_tca_dec(
const int16_t output_frame /* i : length of a frame per channel */
);
+void stereo_tca_dec_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *synth[CPE_CHANNELS], /* i/o: output synth */
+ const int16_t output_frame /* i : length of a frame per channel */
+);
+
void stereo_tca_scale_R_channel(
CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
float *output, /* i/o: output synthesis, R channel */
const int16_t output_frame /* i : frame length */
);
+void stereo_tca_scale_R_channel_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *output_fx, /* i/o: output synthesis, R channel */
+ const int16_t output_frame /* i : frame length */
+);
+
void adjustTargetSignal(
float *target,
const int16_t prevShift,
@@ -1968,7 +1992,12 @@ void adjustTargetSignal(
const int16_t method
);
-
+void adjustTargetSignal_fx(
+ Word32 *target_fx,
+ const int16_t prevShift,
+ const int16_t currShift,
+ const int16_t L_shift_adapt,
+ const int16_t method);
/*----------------------------------------------------------------------------------*
* IC-BWE Stereo prototypes
*----------------------------------------------------------------------------------*/
@@ -2111,6 +2140,11 @@ void stereo_td_init_dec(
const int16_t last_element_mode /* i : last element mode */
);
+void stereo_td_init_dec_fx(
+ STEREO_TD_DEC_DATA_HANDLE hStereoTD, /* i/o: TD stereo decoder handle */
+ const int16_t last_element_mode /* i : last element mode */
+);
+
void tdm_configure_dec(
const int16_t ivas_format, /* i : IVAS format */
const int16_t ism_mode, /* i : ISM mode in combined format */
@@ -2131,6 +2165,18 @@ void tdm_upmix_plain(
const int16_t plus_minus_flag /* i : plus/minus flag */
);
+void tdm_upmix_plain_fx(
+ Word32 Left_fx[], /* o : left channel */
+ Word32 Right_fx[], /* o : right channel */
+ const Word32 PCh_2_L_fx[], /* i : primary channel */
+ const Word32 SCh_2_R_fx[], /* i : secondary channel */
+ const Word32 LR_ratio_fx, /* i : mixing ratio */
+ const Word32 inv_den_LR_ratio_fx, /* i : inverse mixing ration */
+ const int16_t start_index, /* i : start index */
+ const int16_t end_index, /* i : end index */
+ const int16_t plus_minus_flag /* i : plus/minus flag */
+);
+
void stereo_tdm_combine(
CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
float *PCh_2_L, /* i/o: Primary channel -> output as L channel */
@@ -2140,6 +2186,15 @@ void stereo_tdm_combine(
const int16_t tdm_ratio_idx /* i : TDM ratio index */
);
+void stereo_tdm_combine_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *PCh_2_L_fx, /* i/o: Primary channel -> output as left channel */
+ Word32 *SCh_2_R_fx, /* i/o: Secondary channel -> output as right channel*/
+ const int16_t output_frame, /* i : Number of samples */
+ const int16_t flag_HB, /* i : flag to distinguish between core (0) and HB (1) synthesis */
+ const int16_t tdm_ratio_idx /* i : TDM ratio index */
+);
+
/*! r: replication decision; 1 = Use old LP */
int16_t tdm_lp_comparison(
STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i/o: TD stereo encoder handle */
@@ -2876,6 +2931,12 @@ void applyDmxMdctStereo(
const int16_t output_frame /* i : output frame length */
);
+void applyDmxMdctStereo_fx(
+ const CPE_DEC_HANDLE hCPE, /* i : CPE handle */
+ Word32 *output_fx[CPE_CHANNELS], /* o : output from core decoder */
+ const int16_t output_frame /* i : output frame length */
+);
+
/*----------------------------------------------------------------------------------*
* Front-VAD prototypes
@@ -2956,7 +3017,12 @@ void stereo_cna_update_params(
const int16_t output_frame, /* i : Output frame length */
const int16_t tdm_ratio_idx /* i : TDM ratio index */
);
-
+void stereo_cna_update_params_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *output_fx[CPE_CHANNELS], /* i : Output signal */
+ const int16_t output_frame, /* i : Output frame length */
+ const int16_t tdm_ratio_idx /* i : TDM ratio index */
+);
void dtx_enc_init(
Encoder_State *st, /* i : Encoder state handle */
const int16_t var_SID_rate_flag, /* i : flag for variable SID update rate */
diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h
index c070332087e9b838a2618ba88feb19e62f95a88d..2189501baad1f8c102ad65000aa28b64e477bae8 100644
--- a/lib_com/ivas_prot_fx.h
+++ b/lib_com/ivas_prot_fx.h
@@ -1501,4 +1501,12 @@ void ivas_hq_pred_hb_bws_fx(
const Word16 hqswb_clas, /* i : HQ SWB class */
const Word16 *SWB_fenv /* i : SWB frequency envelopes Q1 */
);
+
+void synchro_synthesis_fixed_clean(
+ const Word16 ivas_total_brate, /* i : IVAS total bitrate */
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *output_fx[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 */
+);
#endif
diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c
index e553375ee92e2fb5b887b58d5a84b4f1ba64ad6e..3cf9e08f1f2e4e87356973bbf75dae8282180e02 100644
--- a/lib_com/ivas_rom_com.c
+++ b/lib_com/ivas_rom_com.c
@@ -557,7 +557,18 @@ const float ica_sincInterp2[2*SINC_ORDER1+1] =
1.0f, 0.634114f,0.0f,-0.204776f, 0.0f, 0.115220f,0.0f,-0.074578f, 0.0f, 0.050649f,0.0f,-0.034727f,
0.0f, 0.023503f,0.0f,-0.015447f, 0.0f, 0.009735f,0.0f,-0.005865f, 0.0f, 0.003486f,0.0f,-0.002323f, 0.0f
};
-
+const Word32 ica_sincInterp2_fx[2 * SINC_ORDER1 + 1] =
+{
+ 0, -4988604, 0, 7486127, 0,
+-12594991, 0, 20905753, 0, -33172179, 0,
+50472307, 0, -74575663, 0, 108767895, 0,
+-160155039, 0, 247433071, 0, -439753119, 0,
+1361749503, 2147483647, 1361749503, 0, -439753119, 0,
+247433071, 0, -160155039, 0, 108767895, 0,
+-74575663, 0, 50472307, 0, -33172179, 0,
+20905753, 0, -12594991, 0, 7486127, 0,
+-4988604, 0
+};
const float ica_sincInterp4[2*SINC_ORDER1+1] =
{
0.0f,-0.003285f,-0.005537f,-0.004930f, 0.0f, 0.008295f, 0.015189f, 0.013767f, 0.0f,-0.021845f,-0.038282f,-0.033239f,
@@ -639,12 +650,13 @@ const float tdm_ratio_tabl[TDM_NQ+1] =
0.9045f, 0.9330f, 0.9568f, 0.9755f, 0.9891f, 1.0000f, 1.0000f, 1.0000f
};
-const Word16 tdm_ratio_tabl_fx[TDM_NQ+1] /*Q15*/=
-{
- 0 ,0 ,357 ,803 ,1416 ,2195 ,3129 ,4207 ,5420 ,6753 ,8192 ,9719 ,11321 ,12976 ,
- 14670 ,16384 ,18097 ,19791 ,21446 ,23048 ,24575 ,26014 ,27347 ,28560 ,29638 ,30572 ,31351 ,31964 ,
- 32410 ,32767 ,32767 ,32767 ,
-};
+const UWord32 tdm_ratio_tabl_fx[TDM_NQ + 1] =
+{ 0, 0, 23407572, 52613348, 92771296,
+143881408, 205084688, 275736896, 355193792, 442596384, 536870912,
+636943680, 741955584, 850403520, 961428416, 1073741824, 1186055168,
+1297080064, 1405528064, 1510540032, 1610612736, 1704887296, 1792289792,
+1871746688, 1942398976, 2003602304, 2054712320, 2094870272, 2124076032,
+2147483647, 2147483647, 2147483647 };
const float tdm_den_ratio_tabl[TDM_NQ+1] = /* 1.0f/(2*LR_ratio*LR_ratio-2*LR_ratio+1) */
{
@@ -654,6 +666,14 @@ const float tdm_den_ratio_tabl[TDM_NQ+1] = /* 1.0f/(2*LR_ratio*LR_ratio-2*LR_ra
1.2088f, 1.1429f, 1.0902f, 1.0501f, 1.0221f, 1.0000f, 1.0000f, 1.0000f
};
+const UWord32 tdm_den_ratio_tabl_fx[TDM_NQ + 1] =
+{ 1073741824, 1073741824, 1097471488, 1127536256, 1170593280,
+1227179520, 1297939072, 1383409024, 1483374336, 1596009856, 1717986944,
+1842648320, 1960330496, 2058470400, 2124290816, 2147483647, 2124290816,
+2058470400, 1960330496, 1842648320, 1717986944, 1596009856, 1483374336,
+1383409024, 1297939072, 1227179520, 1170593280, 1127536256, 1097471488,
+1073741824, 1073741824, 1073741824 };
+
const int16_t tdm_bit_allc_tbl[5][6] =
{
/* IC -- UC -- GC -- TM --AC */
diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h
index 846e9f9b6e36df5119cf150fbcad028794cb557a..584d925429614d6009fc415386343f16d3669e6c 100644
--- a/lib_com/ivas_rom_com.h
+++ b/lib_com/ivas_rom_com.h
@@ -87,6 +87,7 @@ extern const uint16_t ECSQ_tab_inverse[1 + ECSQ_SEGMENT_SIZE];
*----------------------------------------------------------------------------------*/
extern const float ica_sincInterp2[];
+extern const Word32 ica_sincInterp2_fx[];
extern const float ica_sincInterp4[];
extern const float ica_sincInterp6[];
@@ -104,8 +105,9 @@ extern const Word16 pow_10_icbwe_gsMappingDFT_tbl_fx[];
*----------------------------------------------------------------------------------*/
extern const float tdm_ratio_tabl[];
-extern const Word16 tdm_ratio_tabl_fx[];
+extern const UWord32 tdm_ratio_tabl_fx[TDM_NQ + 1];
extern const float tdm_den_ratio_tabl[];
+extern const UWord32 tdm_den_ratio_tabl_fx[];
extern const int16_t tdm_bit_allc_tbl[5][6];
/* LSFs Intra-frame prediction tables */
diff --git a/lib_com/ivas_stereo_ica_com_fx.c b/lib_com/ivas_stereo_ica_com_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..1e6c2bb84dff30c9cf55b2914ca09ce08f29399c
--- /dev/null
+++ b/lib_com/ivas_stereo_ica_com_fx.c
@@ -0,0 +1,383 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 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
+#include "options.h"
+#include "cnst.h"
+#include "ivas_cnst.h"
+#include "prot.h"
+#include "prot_fx1.h"
+#include "prot_fx2.h"
+#include "ivas_prot.h"
+#include "wmc_auto.h"
+#include "rom_com.h"
+#include "ivas_rom_com.h"
+
+/*---------------------------------------------------------------
+ * interpTargetChannel_fx()
+ *
+ * Target signal correction FOR shift variations.
+ * The pointer passsed into this function is assumed to be chanR/chanL + currNCShift.
+ * ---------------------------------------------------------------*/
+
+#define SPREAD_FACTOR1 ( 1.0f / INTERP_FACTOR1 )
+Word32 table_596[N_MAX_SHIFT_CHANGE + 1] = {
+ 0, 2441216, 1220608, 813738, 610304, 488243, 406869, 348745,
+ 305152, 271246, 244121, 221928, 203434, 187785, 174372, 162747,
+ 152576, 143600, 135623, 128485, 122060
+}; // Q21
+
+Word32 inv_table_596[N_MAX_SHIFT_CHANGE + 1] = {
+ 0, 7206320, 14412641, 21618962, 28825283, 36031605, 43237924, 50444244,
+ 57650567, 64856889, 72063211, 79269528, 86475849, 93682173, 100888489, 108094813,
+ 115301135, 122507459, 129713778, 136920096, 144126422
+}; // Q31
+Word32 tableD1_596[N_MAX_SHIFT_CHANGE + 1] = {
+ 0, 216, 1731, 5842, 13849, 27049, 46741, 74223,
+ 110794, 157752, 216396, 288023, 373932, 475422, 593791, 730337,
+ 886359, 1063155, 1262023, 1484262, 1731170
+}; // Q35
+
+
+Word32 table_298[N_MAX_SHIFT_CHANGE + 1] = {
+ 0, 1220608, 610304, 406869, 305152, 244121, 203434, 174372,
+ 152576, 135623, 122060, 110964, 101717, 93892, 87186, 81373,
+ 76288, 71800, 67811, 64242, 61030
+};
+Word32 inv_table_298[N_MAX_SHIFT_CHANGE + 1] = {
+ 0, 14412641, 28825283, 43237924, 57650567, 72063211, 86475849, 100888489,
+ 115301135, 129713778, 144126422, 158539056, 172951698, 187364347, 201776979, 216189627,
+ 230602270, 245014919, 259427557, 273840192, 288252845
+};
+Word32 tableD1_298[N_MAX_SHIFT_CHANGE + 1] = {
+ 0, 1731, 13849, 46741, 110794, 216396, 373932, 593791,
+ 886359, 1262023, 1731170, 2304187, 2991462, 3803381, 4750330, 5842699,
+ 7090873, 8505240, 10096185, 11874096, 13849363
+};
+
+
+Word32 table_290[N_MAX_SHIFT_CHANGE + 1] = {
+ 0, 1187840, 593920, 395946, 296960, 237568, 197973, 169691,
+ 148480, 131982, 118784, 107985, 98986, 91372, 84845, 79189,
+ 74240, 69872, 65991, 62517, 59392
+};
+Word32 inv_table_290[N_MAX_SHIFT_CHANGE + 1] = {
+ 0, 14810232, 29620464, 44430697, 59240928, 74051160, 88861394, 103671628,
+ 118481856, 133292091, 148102320, 162912554, 177722789, 192533022, 207343256, 222153473,
+ 236963712, 251773958, 266584183, 281394409, 296204640
+};
+Word32 tableD1_290[N_MAX_SHIFT_CHANGE + 1] = { 0, 1878, 15027, 50717, 120219, 234803, 405740, 644300,
+ 961755, 1369374, 1878428, 2500187, 3245924, 4126907, 5154407, 6339694,
+ 7694041, 9228719, 10954993, 12884138, 15027425 };
+
+
+Word32 table_145[N_MAX_SHIFT_CHANGE + 1] = {
+ 0, 593920, 296960, 197973, 148480, 118784, 98986, 84845,
+ 74240, 65991, 59392, 53992, 49493, 45686, 42422, 39594,
+ 37120, 34936, 32995, 31258, 29696
+};
+Word32 inv_table_145[N_MAX_SHIFT_CHANGE + 1] = {
+ 0, 29620464, 59240928, 88861394, 118481856, 148102320, 177722789, 207343256,
+ 236963712, 266584183, 296204640, 325825109, 355445578, 385066045, 414686513, 444306946,
+ 473927425, 503547916, 533168367, 562788819, 592409281
+};
+Word32 tableD1_145[N_MAX_SHIFT_CHANGE + 1] = { 0, 15027, 120219, 405740, 961755, 1878428, 3245924, 5154407,
+ 7694041, 10954993, 15027425, 20001503, 25967392, 33015256, 41235259, 50717555,
+ 61552334, 73829752, 87639951, 103073111, 120219402 };
+static void interpTargetChannel_fx(
+ Word32 *target_fx,
+ const Word16 prevShift,
+ const Word16 currShift,
+ const Word16 L_shift_adapt )
+{
+ Word16 i, j, k, /*m,*/ d, N, signShift, lim1, lim2;
+ const Word32 *win_fx;
+ Word32 *ptr1_fx, *ptr2_fx;
+ Word32 tempBuff1_fx[INTERP_FACTOR1 * ( L_SHIFT_ADAPT_MAX + 2 * N_MAX_SHIFT_CHANGE + 2 )], tempBuff2_fx[L_SHIFT_ADAPT_MAX - 1];
+ Word16 temp_int;
+ Word32 x_fx[4], y_fx[4], tempF_fx, tempF1_fx;
+ Word32 interp_factor2_fx, factor_fx;
+ Word32 spread_factor2_fx;
+ Word64 tempD1_fx, tempD2_fx;
+
+ d = -( currShift - prevShift );
+ signShift = ( d >= 0 ) ? ( 1 ) : ( -1 );
+
+ IF( d == 0 )
+ {
+ /* this can happen in DFT->TD switching */
+ return;
+ }
+
+ N = L_shift_adapt;
+ Word32 *table_pointer = NULL;
+ Word32 *inv_table_pointer = NULL;
+ Word32 *table_D1_pointer = NULL;
+ SWITCH( N )
+ {
+ case 596:
+ table_pointer = table_596;
+ inv_table_pointer = inv_table_596;
+ table_D1_pointer = tableD1_596;
+ break;
+ case 298:
+ table_pointer = table_298;
+ inv_table_pointer = inv_table_298;
+ table_D1_pointer = tableD1_298;
+ break;
+ case 290:
+ table_pointer = table_290;
+ inv_table_pointer = inv_table_290;
+ table_D1_pointer = tableD1_290;
+ break;
+ case 145:
+ table_pointer = table_145;
+ inv_table_pointer = inv_table_145;
+ table_D1_pointer = tableD1_145;
+ break;
+ default:
+ assert( 0 );
+ }
+
+ factor_fx = table_pointer[L_abs( d )];
+ interp_factor2_fx = L_shr( factor_fx, 1 );
+ spread_factor2_fx = inv_table_pointer[L_abs( d )];
+
+ /* start from (target - N - d + 1) : (extra lag = step1) :to: (target - 1 - d) : (extra lag = d) */
+ /* sinc interp by a factor of 2 */
+
+ win_fx = ica_sincInterp2_fx + SINC_ORDER1;
+ ptr1_fx = target_fx;
+ ptr2_fx = tempBuff1_fx + ( N_MAX_SHIFT_CHANGE + 1 ) * INTERP_FACTOR1;
+
+ FOR( i = -( N_MAX_SHIFT_CHANGE + 1 ) * INTERP_FACTOR1; i < ( N + N_MAX_SHIFT_CHANGE + 1 ) * INTERP_FACTOR1; i++ )
+ {
+ IF( i & 0x1 )
+ {
+ ptr2_fx[i] = 0;
+ /* lim1 = ceil((i - SINC_ORDER1)*SPREAD_FACTOR1); */
+ /* lim2 = floor((i + SINC_ORDER1)*SPREAD_FACTOR1); */
+ temp_int = shr( ( i - SINC_ORDER1 ), 1 );
+ tempF_fx = ( i - SINC_ORDER1 ) % 2; //*SPREAD_FACTOR1
+ lim1 = (Word16) ( temp_int );
+ IF( tempF_fx == 1 )
+ {
+ lim1++;
+ }
+ tempF_fx = ( i + SINC_ORDER1 ) % 2; //*SPREAD_FACTOR1
+ temp_int = shr( ( i + SINC_ORDER1 ), 1 ); //*SPREAD_FACTOR1
+ lim2 = (Word16) ( temp_int );
+ IF( tempF_fx == -1 )
+ {
+ lim2--;
+ }
+ FOR( j = lim1; j <= lim2; j++ )
+ {
+ ptr2_fx[i] = L_add( Mpy_32_32( win_fx[j * INTERP_FACTOR1 - i], ptr1_fx[j] ), ptr2_fx[i] );
+ }
+ }
+ ELSE
+ {
+ ptr2_fx[i] = ptr1_fx[shr( i, 1 )];
+ }
+ }
+
+ /* cubic spline interp */
+ ptr1_fx = ptr2_fx;
+ ptr2_fx = tempBuff2_fx;
+
+ ;
+ tempD1_fx = table_D1_pointer[L_abs( d )];
+ tempD2_fx = 3 * table_D1_pointer[L_abs( d )];
+
+ tempF1_fx = L_sub( d * factor_fx, ( signShift == 1 ? ONE_IN_Q12 : -( ONE_IN_Q12 ) ) );
+ FOR( k = 0; k < N - 1; k++ )
+ {
+ Word32 local = ( ( (Word64) tempF1_fx * spread_factor2_fx ) >> 31 ) - ONE_IN_Q12;
+ Word32 sign_local = local > 0 ? 1 : -1;
+ Word32 local_int = (Word32) W_shr( W_abs( local ), 12 );
+ Word32 res_a1, res_a2, res_a3;
+ Word32 res_b1, res_b2, res_b3;
+ Word32 res_c1, res_c2, res_c3;
+ Word32 res_d1, res_d2, res_d3;
+ Word64 local_int_scaled;
+ Word64 res_a, res_b, res_c, res_d;
+ Word64 tempa, tempb;
+ Word64 mult_a_D1, mult_b_D2;
+ local_int = sign_local * local_int;
+ local_int_scaled = local_int << 12;
+ lim1 = (Word16) local_int;
+ IF( local_int_scaled > local )
+ {
+ lim1--;
+ }
+
+ y_fx[0] = ptr1_fx[lim1];
+ y_fx[1] = ptr1_fx[lim1 + 1];
+ y_fx[2] = ptr1_fx[lim1 + 2];
+ y_fx[3] = ptr1_fx[lim1 + 3];
+
+ x_fx[0] = lim1 * interp_factor2_fx;
+ x_fx[1] = L_add( x_fx[0], interp_factor2_fx );
+ x_fx[2] = L_add( x_fx[1], interp_factor2_fx );
+ x_fx[3] = L_add( x_fx[2], interp_factor2_fx );
+
+
+ res_a1 = ( tempF1_fx - x_fx[0] );
+ res_a2 = ( tempF1_fx - x_fx[1] );
+ res_a3 = ( tempF1_fx - x_fx[2] );
+ res_a = ( ( (Word64) res_a1 * res_a2 ) >> 12 ) * res_a3;
+ res_a = ( y_fx[3] * ( res_a >> 16 ) );
+
+ res_b1 = ( tempF1_fx - x_fx[1] );
+ res_b2 = ( tempF1_fx - x_fx[2] );
+ res_b3 = ( tempF1_fx - x_fx[3] );
+ res_b = ( ( (Word64) res_b1 * res_b2 ) >> 12 ) * res_b3;
+ res_b = ( y_fx[0] * ( res_b >> 16 ) );
+
+ res_c1 = ( tempF1_fx - x_fx[0] );
+ res_c2 = ( tempF1_fx - x_fx[2] );
+ res_c3 = ( tempF1_fx - x_fx[3] );
+ res_c = ( ( (Word64) res_c1 * res_c2 ) >> 12 ) * res_c3;
+ res_c = ( y_fx[1] * ( res_c >> 16 ) );
+
+ res_d1 = ( tempF1_fx - x_fx[0] );
+ res_d2 = ( tempF1_fx - x_fx[1] );
+ res_d3 = ( tempF1_fx - x_fx[3] );
+ res_d = ( ( (Word64) res_d1 * res_d2 ) >> 12 ) * res_d3;
+ res_d = ( y_fx[2] * ( res_d >> 16 ) );
+
+
+ tempa = res_a - res_b;
+ tempb = res_c - res_d;
+
+ mult_a_D1 = ( tempD1_fx * ( tempa >> 14 ) ) >> 15;
+ mult_b_D2 = ( tempD2_fx * ( tempb >> 14 ) ) >> 15;
+ ptr2_fx[k] = (Word32) ( ( mult_a_D1 + mult_b_D2 ) >> 14 ); // 38-14
+ tempF1_fx = (Word32) W_add( tempF1_fx, L_sub( factor_fx, ( signShift == 1 ? ONE_IN_Q12 : -( ONE_IN_Q12 ) ) ) );
+ }
+ ptr1_fx = target_fx;
+ Copy32( ptr2_fx, ptr1_fx, N - 1 );
+
+ return;
+}
+
+
+/*---------------------------------------------------------------
+ * Function targetCh_AlignStereoDFT()
+ *
+ * Align target channel in DFT stereo to correct FOR shift variations
+ * ---------------------------------------------------------------*/
+
+static void targetCh_AlignStereoDFT_fx(
+ Word32 *target_fx,
+ const Word16 prevShift,
+ const Word16 currShift,
+ const Word16 L_shift_adapt )
+{
+ Word16 i;
+ Word32 winSlope_fx, alpha_fx;
+ Word16 d;
+
+ Word32 fadeOutBuff_fx[L_SHIFT_ADAPT_MAX];
+ Word32 fadeInBuff_fx[L_SHIFT_ADAPT_MAX];
+
+ d = -( currShift - prevShift );
+
+ Copy32( target_fx + d, fadeOutBuff_fx, L_shift_adapt );
+ Copy32( target_fx, fadeInBuff_fx, L_shift_adapt );
+
+ IF( L_shift_adapt > 0 )
+ {
+ alpha_fx = 0;
+ SWITCH( L_shift_adapt )
+ {
+ case 596:
+ winSlope_fx = 3603160;
+ break;
+ case 298:
+ winSlope_fx = 7206320;
+ break;
+ case 290:
+ winSlope_fx = 7405116;
+ break;
+ case 145:
+ winSlope_fx = 14810232;
+ break;
+ default:
+ winSlope_fx = ONE_IN_Q31;
+ break;
+ }
+ FOR( i = 0; i < L_shift_adapt; i++ )
+ {
+ target_fx[i] = L_add( Mpy_32_32( alpha_fx, fadeInBuff_fx[i] ), Mpy_32_32( L_sub( ONE_IN_Q31, alpha_fx ), fadeOutBuff_fx[i] ) );
+
+ alpha_fx = L_add_sat( alpha_fx, winSlope_fx );
+ }
+ }
+ ELSE
+ {
+ Copy32( fadeInBuff_fx, target_fx, L_shift_adapt );
+ }
+
+ return;
+}
+
+
+/*---------------------------------------------------------------
+ * adjustTargetSignal()
+ *
+ * Target signal correction FOR shift variations.
+ * ---------------------------------------------------------------*/
+
+void adjustTargetSignal_fx(
+ Word32 *target_fx,
+ const Word16 prevShift,
+ const Word16 currShift,
+ const Word16 L_shift_adapt,
+ const Word16 method )
+{
+ /* inter-frame shift variation and target shifting */
+
+ IF( method == 0 )
+ {
+ interpTargetChannel_fx( target_fx, prevShift, currShift, L_shift_adapt );
+ }
+ ELSE
+ {
+ targetCh_AlignStereoDFT_fx( target_fx, prevShift, currShift, L_shift_adapt );
+ }
+
+ return;
+}
diff --git a/lib_dec/hq_core_dec.c b/lib_dec/hq_core_dec.c
index 4299340c85186378262e9dfe7d24121358de5e6f..aee3c0a70e51e13e0c44caf3abb11eb9405fcc6f 100644
--- a/lib_dec/hq_core_dec.c
+++ b/lib_dec/hq_core_dec.c
@@ -83,7 +83,9 @@ void hq_core_dec(
int16_t index, left_rect, tcx_offsetFB, overlapFB, L_frameTCX;
int16_t tcx_offset, overlap, L_frame, L_spec, fscaleFB;
int16_t L_frameTCX_glob, L_frame_glob;
+#ifndef IVAS_FLOAT_FIXED
float acelp_zir[L_FRAME_MAX / 2];
+#endif
int16_t encoderLookahead, encoderLookaheadFB;
int16_t hq_recovery_flag;
int16_t mdctWindowLength;
diff --git a/lib_dec/ivas_cpe_dec.c b/lib_dec/ivas_cpe_dec.c
index 3e337fa43b636ccd7cf904186ae141fa93230739..950656ab9d4d617efa27dd92e732214ae99e6ad1 100644
--- a/lib_dec/ivas_cpe_dec.c
+++ b/lib_dec/ivas_cpe_dec.c
@@ -492,7 +492,6 @@ 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 eba7538315e343ca90adf97f8c525623559461f9..e938701b3db371267ea3962a0b8f735035c2c610 100644
--- a/lib_dec/ivas_cpe_dec_fx.c
+++ b/lib_dec/ivas_cpe_dec_fx.c
@@ -80,6 +80,8 @@ ivas_error ivas_cpe_dec_fx(
float *output_flt[CPE_CHANNELS];
float outputHB[CPE_CHANNELS][L_FRAME48k]; /* 'float' buffer for output HB synthesis, both channels */
float res_buf[STEREO_DFT_N_8k];
+ Word32 outputHB_fx[CPE_CHANNELS][L_FRAME48k]; /* buffer for output HB synthesis, both channels */
+ Word32 res_buf_fx[STEREO_DFT_N_8k];
#else
Word32 outputHB_fx[CPE_CHANNELS][L_FRAME48k]; /* buffer for output HB synthesis, both channels */
Word32 res_buf_fx[STEREO_DFT_N_8k];
@@ -452,7 +454,13 @@ ivas_error ivas_cpe_dec_fx(
/*----------------------------------------------------------------*
* Stereo decoder & upmixing
*----------------------------------------------------------------*/
-
+ for (int j = 0; j < output_frame; j++)
+ {
+ output[0][j] = (Word32)(output_flt[0][j] * (1 << *q_output));
+ output[1][j] = (Word32)(output_flt[1][j] * (1 << *q_output));
+ outputHB_fx[0][j] = (Word32)(outputHB[0][j] * (1 << *q_output));
+ outputHB_fx[1][j] = (Word32)(outputHB[1][j] * (1 << *q_output));
+ }
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];
@@ -611,6 +619,15 @@ ivas_error ivas_cpe_dec_fx(
{
stereo_dft_dec_synthesize( hCPE, DFT, n, output_flt[n], output_frame );
}
+
+ //delete below
+ for (int j = 0; j < output_frame; j++)
+ {
+ output[0][j] = (Word32)(output_flt[0][j] * (1 << *q_output));
+ output[1][j] = (Word32)(output_flt[1][j] * (1 << *q_output));
+ outputHB_fx[0][j] = (Word32)(outputHB[0][j] * (1 << *q_output));
+ outputHB_fx[1][j] = (Word32)(outputHB[1][j] * (1 << *q_output));
+ }
}
ELSE IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) )
{
@@ -620,10 +637,11 @@ ivas_error ivas_cpe_dec_fx(
}
/* TD stereo upmixing */
- stereo_tdm_combine( hCPE, output_flt[0], output_flt[1], output_frame, 0, tdm_ratio_idx );
+ //stereo_tdm_combine( hCPE, output_flt[0], output_flt[1], output_frame, 0, tdm_ratio_idx );
+ stereo_tdm_combine_fx(hCPE, output[0], output[1], output_frame, 0, tdm_ratio_idx);
IF( sts[0]->tdm_LRTD_flag )
{
- stereo_tdm_combine( hCPE, outputHB[0], outputHB[1], output_frame, 1, tdm_ratio_idx );
+ stereo_tdm_combine_fx(hCPE, outputHB_fx[0], outputHB_fx[1], output_frame, 0, tdm_ratio_idx);
}
hCPE->hStereoCng->last_tdm_idx = hCPE->hStereoTD->tdm_last_ratio_idx;
@@ -633,34 +651,28 @@ ivas_error ivas_cpe_dec_fx(
{
/* Scale the Right channel with the gain */
stereo_tca_scale_R_channel( hCPE, output_flt[1], output_frame );
-#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED
- FOR( int k = 0; k < output_frame; k++ )
- {
- output[0][k] = (Word32) ( output_flt[0][k] * ( 1 << *q_output ) );
- output[1][k] = (Word32) ( output_flt[1][k] * ( 1 << *q_output ) );
- }
-#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED
+ //stereo_tca_scale_R_channel_fx(hCPE, output[1], output_frame);
/* stereo to mono downmix */
FOR( i = 0; i < output_frame; i++ )
{
output[0][i] = L_shr( L_add( output[0][i], output[1][i] ), 1 );
}
-
-#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED
- FOR( int k = 0; k < output_frame; k++ )
- {
- output_flt[0][k] = ( (float) output[0][k] / ( 1 << *q_output ) );
- output_flt[1][k] = ( (float) output[1][k] / ( 1 << *q_output ) );
- }
-#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED
}
}
/*----------------------------------------------------------------*
* Update parameters for stereo CNA
*----------------------------------------------------------------*/
+ //Delete below
+ IF(hCPE->hStereoDft != NULL)
+ {
+ Word16 q_td_gain = Q_factor_arr(hCPE->hStereoDft->td_gain, STEREO_DFT_CORE_HIST_MAX);
+ floatToFixed_arrL(hCPE->hStereoDft->td_gain, hCPE->hStereoDft->td_gain_fx, q_td_gain, STEREO_DFT_CORE_HIST_MAX); // Checking this.
+ }
+ //////Till here
- stereo_cna_update_params( hCPE, output_flt, output_frame, tdm_ratio_idx );
+ //stereo_cna_update_params( hCPE, output_flt, output_frame, tdm_ratio_idx );
+ stereo_cna_update_params_fx( hCPE, output, output_frame, tdm_ratio_idx );
/*----------------------------------------------------------------*
* Synthesis synchronization between CPE modes
@@ -668,61 +680,35 @@ ivas_error ivas_cpe_dec_fx(
IF( !st_ivas->sba_dirac_stereo_flag )
{
- synchro_synthesis( ivas_total_brate, hCPE, output_flt, output_frame, 0 );
+ synchro_synthesis_fixed_clean( ivas_total_brate, hCPE, output, output_frame, 0 );
}
IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) && EQ_16( hCPE->nchan_out, 1 ) && ( EQ_16( is_DTXrate( ivas_total_brate ), 0 ) || ( EQ_16( is_DTXrate( ivas_total_brate ), 1 ) && EQ_16( is_DTXrate( st_ivas->hDecoderConfig->last_ivas_total_brate ), 0 ) ) ) )
{
- applyDmxMdctStereo( hCPE, output_flt, output_frame );
+ applyDmxMdctStereo_fx( hCPE, output, output_frame );
}
/*----------------------------------------------------------------*
* IC-BWE: output LB and HB mix in ACELP mode
*----------------------------------------------------------------*/
-#ifdef IVAS_FLOAT_FIXED
- Word32 *output_fx[CPE_CHANNELS];
- Word32 outputHB_fx[CPE_CHANNELS][L_FRAME48k];
- Word16 q_output_HB = 11;
- FOR(Word16 j = 0; j < CPE_CHANNELS; j++)
- {
- output_fx[j] = (Word32 *)malloc(output_frame * sizeof(Word32));
- floatToFixed_arrL(output_flt[j], output_fx[j], *q_output, output_frame);
- floatToFixed_arrL(outputHB[j], outputHB_fx[j], *q_output, output_frame);
- }
+ stereo_icBWE_decproc_fx(hCPE, output, outputHB_fx, last_core, last_bwidth, output_frame);
- IF (hCPE->hStereoDft != NULL)
- {
- Word16 q_td_gain = Q_factor_arr(hCPE->hStereoDft->td_gain, STEREO_DFT_CORE_HIST_MAX);
- floatToFixed_arrL(hCPE->hStereoDft->td_gain, hCPE->hStereoDft->td_gain_fx, q_td_gain, STEREO_DFT_CORE_HIST_MAX); // Checking this.
- }
+ smooth_dft2td_transition_fx( hCPE, output, output_frame );
+
+ /*----------------------------------------------------------------*
+ * Temporal ICA, stereo adjustment and upmix
+ *----------------------------------------------------------------*/
- stereo_icBWE_decproc_fx(hCPE, output_fx, outputHB_fx, last_core, last_bwidth, output_frame);
+ stereo_tca_dec_fx(hCPE, output, output_frame);
- IF (hCPE->hStereoDft != NULL)
+ //delete below
+ IF(hCPE->hStereoDft != NULL)
{
Word16 q_td_gain = Q_factor_arr(hCPE->hStereoDft->td_gain, STEREO_DFT_CORE_HIST_MAX);
fixedToFloat_arrL(hCPE->hStereoDft->td_gain_fx, hCPE->hStereoDft->td_gain, q_td_gain, STEREO_DFT_CORE_HIST_MAX); // Checking this.
}
- FOR(Word16 j = 0; j < CPE_CHANNELS; j++)
- {
- fixedToFloat_arrL(output_fx[j], output_flt[j], q_output_HB, output_frame);
- fixedToFloat_arrL(outputHB_fx[j], outputHB[j], q_output_HB, output_frame);
- free(output_fx[j]);
- }
-#else
- stereo_icBWE_decproc(hCPE, output_flt, outputHB, last_core, last_bwidth, output_frame);
-#endif
-
- smooth_dft2td_transition( hCPE, output_flt, output_frame );
-
- /*----------------------------------------------------------------*
- * Temporal ICA, stereo adjustment and upmix
- *----------------------------------------------------------------*/
-
- stereo_tca_dec(hCPE, output_flt, output_frame);
-
/*----------------------------------------------------------------*
* Common Stereo updates
*----------------------------------------------------------------*/
@@ -744,11 +730,6 @@ ivas_error ivas_cpe_dec_fx(
st_ivas->BER_detect = s_or( st_ivas->BER_detect, sts[1]->BER_detect );
#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED
- FOR( int k = 0; k < L_FRAME48k; k++ )
- {
- output[0][k] = (Word32) ( output_flt[0][k] * ( 1 << *q_output ) );
- output[1][k] = (Word32) ( output_flt[1][k] * ( 1 << *q_output ) );
- }
free( output_flt[0] );
free( output_flt[1] );
#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED
@@ -1083,7 +1064,7 @@ ivas_error create_cpe_dec(
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD Stereo\n" ) );
}
- stereo_td_init_dec( hCPE->hStereoTD, hCPE->last_element_mode );
+ stereo_td_init_dec_fx( hCPE->hStereoTD, hCPE->last_element_mode );
}
/*-----------------------------------------------------------------*
diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c
index e741b2fa8809b8434abf3e26da665da0bea6754b..70b7f1dc23b48f40c6d405e5e551fd34f145c1ac 100644
--- a/lib_dec/ivas_mct_dec.c
+++ b/lib_dec/ivas_mct_dec.c
@@ -498,7 +498,14 @@ ivas_error ivas_mct_dec(
/* synthesis synchronization between stereo modes */
if ( !st_ivas->sba_dirac_stereo_flag || ( st_ivas->ivas_format == SBA_ISM_FORMAT && cpe_id < nCPE - 2 ) )
{
- synchro_synthesis( ivas_total_brate, hCPE, output + cpe_id * CPE_CHANNELS, output_frame, 0 );
+#ifdef IVAS_FLOAT_FIXED
+ synchro_synthesis_fixed( ivas_total_brate, hCPE, output + cpe_id * CPE_CHANNELS, output_frame, 0 );
+#else
+ synchro_synthesis( ivas_total_brate, hCPE, output + cpe_id * CPE_CHANNELS, output_frame, 0 );
+#endif
+
+ //Todo use below once input is fixed not done due to complication in pointer
+ //synchro_synthesis_fixed_clean( ivas_total_brate, hCPE, output + cpe_id * CPE_CHANNELS, output_frame, 0 );
}
}
diff --git a/lib_dec/ivas_mono_dmx_renderer.c b/lib_dec/ivas_mono_dmx_renderer.c
index 774f7c153a7ac8b683fc64e6d1aabd9a4b24858a..91e65b52cbac41a21e77515dab232fa6cb2d15c9 100644
--- a/lib_dec/ivas_mono_dmx_renderer.c
+++ b/lib_dec/ivas_mono_dmx_renderer.c
@@ -409,8 +409,8 @@ void ivas_mono_stereo_downmix_mcmasa_fx(
/* Dowmix center channel to L and R */
if ( st_ivas->hDecoderConfig->nchan_out == 2 && st_ivas->hOutSetup.separateChannelEnabled )
{
- v_multc_acc_32_16( output_f_fx[st_ivas->hOutSetup.separateChannelIndex], INV_SQRT2_FX, output_f_fx[0], output_frame );
- v_multc_acc_32_16( output_f_fx[st_ivas->hOutSetup.separateChannelIndex], INV_SQRT2_FX, output_f_fx[1], output_frame );
+ v_multc_acc_32_16( output_f_fx[st_ivas->hOutSetup.separateChannelIndex], INV_SQRT2_FX_Q15, output_f_fx[0], output_frame );
+ v_multc_acc_32_16( output_f_fx[st_ivas->hOutSetup.separateChannelIndex], INV_SQRT2_FX_Q15, output_f_fx[1], output_frame );
}
/* Mono downmix */
else if ( st_ivas->hDecoderConfig->nchan_out == 1 )
@@ -418,7 +418,7 @@ void ivas_mono_stereo_downmix_mcmasa_fx(
/* Downmix L and R to dmx_tmp */
for ( i = 0; i < st_ivas->nchan_transport; i++ )
{
- v_multc_acc_32_16( output_f_fx[i], INV_SQRT2_FX, dmx_tmp_fx, output_frame );
+ v_multc_acc_32_16( output_f_fx[i], INV_SQRT2_FX_Q15, dmx_tmp_fx, output_frame );
}
/* Add center channel */
if ( st_ivas->hOutSetup.separateChannelEnabled )
diff --git a/lib_dec/ivas_sba_dirac_stereo_dec.c b/lib_dec/ivas_sba_dirac_stereo_dec.c
index f8bdb85ec9b4b801acdceafd0b92192e7553a05b..4781d50bf4a7fce2907254ca3bcbda8056093950 100644
--- a/lib_dec/ivas_sba_dirac_stereo_dec.c
+++ b/lib_dec/ivas_sba_dirac_stereo_dec.c
@@ -1007,8 +1007,14 @@ void ivas_sba_dirac_stereo_dec(
{
stereo_dft_dec_synthesize( hCPE, DFT, 1, output[1], output_frame );
}
-
+#ifdef IVAS_FLOAT_FIXED
+ synchro_synthesis_fixed( st_ivas->hDecoderConfig->ivas_total_brate, hCPE, output, output_frame, 1 /*st_ivas->sba_dirac_stereo_flag*/ );
+#else
synchro_synthesis( st_ivas->hDecoderConfig->ivas_total_brate, hCPE, output, output_frame, 1 /*st_ivas->sba_dirac_stereo_flag*/ );
+#endif
+
+ //Todo use below once input is fixed not done due to complication in pointer
+ //synchro_synthesis_fixed_clean( st_ivas->hDecoderConfig->ivas_total_brate, hCPE, output, output_frame, 1 /*st_ivas->sba_dirac_stereo_flag*/ );
/* output scaling */
if ( !sba_mono_flag )
diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h
index 00b8868c8b07de5a4cf24a714c50932e10c46bf4..8277e7386ae3417af661e0b796ac1c0bd741b139 100644
--- a/lib_dec/ivas_stat_dec.h
+++ b/lib_dec/ivas_stat_dec.h
@@ -362,6 +362,7 @@ typedef struct stereo_dec_cng
int16_t prev_sid_nodata; /* previous frame SID/FRAME_NO_DATA indicator */
int16_t last_tdm_idx; /* last tdm index */
float c_LR_LT; /* left right cross correlation */
+ Word32 c_LR_LT_fx; /* left right cross correlation */
int16_t active_frame_counter; /* counter for active frames */
int16_t xfade_frame_counter; /* xfade counter */
int16_t xfade_length; /* number of frames to perform xfade */
@@ -402,10 +403,14 @@ typedef struct stereo_td_dec_data_structure
int16_t flag_skip_DMX; /* flag that indicates whether the TD downmixing is skipped */
float TCX_old_syn_Overl[L_FRAME16k / 2]; /* past ovrl buffer for possible switching from TD stereo ACELP to MDCT stereo TCX frame */
+ Word32 TCX_old_syn_Overl_fx[L_FRAME16k / 2]; /* past ovrl buffer for possible switching from TD stereo ACELP to MDCT stereo TCX frame */
float prevSP_ratio; /* previous SP ratio */
+ Word32 prevSP_ratio_fx; /* previous SP ratio */
float SP_ratio_LT; /* longterm SP ratio */
+ Word32 SP_ratio_LT_fx; /* longterm SP ratio */
float c_LR_LT; /* left-right cross-correlation */
+ Word32 c_LR_LT_fx; /* left-right cross-correlation */
} STEREO_TD_DEC_DATA, *STEREO_TD_DEC_DATA_HANDLE;
@@ -464,7 +469,7 @@ typedef struct stereo_tca_dec_data_structure
float prevTargetGain; /* gain norm applied on target (or right) channel in previous frame */
#ifdef IVAS_FLOAT_FIXED
Word32 targetGain_fx; // Q29
- Word16 prevTargetGain_fx; // Q14
+ Word32 prevTargetGain_fx; // Q29
#endif
int16_t corrLagStats; /* corr lag stats in current frame */
@@ -950,7 +955,7 @@ typedef struct cpe_dec_data_structure
float *prev_synth_chs[CPE_CHANNELS];
#ifdef IVAS_FLOAT_FIXED
- Word32 lt_es_em_fx;
+ Word32 lt_es_em_fx;//24
Word32 prev_hb_synth_fx[CPE_CHANNELS][NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS )];
Word32 prev_synth_fx[CPE_CHANNELS][NS2SA( 48000, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS )];
diff --git a/lib_dec/ivas_stereo_cng_dec.c b/lib_dec/ivas_stereo_cng_dec.c
index 5005ea295de6adabc60bed4da0a873793bca640e..85077f96c60f24eaf04ca3378bb0e861e7a1e5b7 100644
--- a/lib_dec/ivas_stereo_cng_dec.c
+++ b/lib_dec/ivas_stereo_cng_dec.c
@@ -54,6 +54,7 @@
/* DTX/CNG */
#define MAX_K 50.0f
#define STEREO_TD_PS_CORR_FILT 0.8f
+#define STEREO_TD_PS_CORR_FILT_FX 1717986918
#define STEREO_TD_PS_CORR_FILT_Q31 1717986944
#define ONE_MINUS_STEREO_TD_PS_CORR_FILT_Q31 429496704
#define MAX_XFADE 50.0f
@@ -61,7 +62,9 @@
#define CORR_INIT 8
#define SID_INIT 6
#define STEREO_CNA_LR_CORR_LT_FILT 0.95f /* long-term averaging factor for L/R correlation estimation in stereo CNA */
+#define STEREO_CNA_LR_CORR_LT_FILT_FX 2040109440 /* long-term averaging factor for L/R correlation estimation in stereo CNA */
#define STEREO_CNA_ILD_LT_FILT 0.9f /* long-term averaging factor for ILD estimation in stereo CNA */
+#define STEREO_CNA_ILD_LT_FILT_FX 1932735283 /* long-term averaging factor for ILD estimation in stereo CNA */
#define STEREO_CNA_SOFT_VAD_UP 0.7f /* long-term averaging factor for upward soft VAD update in stereo CNA */
#define STEREO_CNA_SOFT_VAD_DN 0.95f /* long-term averaging factor for downward soft VAD update in stereo CNA */
@@ -699,39 +702,39 @@ void stereo_dtf_cng(
*-------------------------------------------------------------------*/
void stereo_cng_dec_update(
- CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
- const int32_t ivas_total_brate /* i : IVAS total bitrate */
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ const Word32 ivas_total_brate /* i : IVAS total bitrate */
)
{
- if ( hCPE->hCoreCoder[0]->core_brate > SID_2k40 )
+ IF( hCPE->hCoreCoder[0]->core_brate > SID_2k40 )
{
hCPE->hStereoCng->last_act_element_mode = hCPE->element_mode;
- if ( hCPE->hStereoCng->active_frame_counter > SKIP_XFADE_FRAMES )
+ IF( hCPE->hStereoCng->active_frame_counter > SKIP_XFADE_FRAMES )
{
hCPE->hStereoCng->xfade_frame_counter = 0;
hCPE->hStereoCng->xfade_length = 0;
}
- if ( hCPE->hStereoCng->active_frame_counter < MAX_FRAME_COUNTER )
+ IF( hCPE->hStereoCng->active_frame_counter < MAX_FRAME_COUNTER )
{
hCPE->hStereoCng->active_frame_counter++;
}
}
- else
+ ELSE
{
hCPE->hStereoCng->active_frame_counter = 0;
- if ( hCPE->hStereoCng->xfade_frame_counter < MAX_FRAME_COUNTER )
+ IF( hCPE->hStereoCng->xfade_frame_counter < MAX_FRAME_COUNTER )
{
hCPE->hStereoCng->xfade_frame_counter++;
}
}
- if ( hCPE->element_mode == IVAS_CPE_DFT )
+ IF( hCPE->element_mode == IVAS_CPE_DFT )
{
- if ( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA )
+ IF( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA )
{
hCPE->hStereoCng->prev_sid_nodata = 1;
}
- else
+ ELSE
{
hCPE->hStereoCng->prev_sid_nodata = 0;
}
@@ -943,6 +946,176 @@ static void stereo_cng_compute_LRcorr(
return;
}
+static void stereo_cng_compute_LRcorr_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE handle */
+ Word32 *output_fx[CPE_CHANNELS], /* i : Output signal */
+ const int16_t output_frame, /* i : Output frame length */
+ const int16_t tdm_ratio_idx /* i : TDM ratio index */
+)
+{
+ Word16 i;
+ Word32 c_LR_fx, c_fx, tmp_fx, sc_fx;
+ Word16 c_q;
+ Word64 enrL_fx, enrR_fx, dotLR_fx;
+ Word32 beta_fx;
+ Word16 enrL_q, enrR_q, dotLR_q;
+ Word16 enrL_inv_q, enrR_inv_q;
+ Word16 sc_q;
+ Word16 headroom_left_enrL, headroom_left_enrR, headroom_left_dotLR;
+ Word32 temp_x_inv, temp_y_inv, energy_xy_fx;
+ Word16 res_q;
+ Word32 numer_1, numer_2, numer_3, num;
+ Word16 numer_1_q, numer_2_q, numer_3_q, num_q;
+ Word32 denom_1, denom_2, denom_3, denom;
+ Word16 denom_1_q, denom_2_q, denom_3_q, denom_q;
+ Word32 beta_sqr, one_minus_beta_sqr;
+ beta_fx = tdm_ratio_tabl_fx[tdm_ratio_idx];
+
+ enrL_fx = 0;
+ enrR_fx = 0;
+ dotLR_fx = 0;
+
+ FOR( i = 0; i < output_frame; i++ )
+ {
+
+ enrL_fx += ( (Word64) output_fx[0][i] ) * ( output_fx[0][i] );
+ enrR_fx += ( (Word64) output_fx[1][i] ) * ( output_fx[1][i] );
+ dotLR_fx += ( ( (Word64) output_fx[0][i] ) * ( output_fx[1][i] ) );
+ }
+ dotLR_fx = dotLR_fx + EPSILON_FX_SMALL;
+ IF( dotLR_fx < 0 )
+ {
+ dotLR_fx = W_neg( dotLR_fx );
+ }
+ enrL_fx = enrL_fx + EPSILON_FX_SMALL;
+ enrR_fx = enrR_fx + EPSILON_FX_SMALL;
+
+ headroom_left_enrL = W_norm( enrL_fx );
+ headroom_left_enrR = W_norm( enrR_fx );
+
+ {
+
+ IF( headroom_left_enrL < 32 )
+ {
+ enrL_fx = W_shr( enrL_fx, ( 32 - headroom_left_enrL ) );
+ enrL_q = ( 31 - ( ( 2 * OUTPUT_Q ) - ( 32 - headroom_left_enrL ) ) );
+ }
+ ELSE
+ {
+ enrL_q = 31 - ( 2 * OUTPUT_Q );
+ }
+ IF( headroom_left_enrR < 32 )
+ {
+ enrR_fx = W_shr( enrR_fx, ( 32 - headroom_left_enrR ) );
+ enrR_q = ( 31 - ( ( 2 * OUTPUT_Q ) - ( 32 - headroom_left_enrR ) ) );
+ }
+ ELSE
+ {
+ enrR_q = 31 - ( 2 * OUTPUT_Q );
+ }
+
+ enrL_inv_q = enrL_q;
+ enrR_inv_q = enrR_q;
+
+ temp_x_inv = ISqrt32( (Word32) enrL_fx, &enrL_inv_q );
+ temp_y_inv = ISqrt32( (Word32) enrR_fx, &enrR_inv_q );
+ energy_xy_fx = Mpy_32_32( temp_x_inv, temp_y_inv );
+ res_q = enrL_inv_q + enrR_inv_q;
+ headroom_left_dotLR = W_norm( dotLR_fx );
+ dotLR_q = OUTPUT_Q * 2;
+ IF( headroom_left_dotLR < 32 )
+ {
+ dotLR_fx = W_shr( dotLR_fx, 32 - headroom_left_dotLR );
+ dotLR_q = dotLR_q - ( 32 - headroom_left_dotLR );
+ }
+ dotLR_fx = Mpy_32_32( (Word32) dotLR_fx, energy_xy_fx );
+ dotLR_q = dotLR_q + ( 31 - res_q ) - 31;
+ dotLR_fx = W_shl( dotLR_fx, 31 - dotLR_q );
+ }
+ c_LR_fx = extract_h( (Word32) dotLR_fx );
+
+ Word16 div_q = 0;
+ c_fx = BASOP_Util_Divide3232_Scale( (Word32) enrL_fx, (Word32) enrR_fx, &div_q );
+ c_q = 15 - div_q + ( enrR_q - enrL_q );
+
+ // to be delete
+ hCPE->hStereoCng->c_LR_LT = (float) hCPE->hStereoCng->c_LR_LT_fx / ( ONE_IN_Q31 );
+ hCPE->hStereoTD->c_LR_LT = (float) hCPE->hStereoTD->c_LR_LT_fx / ( ONE_IN_Q31 );
+
+ hCPE->hStereoTD->c_LR_LT_fx = L_add( Mpy_32_32( STEREO_TD_PS_CORR_FILT_FX, hCPE->hStereoTD->c_LR_LT_fx ),
+ Mpy_32_32( L_sub( ONE_IN_Q31, STEREO_TD_PS_CORR_FILT_FX ), L_deposit_h( (Word16) c_LR_fx ) ) );
+ hCPE->hStereoCng->c_LR_LT_fx = hCPE->hStereoTD->c_LR_LT_fx;
+
+ Word16 sqrt_q = 31 - c_q;
+ Word32 sqrt_res = Sqrt32( c_fx, &sqrt_q );
+ tmp_fx = Mpy_32_32( beta_fx, L_sub( ONE_IN_Q31, beta_fx ) );
+ tmp_fx = Mpy_32_32( tmp_fx, hCPE->hStereoTD->c_LR_LT_fx );
+ tmp_fx = Mpy_32_32( tmp_fx, sqrt_res );
+ Word16 tmp_q = ( 31 - sqrt_q ) - 1; // *2 handled with q reduction
+
+ beta_sqr = Mpy_32_32( beta_fx, beta_fx );
+ one_minus_beta_sqr = Mpy_32_32( L_sub( ONE_IN_Q31, beta_fx ), L_sub( ONE_IN_Q31, beta_fx ) );
+
+ numer_1 = Mpy_32_16_1( one_minus_beta_sqr, (Word16) c_fx ); // c_q+31-15
+ numer_1_q = c_q + 31 - 15;
+ numer_2 = beta_sqr; // 31
+ numer_2_q = 31;
+ numer_3 = tmp_fx; // tmp_q
+ numer_3_q = tmp_q;
+ num_q = 31;
+ num_q = num_q < numer_1_q ? num_q : numer_1_q;
+ num_q = num_q < numer_2_q ? num_q : numer_2_q;
+ num_q = num_q < numer_3_q ? num_q : numer_3_q;
+
+
+ denom_1 = Mpy_32_16_1( beta_sqr, (Word16) c_fx ); // c_q+31-15;
+ denom_1_q = c_q + 31 - 15;
+ denom_2 = one_minus_beta_sqr; // 31
+ denom_2_q = 31;
+ denom_3 = tmp_fx; // tmp_q
+ denom_3_q = tmp_q;
+ denom_q = 31;
+ denom_q = denom_q < denom_1_q ? denom_q : denom_1_q;
+ denom_q = denom_q < denom_2_q ? denom_q : denom_2_q;
+ denom_q = denom_q < denom_3_q ? denom_q : denom_3_q;
+
+ num = L_add( L_shr( numer_1, numer_1_q - num_q ), L_sub( L_shr( numer_2, numer_2_q - num_q ), L_shr( numer_3, numer_3_q - num_q ) ) ) + DELTA_FX;
+ denom = L_add( L_shr( denom_1, denom_1_q - denom_q ), L_add( L_shr( denom_2, denom_2_q - denom_q ), L_shr( denom_3, denom_3_q - denom_q ) ) ) + DELTA_FX;
+ Word16 q = 0;
+ sc_fx = BASOP_Util_Divide3232_Scale( num, denom, &q );
+ sc_q = 15 - ( num_q - denom_q ) - q;
+ Word32 sc_thr = L_shr( sc_fx, sc_q );
+ IF( sc_thr > 4 )
+ {
+ sc_fx = MAX_WORD16;
+ }
+ ELSE
+ {
+ sc_fx = L_shr( sc_fx, sc_q - 13 );
+ }
+ sqrt_q = 2;
+ sqrt_res = Sqrt32( L_shl_sat( sc_fx, 16 ), &sqrt_q );
+ IF( sqrt_q < 0 )
+ {
+ sqrt_res = L_shr( sqrt_res, -1 * sqrt_q );
+ sqrt_q = 0;
+ }
+ hCPE->hStereoTD->SP_ratio_LT_fx = L_add_sat( Mpy_32_32( 1932735283, hCPE->hStereoTD->SP_ratio_LT_fx ),
+ L_shl_sat( Mpy_32_32( 214748364, sqrt_res ), sqrt_q ) );
+
+ // to be deleted
+ hCPE->hStereoTD->SP_ratio_LT = (float) hCPE->hStereoTD->SP_ratio_LT_fx / ONE_IN_Q31;
+ IF( hCPE->hStereoCng->nr_corr_frames < CM_INIT )
+ {
+ hCPE->hStereoCng->nr_corr_frames++;
+ }
+
+ hCPE->hStereoCng->nr_dft_frames = 0;
+
+ return;
+}
+
+
/*-------------------------------------------------------------------*
* FindEmEs()
@@ -981,6 +1154,69 @@ static void FindEmEs(
return;
}
+static void FindEmEs_fx(
+ const Word32 *ch1_fx, /* i : Left channel */
+ const Word32 *ch2_fx, /* i : right channel */
+ const Word16 len, /* i : length */
+ Word32 *lt_es_em_fx /* i/o: LT energy ratio */
+)
+{
+ Word16 i;
+ Word32 mono_i_fx;
+ Word32 es_em_fx;
+ Word32 side_i_fx;
+ Word64 ener_fx, ener_side_fx;
+ Word16 headroom_left_ener_fx, headroom_left_ener_side_fx;
+ Word16 ener_q, ener_side_q;
+ ener_fx = 1;
+ ener_side_fx = 1;
+ Word32 square_res, log_res, division_res;
+ Word16 temp_q = 0;
+ for ( i = 0; i < len; i++ )
+ {
+ mono_i_fx = L_add( L_shr( ch1_fx[i], 1 ), L_shr( ch2_fx[i], 1 ) );
+ ener_fx = W_add( ener_fx, ( (Word64) mono_i_fx * mono_i_fx ) );
+ side_i_fx = L_sub( L_shr( ch1_fx[i], 1 ), L_shr( ch2_fx[i], 1 ) );
+ ener_side_fx = W_add( ener_side_fx, ( (Word64) side_i_fx * side_i_fx ) );
+ }
+ headroom_left_ener_fx = W_norm( ener_fx );
+ headroom_left_ener_side_fx = W_norm( ener_side_fx );
+
+ IF( headroom_left_ener_fx < 32 )
+ {
+ ener_fx = W_shr( ener_fx, ( 32 - headroom_left_ener_fx ) );
+ ener_q = ( ( 2 * OUTPUT_Q ) - ( 32 - headroom_left_ener_fx ) );
+ }
+ ELSE
+ {
+ ener_q = ( 2 * OUTPUT_Q );
+ }
+ IF( headroom_left_ener_side_fx < 32 )
+ {
+ ener_side_fx = W_shr( ener_side_fx, ( 32 - headroom_left_ener_side_fx ) );
+ ener_side_q = ( ( 2 * OUTPUT_Q ) - ( 32 - headroom_left_ener_side_fx ) );
+ }
+ ELSE
+ {
+ ener_side_q = ( 2 * OUTPUT_Q );
+ }
+
+ /**es_em = 10 * ( log10( sqrt( ener_side / len ) ) - log10( sqrt( ener / len ) ) ); */
+ division_res = BASOP_Util_Divide3232_Scale( (Word32) ener_side_fx, (Word32) ener_fx, &temp_q );
+ temp_q = temp_q - ( ener_side_q - ener_q );
+ square_res = Sqrt32( L_deposit_h( (Word16) division_res ), &temp_q );
+ IF( temp_q < 0 )
+ {
+ square_res = L_shr( square_res, -1 * temp_q );
+ temp_q = 0;
+ }
+ log_res = BASOP_Util_Log2( square_res );
+ es_em_fx = Mpy_32_32( log_res, 1616107501 ); // 25+30
+ /* long-term estimate */
+ *lt_es_em_fx = L_add( Mpy_32_32( 858993459, *lt_es_em_fx ), Mpy_32_32( 1288490188, es_em_fx ) );
+ return;
+}
+
/*-------------------------------------------------------------------*
* Function stereo_cna_update_params()
@@ -1097,8 +1333,216 @@ void stereo_cna_update_params(
return;
}
+#ifdef IVAS_FLOAT_FIXED
+void stereo_cna_update_params_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *output_fx[CPE_CHANNELS], /* i : Output signal */
+ const int16_t output_frame, /* i : Output frame length */
+ const int16_t tdm_ratio_idx /* i : TDM ratio index */
+)
+{
+ int16_t i;
+ Word64 enrL_fx, enrR_fx, dotLR_fx;
+ Word32 c_fx, c_LR_fx, c_ILD_fx;
+ Decoder_State **sts;
+ HANDLE_FD_CNG_DEC hFdCngDec;
+ Word16 dotLR_fx_q;
+ Word32 temp_x_inv, temp_y_inv, energy_xy_fx;
+ Word16 headroom_left_x, headroom_left_y;
+ Word16 headroom_left_dotLR_fx;
+ Word16 x_q, y_q, c_q;
+ Word16 x_inv_q, y_inv_q;
+ Word16 temp_res_q;
+ sts = hCPE->hCoreCoder;
+
+ hFdCngDec = sts[0]->hFdCngDec;
+
+ //delete below
+ hFdCngDec->cna_act_fact_fx = (Word16)(hFdCngDec->cna_act_fact * (1 << 15));
+ hFdCngDec->cna_LR_LT_fx = (Word16)(hFdCngDec->cna_LR_LT * (1 << 15));
+ hFdCngDec->cna_ILD_LT_fx = (Word16)(hFdCngDec->cna_ILD_LT * (1 << 15));
+ for (int idx = 0; idx < STEREO_DFT_BAND_MAX; idx++)
+ {
+ hFdCngDec->cna_g_state_fx[idx] = (Word16)(hFdCngDec->cna_g_state[idx] * (1 << 15));
+ hFdCngDec->cna_cm_fx[idx] = (Word16)(hFdCngDec->cna_cm[idx] * (1 << 15));
+ hCPE->lt_es_em_fx = (Word32)(hCPE->lt_es_em*(1 << 24));
+ }
+ /////
+
+
+ if ( hCPE->element_mode == IVAS_CPE_DFT )
+ {
+ if ( hCPE->nchan_out > 1 )
+ {
+ FindEmEs_fx(output_fx[0], output_fx[1], output_frame,&hCPE->lt_es_em_fx);
+ }
+ else
+ {
+ hCPE->lt_es_em_fx = 0;
+ }
+ }
+ else if ( hCPE->element_mode == IVAS_CPE_TD )
+ {
+ FindEmEs_fx(output_fx[0], output_fx[1], output_frame, &hCPE->lt_es_em_fx);
+
+
+ hCPE->hStereoCng->first_SID_after_TD = 1;
+ stereo_cng_compute_LRcorr_fx( hCPE, output_fx, output_frame, tdm_ratio_idx );
+ }
+ else
+ {
+ return;
+ }
+
+ enrL_fx = 0;
+ enrR_fx = 0;
+ dotLR_fx = 0;
+
+
+ if ( hCPE->element_mode == IVAS_CPE_TD || ( hCPE->element_mode == IVAS_CPE_DFT && sts[0]->core_brate > SID_2k40 && sts[0]->VAD == 0 ) )
+ {
+ if ( hCPE->nchan_out == 1 )
+ {
+ c_LR_fx = MAX_WORD16;
+ c_ILD_fx = 0;
+ }
+ else
+ {
+ FOR( i = 0; i < output_frame; i++ )
+ {
+
+ enrL_fx += ((Word64)output_fx[0][i] ) * ( output_fx[0][i] );
+ enrR_fx += ((Word64)output_fx[1][i] ) * ( output_fx[1][i] );
+ dotLR_fx += ( ((Word64)output_fx[0][i] ) * ( output_fx[1][i] ) );
+ }
+ dotLR_fx = dotLR_fx + EPSILON_FX_SMALL;
+ if (dotLR_fx < 0)
+ {
+ dotLR_fx = W_neg(dotLR_fx);
+ }
+ enrL_fx = enrL_fx + EPSILON_FX_SMALL;
+ enrR_fx = enrR_fx + EPSILON_FX_SMALL;
+ headroom_left_x = W_norm(enrL_fx);
+ headroom_left_y = W_norm(enrR_fx);
+
+ IF(headroom_left_x < 32)
+ {
+ enrL_fx = W_shr(enrL_fx, (32 - headroom_left_x));
+ x_q = (31 - ((2 * OUTPUT_Q) - (32 - headroom_left_x)));
+ }
+ ELSE
+ {
+ x_q = 31 - (2 * OUTPUT_Q);
+ }
+ IF(headroom_left_y < 32)
+ {
+ enrR_fx = W_shr(enrR_fx, (32 - headroom_left_y));
+ y_q = (31 - ((2 * OUTPUT_Q) - (32 - headroom_left_y)));
+ }
+ ELSE
+ {
+ y_q = 31 - (2 * OUTPUT_Q);
+ }
+
+ x_inv_q = x_q;
+ y_inv_q = y_q;
+
+ temp_x_inv = ISqrt32((Word32)enrL_fx, &x_inv_q);
+ temp_y_inv = ISqrt32((Word32)enrR_fx, &y_inv_q);
+ energy_xy_fx = Mpy_32_32(temp_x_inv, temp_y_inv);
+ temp_res_q = x_inv_q + y_inv_q;
+ headroom_left_dotLR_fx = W_norm(dotLR_fx);
+ dotLR_fx_q = OUTPUT_Q * 2;
+ IF(headroom_left_dotLR_fx < 32)
+ {
+ dotLR_fx = W_shr(dotLR_fx, 32 - headroom_left_dotLR_fx);
+ dotLR_fx_q = dotLR_fx_q - (32 - headroom_left_dotLR_fx);
+ }
+ dotLR_fx = Mpy_32_32((Word32)dotLR_fx, energy_xy_fx);
+ dotLR_fx_q = dotLR_fx_q + (31 - temp_res_q) - 31;
+ dotLR_fx = W_shl(dotLR_fx, 31 - dotLR_fx_q);
+ /* estimate L/R correlation factor and ILD in time domain */
+ c_LR_fx = extract_h((Word32)dotLR_fx);
+
+ temp_res_q = 0;
+ c_fx = BASOP_Util_Divide3232_Scale((Word32)enrL_fx, (Word32)enrR_fx, &temp_res_q);
+ c_q = 15 - temp_res_q + (y_q - x_q);
+
+ Word32 one_in_c_q = 1 << c_q;
+ Word32 num_c_fx = L_sub(c_fx, one_in_c_q);
+ Word32 denom_c_fx = L_add(c_fx, one_in_c_q);
+ Word16 num_c_headroom = norm_l(L_sub(c_fx, one_in_c_q));
+ Word16 denom_c_headroom = norm_l(L_add(c_fx, one_in_c_q));
+ Word16 min_headroom_left = num_c_headroom < denom_c_headroom ? num_c_headroom : denom_c_headroom;
+ temp_res_q = 0;
+ c_ILD_fx = BASOP_Util_Divide3232_Scale(L_shl_sat(num_c_fx, min_headroom_left), L_shl_sat(denom_c_fx, min_headroom_left), &temp_res_q);
+ if (temp_res_q < 0)
+ {
+ c_ILD_fx = L_shr(c_ILD_fx, -1 * temp_res_q);
+ }
+ }
+ /* update of long-term ILD and LR correlation factors for stereo CNA */
+ if ( !hFdCngDec->first_cna_noise_updated )
+ {
+ hFdCngDec->cna_LR_LT_fx = (Word16)c_LR_fx;
+ hFdCngDec->cna_ILD_LT_fx = (Word16)c_ILD_fx;
+ }
+ else
+ {
+ hFdCngDec->cna_LR_LT_fx = extract_h(L_add_sat(Mpy_32_16_1(STEREO_CNA_LR_CORR_LT_FILT_FX, hFdCngDec->cna_LR_LT_fx),
+ Mpy_32_16_1(L_sub( ONE_IN_Q31, STEREO_CNA_LR_CORR_LT_FILT_FX ), (Word16)c_LR_fx)));
+ hFdCngDec->cna_ILD_LT_fx = extract_h(L_add_sat(Mpy_32_16_1(STEREO_CNA_ILD_LT_FILT_FX, hFdCngDec->cna_ILD_LT_fx),
+ Mpy_32_16_1(L_sub(ONE_IN_Q31, STEREO_CNA_ILD_LT_FILT_FX ), (Word16)c_ILD_fx)));
+ }
+
+ set16_fx( hFdCngDec->cna_g_state_fx, hFdCngDec->cna_ILD_LT_fx, hFdCngDec->cna_nbands );
+ set16_fx( hFdCngDec->cna_cm_fx, hFdCngDec->cna_LR_LT_fx, hFdCngDec->cna_nbands );
+ }
+
+
+ /* Soft VAD for stereo CNA */
+ if ( hCPE->element_mode == IVAS_CPE_TD || hCPE->element_mode == IVAS_CPE_DFT )
+ {
+ if ( !hFdCngDec->first_cna_noise_updated )
+ {
+ hFdCngDec->cna_act_fact_fx = 0;
+ }
+ else
+ {
+ if ( hCPE->element_mode == IVAS_CPE_TD )
+ {
+ /* quickly decrease in TD stereo mode */
+ hFdCngDec->cna_act_fact_fx = extract_h( Mpy_32_16_1( 1503238553, hFdCngDec->cna_act_fact_fx ) );
+ }
+ else if ( sts[0]->VAD > hFdCngDec->cna_act_fact )
+ {
+ /* quickly increase during active frames in DFT stereo mode */
+ hFdCngDec->cna_act_fact_fx = extract_h( Mpy_32_16_1( 1503238553, hFdCngDec->cna_act_fact_fx ) + ( 644245094 * sts[0]->VAD ) );
+ }
+ else
+ {
+ /* slowly decrease during inactive frames in DFT stereo mode */
+ hFdCngDec->cna_act_fact_fx = extract_h( Mpy_32_16_1( 2040109440, hFdCngDec->cna_act_fact_fx ) + ( 107374184 * sts[0]->VAD ) );
+ }
+ }
+ }
+
+ //delete below
+ hCPE->lt_es_em = (float)hCPE->lt_es_em_fx / (1 << 24);
+ hFdCngDec->cna_act_fact = (float) hFdCngDec->cna_act_fact_fx / ( 1 << 15 );
+ hFdCngDec->cna_LR_LT = (float )hFdCngDec->cna_LR_LT_fx / ( 1 << 15 );
+ hFdCngDec->cna_ILD_LT= (float )hFdCngDec->cna_ILD_LT_fx / ( 1 << 15 );
+ for (int idx = 0; idx < STEREO_DFT_BAND_MAX; idx++)
+ {
+ hFdCngDec->cna_g_state[idx] = (float)hFdCngDec->cna_g_state_fx[idx]/ (1 << 15);
+ hFdCngDec->cna_cm[idx] = (float)hFdCngDec->cna_cm_fx[idx]/ (1 << 15);
+ }
+
+ return;
+}
+#endif
/*-------------------------------------------------------------------
* stereo_cng_init_dec()
*
diff --git a/lib_dec/ivas_stereo_dft_dec_fx.c b/lib_dec/ivas_stereo_dft_dec_fx.c
index 5c4eceb7a01073e9b18a37575551f6dd9147682c..502a4d21031de1fb0abf32f93d98934f6c22c5f1 100644
--- a/lib_dec/ivas_stereo_dft_dec_fx.c
+++ b/lib_dec/ivas_stereo_dft_dec_fx.c
@@ -1798,9 +1798,9 @@ void stereo_dft_dec_fx(
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);
+ DFT_L[1] = Mpy_32_16_1(DFT_L[1], INV_SQRT2_FX_Q15);
move32();
- DFT_R[1] = Mpy_32_16_1(DFT_R[1], INV_SQRT_2_FX);
+ DFT_R[1] = Mpy_32_16_1(DFT_R[1], INV_SQRT2_FX_Q15);
move32();
}
ELSE
diff --git a/lib_dec/ivas_stereo_ica_dec.c b/lib_dec/ivas_stereo_ica_dec.c
index 0818d678b0583d5ebd08b692c62949c680619af9..effd55a39b6f70724902f0f8503dc1d3b76964cf 100644
--- a/lib_dec/ivas_stereo_ica_dec.c
+++ b/lib_dec/ivas_stereo_ica_dec.c
@@ -252,6 +252,213 @@ void stereo_tca_dec(
return;
}
+
+#ifdef IVAS_FLOAT_FIXED
+void stereo_tca_dec_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *synth_fx[CPE_CHANNELS], /* i/o: output synth */
+ const Word16 output_frame /* i : length of a frame per channel */
+)
+{
+ /* Buffers, input Left and right channels @ input_Fs*/
+ Word32 bufChanL_fx[L_DEC_MEM_LEN_ICA + L_FRAME48k];
+ Word32 bufChanR_fx[L_DEC_MEM_LEN_ICA + L_FRAME48k];
+ Word32 *ptrChanL_fx, *ptrChanR_fx;
+ Word32 *target_fx;
+ Word16 target_idx, prevNCShift, currentNCShift, l_shift_adapt;
+ Word16 dsFactor, tempMax;
+ Word32 *ref_fx;
+ Word16 bothChannelShift;
+ Word32 output_Fs;
+ STEREO_TCA_DEC_HANDLE hStereoTCA;
+
+ hStereoTCA = hCPE->hStereoTCA;
+
+ output_Fs = hCPE->hCoreCoder[0]->output_Fs;
+
+ IF( hCPE->nchan_out == 1 )
+ {
+ IF( hCPE->hStereoDftDmx )
+ {
+ IF( hCPE->element_mode == IVAS_CPE_DFT )
+ {
+ // to be deleted next MR
+ hCPE->hStereoDftDmx->targetGain = 1.0f;
+ hCPE->hStereoDftDmx->targetGain_fx = ONE_IN_Q29;
+ }
+
+ /* save the target gain for next frame */
+ // to be deleted next MR
+ hCPE->hStereoDftDmx->prevTargetGain = hCPE->hStereoDftDmx->targetGain;
+ hCPE->hStereoDftDmx->prevTargetGain_fx = hCPE->hStereoDftDmx->targetGain_fx;
+ }
+
+ return;
+ }
+ ELSE IF( hCPE->element_mode == IVAS_CPE_MDCT && !hCPE->hStereoMdct->use_itd )
+ {
+ return;
+ }
+
+ /* populate L/R memories into current buffers */
+ Copy32( hStereoTCA->memChanL_fx, bufChanL_fx, L_DEC_MEM_LEN_ICA );
+ Copy32( hStereoTCA->memChanR_fx, bufChanR_fx, L_DEC_MEM_LEN_ICA );
+
+ /* pointers to the current frame */
+ ptrChanL_fx = bufChanL_fx + L_DEC_MEM_LEN_ICA;
+ ptrChanR_fx = bufChanR_fx + L_DEC_MEM_LEN_ICA;
+
+ /* copy interleaved stereo data to two channels, e.g., L, R */
+ Copy32( synth_fx[0], ptrChanL_fx, output_frame );
+ Copy32( synth_fx[1], ptrChanR_fx, output_frame );
+
+ /* back up the L/R target synth for next frame */
+ Copy32( bufChanL_fx + output_frame, hStereoTCA->memChanL_fx, L_DEC_MEM_LEN_ICA );
+ Copy32( bufChanR_fx + output_frame, hStereoTCA->memChanR_fx, L_DEC_MEM_LEN_ICA );
+
+ /* TCA parameter de-quantize */
+ dsFactor = (Word16) ( output_Fs / 8000 );
+ tempMax = NS2SA( output_Fs, L_NCSHIFT_NS );
+ hStereoTCA->corrLagStats = min( hStereoTCA->indx_ica_NCShift * dsFactor, tempMax );
+
+ bothChannelShift = 0;
+ IF( hCPE->element_mode == IVAS_CPE_DFT || hCPE->element_mode == IVAS_CPE_MDCT )
+ {
+ hStereoTCA->corrLagStats = 0;
+ hStereoTCA->refChanIndx = L_CH_INDX;
+ hStereoTCA->targetGain = 1.0f;
+ hStereoTCA->targetGain_fx = ONE_IN_Q29;
+
+ IF( hCPE->element_mode == IVAS_CPE_DFT )
+ {
+ hStereoTCA->corrLagStats = (Word16) fabsf( hCPE->hStereoDft->itd[1] );
+ hStereoTCA->refChanIndx = ( hCPE->hStereoDft->itd[1] >= 0 ) ? ( L_CH_INDX ) : ( R_CH_INDX );
+ }
+ ELSE IF( hCPE->element_mode == IVAS_CPE_MDCT )
+ {
+ float itd;
+
+ itd = hCPE->hStereoMdct->itd;
+ hStereoTCA->corrLagStats = (Word16) fabsf( itd );
+ hStereoTCA->refChanIndx = ( itd >= 0 ) ? ( L_CH_INDX ) : ( R_CH_INDX );
+ }
+
+ IF( hStereoTCA->refChanIndx != hStereoTCA->prevRefChanIndx && hStereoTCA->corrLagStats != 0 )
+ {
+ bothChannelShift = 1;
+ }
+ }
+
+ prevNCShift = (Word16) abs( hStereoTCA->prevCorrLagStats );
+ currentNCShift = (Word16) abs( hStereoTCA->corrLagStats );
+
+ IF( hCPE->element_mode == IVAS_CPE_TD && hCPE->last_element_mode == IVAS_CPE_TD )
+ {
+ IF( hStereoTCA->corrLagStats == hStereoTCA->prevCorrLagStats && hStereoTCA->interp_dec_switch_to_zero_diff == 0 )
+ {
+ hStereoTCA->interp_dec_switch_to_zero_diff = 1;
+ }
+ ELSE
+ {
+ hStereoTCA->interp_dec_switch_to_zero_diff = 0;
+ }
+
+ IF( currentNCShift != 0 )
+ {
+ currentNCShift = TRUNC( 0.6 * prevNCShift + 0.4 * currentNCShift );
+ }
+
+ prevNCShift = hStereoTCA->interp_dec_prevNCShift;
+ hStereoTCA->interp_dec_prevNCShift = currentNCShift;
+ }
+ ELSE
+ {
+ hStereoTCA->interp_dec_prevNCShift = currentNCShift;
+ hStereoTCA->interp_dec_switch_to_zero_diff = 0;
+ }
+
+ ref_fx = ptrChanL_fx;
+ target_fx = ptrChanR_fx;
+ target_idx = R_CH_INDX;
+ /* identify target signal to adjust for shift variations */
+ IF( ( prevNCShift == 0 && hStereoTCA->refChanIndx == R_CH_INDX ) || ( hStereoTCA->prevRefChanIndx == R_CH_INDX ) )
+ {
+ ref_fx = ptrChanR_fx;
+ target_fx = ptrChanL_fx;
+ target_idx = L_CH_INDX;
+ }
+
+ IF( bothChannelShift == 1 )
+ {
+ ref_fx = ptrChanL_fx;
+ target_fx = ptrChanR_fx;
+ target_idx = R_CH_INDX;
+ IF( hStereoTCA->refChanIndx == R_CH_INDX )
+ {
+ ref_fx = ptrChanR_fx;
+ target_fx = ptrChanL_fx;
+ target_idx = L_CH_INDX;
+ }
+ }
+
+ /* target signal adjustment for temporal shift variations */
+ IF( hStereoTCA->prevCorrLagStats != hStereoTCA->corrLagStats || bothChannelShift || ( hStereoTCA->interp_dec_switch_to_zero_diff == 1 && hCPE->element_mode == IVAS_CPE_TD ) )
+ {
+ l_shift_adapt = L_SHIFT_ADAPT_16k;
+ IF( output_Fs > 16000 )
+ {
+ l_shift_adapt = L_SHIFT_ADAPT_MAX;
+ }
+
+ IF( hCPE->element_mode == IVAS_CPE_TD && hCPE->last_element_mode == IVAS_CPE_DFT )
+ {
+ l_shift_adapt = l_shift_adapt >> 1;
+ }
+
+ IF( abs( currentNCShift - prevNCShift ) <= N_MAX_SHIFT_CHANGE && bothChannelShift == 0 )
+ {
+ adjustTargetSignal_fx( target_fx - currentNCShift, currentNCShift, prevNCShift, l_shift_adapt, 0 );
+ }
+ ELSE
+ {
+ IF( bothChannelShift == 1 )
+ {
+ adjustTargetSignal_fx( ref_fx, 0, prevNCShift, l_shift_adapt, 1 );
+ adjustTargetSignal_fx( target_fx - currentNCShift, currentNCShift, 0, l_shift_adapt, 1 );
+ }
+ ELSE
+ {
+ adjustTargetSignal_fx( target_fx - currentNCShift, currentNCShift, prevNCShift, l_shift_adapt, 1 );
+ }
+ }
+ }
+
+ /* temporal channel adjustment */
+ Copy32( target_fx - currentNCShift, synth_fx[target_idx], output_frame );
+
+ Copy32( ref_fx, synth_fx[!target_idx], output_frame );
+
+ /* Scale the Right channel with the gain */
+ stereo_tca_scale_R_channel_fx( hCPE, synth_fx[1], output_frame );
+
+ /*-----------------------------------------------------------------*
+ * updates and memory backups
+ *-----------------------------------------------------------------*/
+
+ /* save the reference channel index for next frame */
+ hStereoTCA->prevRefChanIndx = hStereoTCA->refChanIndx;
+
+ /* save the corr lag stats for next frame */
+ hStereoTCA->prevCorrLagStats = hStereoTCA->corrLagStats;
+
+ /* save the target gain for next frame */
+ //To delete below in next MR
+ hStereoTCA->prevTargetGain = hStereoTCA->targetGain;
+ hStereoTCA->prevTargetGain_fx = hStereoTCA->targetGain_fx;
+ return;
+}
+
+#endif
/*-------------------------------------------------------------------*
* stereo_tca_scale_R_channel()
*
@@ -330,7 +537,186 @@ void stereo_tca_scale_R_channel(
return;
}
+#ifdef IVAS_FLOAT_FIXED
+
+#define MAX_TARGET_GAIN_Q29 1904890240
+void stereo_tca_scale_R_channel_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *output_fx, /* i/o: output synthesis, R channel */
+ const Word16 output_frame /* i : frame length */
+)
+{
+ STEREO_TCA_DEC_HANDLE hStereoTCA;
+ Word16 j, l_ica_ovl, flat_old;
+ Word16 i_fx;
+ Word32 tempF_fx, tempF1_fx, winSlope_fx = 0;
+ Word32 output_Fs;
+
+ hStereoTCA = hCPE->hStereoTCA;
+ output_Fs = hCPE->hCoreCoder[0]->output_Fs;
+
+ IF( hCPE->hCoreCoder[0]->core_brate <= SID_2k40 && hCPE->nchan_out == 2 )
+ {
+ return;
+ }
+ /* Scale the Right channel with the gain */
+ l_ica_ovl = NS2SA( output_Fs, STEREO_L_TCA_OVLP_NS );
+
+
+ IF( hCPE->nchan_out == 1 )
+ {
+ /* in mono DMX, the scaling is done before synchro_synthesis() */
+ flat_old = NS2SA( output_Fs, ACELP_LOOK_NS + IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS );
+
+ IF( hCPE->last_element_mode == IVAS_CPE_TD && hCPE->element_mode == IVAS_CPE_DFT )
+ {
+ Word64 local_value;
+ // to be deleted next MR
+ hCPE->hStereoDftDmx->prevTargetGain *= 2.0f;
+ hCPE->hStereoDftDmx->prevTargetGain = min( hCPE->hStereoDftDmx->prevTargetGain, powf( 10, ( ( 1 << STEREO_BITS_TCA_GD ) - 1 ) * STEREO_TCA_GDSTEP + STEREO_TCA_GDMIN ) );
+ local_value = (Word64) hCPE->hStereoDftDmx->prevTargetGain_fx << 1;
+ hCPE->hStereoDftDmx->prevTargetGain_fx = (Word32) min( local_value, MAX_TARGET_GAIN_Q29 );
+ // to be deleted next MR
+ hCPE->hStereoDftDmx->targetGain = 1.0f;
+ hCPE->hStereoDftDmx->targetGain_fx = ONE_IN_Q29;
+
+ flat_old = NS2SA( output_Fs, IVAS_DEC_DELAY_NS );
+ }
+ }
+ ELSE IF( hCPE->last_element_mode == IVAS_CPE_TD && hCPE->element_mode == IVAS_CPE_DFT )
+ {
+ flat_old = NS2SA( output_Fs, IVAS_DEC_DELAY_NS );
+ }
+ ELSE
+ {
+ flat_old = NS2SA( output_Fs, ACELP_LOOK_NS + IVAS_DEC_DELAY_NS );
+ }
+
+ IF( hCPE->nchan_out == 1 )
+ {
+ IF( hCPE->hStereoDftDmx->targetGain_fx == ONE_IN_Q29 )
+ {
+ tempF1_fx = ONE_IN_Q27;
+ }
+ ELSE
+ {
+ Word16 temp_a = (Word16) L_shr( hCPE->hStereoDftDmx->targetGain_fx, (Word16) 16 );
+ Word16 temp_a_q = 2;
+ tempF1_fx = Inv16( temp_a, &temp_a_q );
+ tempF1_fx = L_shl( tempF1_fx, ( 31 - 4 ) - ( 15 - temp_a_q ) );
+ }
+
+ IF( hCPE->hStereoDftDmx->prevTargetGain_fx == ONE_IN_Q29 )
+ {
+ tempF_fx = ONE_IN_Q27;
+ }
+ ELSE
+ {
+ Word16 temp_b = (Word16) L_shr( hCPE->hStereoDftDmx->prevTargetGain_fx, 16 );
+ Word16 temp_b_q = 2;
+ tempF_fx = Inv16( temp_b, &temp_b_q );
+ tempF_fx = L_shl( tempF_fx, ( 31 - 4 ) - ( 15 - temp_b_q ) );
+ }
+ }
+ ELSE
+ {
+ IF( hStereoTCA->targetGain_fx == ONE_IN_Q29 )
+ {
+ tempF1_fx = ONE_IN_Q27;
+ }
+ ELSE
+ {
+ Word16 temp_a = (Word16) L_shr( hStereoTCA->targetGain_fx, (Word16) 16 );
+ Word16 temp_a_q = 2;
+ tempF1_fx = Inv16( temp_a, &temp_a_q );
+ tempF1_fx = L_shl( tempF1_fx, ( 31 - 4 ) - ( 15 - temp_a_q ) );
+ }
+
+
+ IF( hStereoTCA->prevTargetGain_fx == ONE_IN_Q29 )
+ {
+ tempF_fx = ONE_IN_Q27;
+ }
+ ELSE
+ {
+ Word16 temp_b = (Word16) L_shr( hStereoTCA->prevTargetGain_fx, (Word16) 16 );
+ Word16 temp_b_q = 2;
+ tempF_fx = Inv16( temp_b, &temp_b_q );
+ tempF_fx = L_shl( tempF_fx, ( 31 - 4 ) - ( 15 - temp_b_q ) );
+ }
+ }
+ SWITCH( output_Fs )
+ {
+ case 16000:
+ winSlope_fx = 26843546;
+ break;
+ case 32000:
+ winSlope_fx = 13421773;
+ break;
+ case 48000:
+ winSlope_fx = 8947849;
+ break;
+ }
+
+ IF( tempF_fx == ONE_IN_Q27 )
+ {
+ for ( i_fx = 0; i_fx < flat_old; i_fx++ )
+ {
+ output_fx[i_fx] = output_fx[i_fx];
+ }
+ }
+ ELSE
+ {
+ for ( i_fx = 0; i_fx < flat_old; i_fx++ )
+ {
+ output_fx[i_fx] = L_shl_sat( Mpy_32_32( output_fx[i_fx], tempF_fx ), 4 );
+ }
+ }
+
+
+ IF( tempF1_fx == ONE_IN_Q27 && tempF_fx == ONE_IN_Q27 )
+ {
+ for ( j = 0; i_fx < flat_old + l_ica_ovl; i_fx++, j++ )
+ {
+ Word32 slope_gain_decend = L_sub( ONE_IN_Q31, j * winSlope_fx );
+ Word32 slope_gain_ascend = ( j * winSlope_fx );
+ Word32 left_res = Mpy_32_32( slope_gain_decend, output_fx[i_fx] );
+ Word32 right_res = Mpy_32_32( slope_gain_ascend, output_fx[i_fx] );
+ output_fx[i_fx] = left_res + right_res;
+ }
+ }
+ ELSE
+ {
+ for ( j = 0; i_fx < flat_old + l_ica_ovl; i_fx++, j++ )
+ {
+ Word32 slope_gain_decend = L_sub( ONE_IN_Q31, j * winSlope_fx );
+ Word32 slope_gain_ascend = ( j * winSlope_fx );
+ Word32 left_res = Mpy_32_32( slope_gain_decend, output_fx[i_fx] );
+ Word32 right_res = Mpy_32_32( slope_gain_ascend, output_fx[i_fx] );
+ output_fx[i_fx] = L_add_sat( L_shl_sat( Mpy_32_32( tempF_fx, left_res ), 4 ), L_shl_sat( Mpy_32_32( right_res, tempF1_fx ), 4 ) );
+ }
+ }
+
+ IF( tempF1_fx == ONE_IN_Q27 )
+ {
+ for ( ; i_fx < output_frame; i_fx++ )
+ {
+ output_fx[i_fx] = output_fx[i_fx];
+ }
+ }
+ ELSE
+ {
+ for ( ; i_fx < output_frame; i_fx++ )
+ {
+ output_fx[i_fx] = L_shl_sat( Mpy_32_32( output_fx[i_fx], tempF1_fx ), 4 );
+ }
+ }
+
+ return;
+}
+
+#endif
/*-------------------------------------------------------------------*
* stereo_tca_init_dec()
*
@@ -371,7 +757,7 @@ void stereo_tca_init_dec_fx(
hStereoTCA->indx_ica_gD = 0;
hStereoTCA->targetGain = 1.0f; /* TODO: Remove float init*/
hStereoTCA->targetGain_fx = ONE_IN_Q29;
- hStereoTCA->prevTargetGain_fx = ONE_IN_Q14;
+ hStereoTCA->prevTargetGain_fx = ONE_IN_Q29;
hStereoTCA->prevTargetGain = 1.0f; /* TODO: Remove float init*/
hStereoTCA->corrLagStats = 0;
diff --git a/lib_dec/ivas_stereo_icbwe_dec.c b/lib_dec/ivas_stereo_icbwe_dec.c
index 5a1f71cf1855376fa0044c8ec399e991ef8cb3ec..3d39c52f01ed6a181766087e1d82c2b606dc09ce 100644
--- a/lib_dec/ivas_stereo_icbwe_dec.c
+++ b/lib_dec/ivas_stereo_icbwe_dec.c
@@ -1064,7 +1064,7 @@ void stereo_icBWE_dec_fx(
}
ELSE
{
- ratio_L_fx = tdm_ratio_tabl_fx[hCPE->hStereoTD->tdm_last_ratio_idx];
+ ratio_L_fx = extract_h(tdm_ratio_tabl_fx[hCPE->hStereoTD->tdm_last_ratio_idx]);
move16();
}
@@ -1211,7 +1211,7 @@ void stereo_icBWE_dec_fx(
}
ELSE
{
- ratio_L_fx = tdm_ratio_tabl_fx[hCPE->hStereoTD->tdm_last_ratio_idx];
+ ratio_L_fx = extract_h(tdm_ratio_tabl_fx[hCPE->hStereoTD->tdm_last_ratio_idx]);
move16();
}
diff --git a/lib_dec/ivas_stereo_mdct_stereo_dec.c b/lib_dec/ivas_stereo_mdct_stereo_dec.c
index c4e2bf8a2ee5a611048d2abf0af9d8853c674863..35ba2d4c805c9ab598f82a596b9aa91391a8e64b 100644
--- a/lib_dec/ivas_stereo_mdct_stereo_dec.c
+++ b/lib_dec/ivas_stereo_mdct_stereo_dec.c
@@ -1254,3 +1254,98 @@ void applyDmxMdctStereo(
return;
}
+
+
+void applyDmxMdctStereo_fx(
+ const CPE_DEC_HANDLE hCPE, /* i : CPE handle */
+ Word32 *output_fx[CPE_CHANNELS], /* i/o: core decoder output */
+ const Word16 output_frame /* i : output frame length */
+)
+{
+ Word16 crossfade_len, i;
+ Word16 dmx_len;
+ Word32 fade_fx, step_fx;
+
+ step_fx = ONE_IN_Q31;
+ fade_fx = ONE_IN_Q31;
+ dmx_len = output_frame;
+
+ IF( hCPE->last_element_brate <= IVAS_SID_5k2 )
+ {
+ crossfade_len = NS2SA( hCPE->hCoreCoder[0]->output_Fs, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS );
+ SWITCH( hCPE->hCoreCoder[0]->output_Fs )
+ {
+ case 48000:
+ step_fx = 22369622;
+ break;
+ case 32000:
+ step_fx = 33554432;
+ break;
+ case 16000:
+ step_fx = 67108864;
+ break;
+ default:
+ assert( 0 );
+ break;
+ }
+ }
+ /* for first inactive CNG frame after active decoding we have to do a fade-OUT FROM the passive DMX */
+ ELSE IF( hCPE->element_brate <= IVAS_SID_5k2 && hCPE->last_element_brate > IVAS_SID_5k2 )
+ {
+ crossfade_len = output_frame / 4;
+ SWITCH( output_frame )
+ {
+ case 960:
+ step_fx = -8947849;
+ break;
+ case 640:
+ step_fx = -13421773;
+ break;
+ case 320:
+ step_fx = -26843546;
+ break;
+ }
+ fade_fx = 0;
+ dmx_len = crossfade_len;
+ }
+ ELSE IF( hCPE->last_element_mode == IVAS_CPE_DFT && hCPE->last_element_brate <= IVAS_32k )
+ {
+ crossfade_len = NS2SA( hCPE->hCoreCoder[0]->output_Fs, DELAY_CLDFB_NS );
+ SWITCH( hCPE->hCoreCoder[0]->output_Fs )
+ {
+ case 48000:
+ step_fx = 35791396;
+ break;
+ case 32000:
+ step_fx = 53687092;
+ break;
+ case 16000:
+ step_fx = 107374184;
+ break;
+ default:
+ assert( 0 );
+ break;
+ }
+ }
+ ELSE
+ {
+ crossfade_len = 0;
+ }
+
+ /* apply crossfade */
+ FOR( i = 0; i < crossfade_len; i++ )
+ {
+ Word32 temp_1 = Mpy_32_32( output_fx[0][i], fade_fx );
+ Word32 temp_2 = Mpy_32_32( L_add_sat( output_fx[0][i], output_fx[1][i] ), Mpy_32_32( INV_SQRT2_FX, L_sub_sat( ONE_IN_Q31, fade_fx ) ) );
+ output_fx[0][i] = temp_1 + temp_2;
+ fade_fx = L_sub_sat( fade_fx, step_fx );
+ }
+
+ /* apply passive downmix on all-active-frame part */
+ FOR( ; i < dmx_len; i++ )
+ {
+ output_fx[0][i] = Mpy_32_32( L_add_sat( output_fx[0][i], output_fx[1][i] ), INV_SQRT2_FX );
+ }
+
+ return;
+}
diff --git a/lib_dec/ivas_stereo_switching_dec.c b/lib_dec/ivas_stereo_switching_dec.c
index d45bd3d2e15306df5c1333fc9e436fa337ed69a9..e972bc7d8cd2835b5704d7929a14c7b6a426d6ec 100644
--- a/lib_dec/ivas_stereo_switching_dec.c
+++ b/lib_dec/ivas_stereo_switching_dec.c
@@ -35,6 +35,8 @@
#include "cnst.h"
#include "rom_com.h"
#include "prot.h"
+#include "prot_fx1.h"
+#include "prot_fx2.h"
#include "ivas_prot.h"
#include "ivas_prot_fx.h"
#include "ivas_rom_com.h"
@@ -49,7 +51,7 @@
*-------------------------------------------------------------------*/
#define DFT2TD_CORR_THRESH 0.9f
-
+#define DFT2TD_CORR_THRESH_FX 1932735283
/*-------------------------------------------------------------------*
* Function allocate_CoreCoder_TCX()
@@ -517,9 +519,11 @@ ivas_error stereo_memory_dec(
{
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD Stereo\n" ) );
}
-
+#ifndef IVAS_FLOAT_FIXED
stereo_td_init_dec( hCPE->hStereoTD, hCPE->last_element_mode );
-
+#else
+ stereo_td_init_dec_fx( hCPE->hStereoTD, hCPE->last_element_mode );
+#endif
/* allocate CoreCoder secondary channel */
if ( ( error = allocate_CoreCoder( hCPE->hCoreCoder[1] ) ) != IVAS_ERR_OK )
{
@@ -935,6 +939,13 @@ ivas_error stereo_memory_dec(
hCPE->prev_synth_chs[1] = NULL;
}
+#ifdef IVAS_FLOAT_FIXED
+ if (hCPE->prev_synth_chs_fx[1] != NULL)
+ {
+ free(hCPE->prev_synth_chs_fx[1]);
+ hCPE->prev_synth_chs_fx[1] = NULL;
+ }
+#endif
if ( hCPE->hStereoTCA != NULL )
{
free( hCPE->hStereoTCA );
@@ -959,6 +970,17 @@ ivas_error stereo_memory_dec(
set_zero( hCPE->prev_synth_chs[1], NS2SA( st->output_Fs, FRAME_SIZE_NS ) );
}
+#ifdef IVAS_FLOAT_FIXED
+ if (hCPE->prev_synth_chs_fx[1] == NULL)
+ {
+ st = hCPE->hCoreCoder[1];
+ if ((hCPE->prev_synth_chs_fx[1] = (Word32 *)malloc(sizeof(Word32) * NS2SA(st->output_Fs, FRAME_SIZE_NS))) == NULL)
+ {
+ return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n"));
+ }
+ set32_fx(hCPE->prev_synth_chs_fx[1],0, NS2SA(st->output_Fs, FRAME_SIZE_NS));
+ }
+#endif
if ( hCPE->hStereoICBWE == NULL && hCPE->element_mode == IVAS_CPE_DFT )
{
if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_DEC_HANDLE) malloc( sizeof( STEREO_ICBWE_DEC_DATA ) ) ) == NULL )
@@ -1888,187 +1910,1618 @@ void synchro_synthesis_fx(
}
#endif
-/*-------------------------------------------------------------------*
- * Function stereo_switching_dec()
- *
- * Handling of memories in case of CPE modes switching
- *-------------------------------------------------------------------*/
-
-void stereo_switching_dec(
- CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
- const int32_t ivas_total_brate /* i : IVAS total bitrate */
+#ifdef IVAS_FLOAT_FIXED
+void synchro_synthesis_fixed(
+ const Word32 ivas_total_brate, /* i : IVAS total bitrate */
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ float *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 */
)
{
- int16_t i, n;
- int16_t dft32ms_ovl;
- Decoder_State **sts;
- float tmpF;
- int16_t delay_comp_TD;
- sts = hCPE->hCoreCoder;
-
- delay_comp_TD = NS2SA( sts[0]->output_Fs, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS );
-
- /* prevent CPE mode switching in the first received frame */
- if ( sts[0]->ini_frame == 0 )
- {
- hCPE->last_element_mode = hCPE->element_mode;
- hCPE->stereo_switching_counter = 10;
- hCPE->NbFrameMod = 7;
- hCPE->lt_es_em = 0.0f;
- }
-
- if ( hCPE->element_mode == hCPE->last_element_mode )
- {
- hCPE->stereo_switching_counter++;
- hCPE->stereo_switching_counter = min( 10, hCPE->stereo_switching_counter );
- }
- else
- {
- hCPE->stereo_switching_counter = 0;
- }
-
- if ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->nchan_out == 1 && hCPE->element_brate >= IVAS_32k && hCPE->last_element_brate <= IVAS_24k4 )
- {
- dft32ms_ovl = (int16_t) ( ( STEREO_DFT32MS_OVL_MAX * sts[0]->output_Fs ) / 48000 );
- set_zero( hCPE->output_mem[0], dft32ms_ovl );
- }
+ Word32 *output_fx[2];
+ Word32 op[2][L_FRAME48k];
+ output_fx[0] = op[0];
+ output_fx[1] = op[1];
- if ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->last_element_mode != IVAS_CPE_DFT && hCPE->hCoreCoder[0]->ini_frame > 0 )
+ FOR( Word32 n = 0; n < CPE_CHANNELS; n++ )
{
- /* windowing the OLA memory */
- dft32ms_ovl = (int16_t) ( ( STEREO_DFT32MS_OVL_MAX * sts[0]->output_Fs ) / 48000 );
- for ( n = 0; n < CPE_CHANNELS; n++ )
+ FOR( Word32 k = 0; k < L_FRAME48k; k++ )
{
- if ( hCPE->last_element_mode == IVAS_CPE_MDCT )
- {
- /* copy memories from previous MDCT Stereo frame to output_mem */
- mvr2r( hCPE->input_mem[n], hCPE->output_mem[n], dft32ms_ovl );
- }
-
- if ( ivas_total_brate > IVAS_SID_5k2 || n == 0 || hCPE->last_element_mode != IVAS_CPE_TD || hCPE->nchan_out == 1 )
+ output_fx[n][k] = (Word32) ( output[n][k] * ( 1 << OUTPUT_Q ) );
+ }
+ IF( hCPE->hStereoDft != NULL )
+ {
+ IF( hCPE->hStereoDft->hTcxLtpDec != NULL )
{
- for ( i = 0; i < dft32ms_ovl; i++ )
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
{
- hCPE->output_mem[n][i] *= hCPE->hStereoDft->win32ms[STEREO_DFT32MS_STEP * ( dft32ms_ovl - 1 - i )];
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_out_32[p] = (Word32) ( hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_out_float[p] * ( 1u << OUTPUT_Q ) );
+ }
+ FOR( Word32 p = 0; p < TCXLTP_MAX_DELAY; p++ )
+ {
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_in_32[p] = (Word32) ( hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_in_float[p] * ( 1u << OUTPUT_Q ) );
}
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_post_prev = (Word16) ( hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_post_prev_float * ONE_IN_Q15 );
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain = (Word16) ( hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_float * ONE_IN_Q15 );
}
- else
+ }
+ IF( hCPE->hCoreCoder[n] != NULL )
+ {
+ IF( hCPE->hCoreCoder[n]->hTcxLtpDec != NULL )
{
- tmpF = 1.0f / hCPE->hStereoTCA->prevTargetGain;
- for ( i = 0; i < dft32ms_ovl; i++ )
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
{
- hCPE->output_mem[n][i] *= tmpF * hCPE->hStereoDft->win32ms[STEREO_DFT32MS_STEP * ( dft32ms_ovl - 1 - i )];
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_out_32[p] = (Word32) ( hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_out_float[p] * ( 1u << OUTPUT_Q ) );
}
- for ( i = 0; i < delay_comp_TD; i++ )
+ FOR( Word32 p = 0; p < TCXLTP_MAX_DELAY; p++ )
{
- hCPE->hCoreCoder[1]->prev_synth_buffer[i] *= tmpF;
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_in_32[p] = (Word32) ( hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_in_float[p] * ( 1u << OUTPUT_Q ) );
}
- for ( i = 0; i < L_DEC_MEM_LEN_ICA; i++ )
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_post_prev = (Word16) ( hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_post_prev_float * ONE_IN_Q15 );
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain = (Word16) ( hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_float * ONE_IN_Q15 );
+ }
+
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS ); k++ )
+ {
+ hCPE->hCoreCoder[n]->prev_synth_buffer32_fx[k] = (Word32) ( hCPE->hCoreCoder[n]->prev_synth_buffer[k] * ( 1 << OUTPUT_Q ) );
+ }
+ FOR( Word32 k = 0; k < HQ_DELTA_MAX * HQ_DELAY_COMP; k++ )
+ {
+ hCPE->hCoreCoder[n]->delay_buf_out32_fx[k] = (Word32) ( hCPE->hCoreCoder[n]->delay_buf_out[k] * ( 1 << OUTPUT_Q ) );
+ }
+ IF( hCPE->hCoreCoder[n]->hTcxDec != NULL )
+ {
+ FOR( Word32 k = 0; k < 111; k++ )
{
- hCPE->hStereoTCA->memChanR[i] *= tmpF;
+ hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_32[k] = (Word32) ( hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_float[k] * ( 1 << OUTPUT_Q ) );
}
}
}
- if ( hCPE->last_element_mode == IVAS_CPE_MDCT )
+ IF( hCPE->output_mem[n] != NULL )
{
- /* create passive downmix of MDCT Stereo memories for DFT input memory */
- v_add( hCPE->input_mem_LB[0], hCPE->input_mem_LB[1], hCPE->input_mem_LB[0], STEREO_DFT32MS_OVL_16k );
- v_multc( hCPE->input_mem_LB[0], 0.5f, hCPE->input_mem_LB[0], STEREO_DFT32MS_OVL_16k );
-
- v_add( hCPE->input_mem[0], hCPE->input_mem[1], hCPE->input_mem[0], dft32ms_ovl );
- v_multc( hCPE->input_mem[0], 0.5f, hCPE->input_mem[0], dft32ms_ovl );
-
- if ( hCPE->nchan_out == 1 )
+ FOR( Word32 k = 0; k < NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS ); k++ )
{
- v_add( hCPE->output_mem[0], hCPE->output_mem[1], hCPE->output_mem[0], dft32ms_ovl );
- v_multc( hCPE->output_mem[0], INV_SQRT_2, hCPE->output_mem[0], dft32ms_ovl );
+ hCPE->output_mem_fx[n][k] = (Word32) ( hCPE->output_mem[n][k] * ( 1 << OUTPUT_Q ) );
}
}
-
- /* Update the side_gain[] parameters */
- if ( hCPE->last_element_mode != IVAS_CPE_MDCT )
+ IF( hCPE->input_mem[n] != NULL )
{
- tmpF = 0;
- if ( hCPE->hStereoTCA != NULL )
+ FOR( Word32 ind = 0; ind < STEREO_DFT32MS_OVL_16k; ind++ )
{
- tmpF = usdequant( hCPE->hStereoTCA->indx_ica_gD, STEREO_TCA_GDMIN, STEREO_TCA_GDSTEP );
+ hCPE->input_mem_LB_fx[n][ind] = (Word32) ( hCPE->input_mem_LB[n][ind] * ( 1 << OUTPUT_Q ) );
}
+ }
- set_f( hCPE->hStereoDft->side_gain + STEREO_DFT_NBDIV * STEREO_DFT_BAND_MAX, tmpF, STEREO_DFT_BAND_MAX );
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS ); k++ )
+ {
+ hCPE->prev_hb_synth_fx[n][k] = (Word32) ( hCPE->prev_hb_synth[n][k] * ( 1 << OUTPUT_Q ) );
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS ); k++ )
+ {
+ hCPE->prev_synth_fx[n][k] = (Word32) ( hCPE->prev_synth[n][k] * ( 1 << OUTPUT_Q ) );
}
+ }
- /* reset residual coding / ESF (secondary channel) */
- set_zero( hCPE->hStereoDft->res_cod_mem, STEREO_DFT_OVL_8k );
- set_zero( hCPE->input_mem[1], NS2SA( sts[0]->output_Fs, STEREO_DFT32MS_OVL_NS ) );
+ Word16 n, delay_comp_TD, delay_comp_DFT;
+ Word32 output_Fs;
+ Decoder_State **sts;
+ Word16 i, delay_cldfb, dft32ms_ovl;
+
+ Word32 *p_output_mem_fx[CPE_CHANNELS];
+ Word32 tmp_out_fx[CPE_CHANNELS][NS2SA( 48000, DELAY_CLDFB_NS )];
+ Word32 tmp_out_TD_fx[CPE_CHANNELS][STEREO_DFT32MS_OVL_MAX];
+ Word32 tmp_out_TD2_fx[CPE_CHANNELS][STEREO_DFT32MS_OVL_MAX];
+
+ Word16 use_cldfb_for_last_dft;
+ Word16 dft_mono_brate_switch;
+ Word16 delay_diff;
+ Word32 tmpF_fx = 0;
+ 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;
}
- if ( hCPE->element_mode == IVAS_CPE_TD && hCPE->last_element_mode != IVAS_CPE_TD && hCPE->hCoreCoder[0]->ini_frame > 0 )
+ 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 )
{
- hCPE->hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_MID_IS_PRIM;
- hCPE->hStereoTD->tdm_last_SM_flag = 0;
- hCPE->hStereoTD->tdm_prev_last_SM_flag = 0;
+ 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*/
+ }
+ }
- /* First frame after DFT frame AND the content is uncorrelated or xtalk -> the primary channel is forced to left */
- if ( hCPE->hStereoTD->tdm_LRTD_flag == 1 )
+ 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 ) )
{
- hCPE->hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_LEFT_IS_PRIM;
+ stereo_tca_scale_R_channel_fx( hCPE, output_fx[0], output_frame );
}
}
- /* no secondary channel in the previous frame -> memory resets */
- if ( hCPE->element_mode > IVAS_CPE_DFT && hCPE->last_element_mode == IVAS_CPE_DFT )
+ /* 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 = (Word16) ( ( 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_fx[0] != NULL )
{
- if ( hCPE->last_element_brate <= IVAS_SID_5k2 && hCPE->nchan_out == 2 )
+ FOR( n = 0; n < CPE_CHANNELS; n++ )
{
- /* reset CLDFB memories */
- cldfb_reset_memory_ivas( sts[0]->cldfbAna );
- cldfb_reset_memory_ivas( sts[0]->cldfbBPF );
- cldfb_reset_memory_ivas( sts[0]->cldfbSyn );
+ p_output_mem_fx[n] = hCPE->output_mem_fx[n];
+ }
+ }
- sts[0]->mem_deemph = 0;
+ /*----------------------------------------------------------------*
+ * DFT stereo synchro
+ *----------------------------------------------------------------*/
- sts[0]->tilt_code = 0.0f;
- sts[0]->gc_threshold = 0.0f;
+ 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_buffer32_fx[i] = p_output_mem_fx[0][i - delay_comp_DFT];
+ }
- set_f( sts[0]->mem_syn1, 0, M );
- set_f( sts[0]->mem_syn2, 0, M );
- set_f( sts[0]->mem_syn3, 0, M );
- set_f( sts[0]->mem_syn_r_float, 0.0f, L_SYN_MEM );
+ FOR( i = delay_comp_TD; i < delay_comp_TD + delay_cldfb; i++ )
+ {
+ tmp_out_fx[0][i - delay_comp_TD] = p_output_mem_fx[0][i - delay_comp_DFT];
+ }
+ }
- sts[1]->last_L_frame = sts[0]->last_L_frame;
+ IF( hCPE->nchan_out == 1 && hCPE->last_element_mode == IVAS_CPE_MDCT )
+ {
+ FOR( Word32 ind = 0; ind < delay_comp_DFT; ind++ )
+ {
+ Word32 temp = sts[0]->prev_synth_buffer32_fx[ind] + sts[1]->prev_synth_buffer32_fx[ind];
+ sts[0]->prev_synth_buffer32_fx[ind] = Mpy_32_32( temp, INV_SQRT2_FX );
+ }
+ }
- /* reset PCh memories */
- set_f( sts[0]->old_exc, 0, L_EXC_MEM_DEC );
- set_f( sts[0]->lsf_old, 0, M );
- set_f( sts[0]->lsp_old, 0, M );
+ 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. */
+ Copy32( sts[0]->prev_synth_buffer32_fx + delay_comp_DFT, hCPE->hCoreCoder[0]->hTcxDec->FBTCXdelayBuf_32, delay_diff );
+ delay_signal_fx( output_fx[0], output_frame, hCPE->hCoreCoder[0]->hTcxDec->FBTCXdelayBuf_32, delay_diff );
}
- sts[1]->last_extl = -1;
- sts[1]->prev_bfi = sts[0]->prev_bfi;
+ IF( hCPE->element_mode != IVAS_CPE_MDCT )
+ {
+ ivas_post_proc_fx( NULL, hCPE, 0, output_fx[0], output_fx, output_frame, sba_dirac_stereo_flag );
+ }
- set_f( sts[1]->old_pitch_buf, (float) L_SUBFR, 2 * NB_SUBFR16k );
- sts[1]->old_fpitchFB_float = 2 * (float) L_SUBFR;
+ /* 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_fx( output_fx[n], output_frame, hCPE->prev_synth_fx[n], delay_comp_DFT );
+ }
+ ELSE
+ {
+ delay_signal_fx( output_fx[n], output_frame, sts[n]->prev_synth_buffer32_fx, delay_comp_DFT );
+ }
+ }
+ IF( use_cldfb_for_last_dft )
+ {
+ Copy32( hCPE->hCoreCoder[0]->hTcxDec->FBTCXdelayBuf_32, sts[0]->prev_synth_buffer32_fx + delay_comp_DFT, delay_diff );
+ }
- /* reset CLDFB memories */
- cldfb_reset_memory_ivas( sts[1]->cldfbAna );
- cldfb_reset_memory_ivas( sts[1]->cldfbBPF );
- cldfb_reset_memory_ivas( sts[1]->cldfbSyn );
+ /* 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 )
+ {
+ Word32 *pPrev_synth_fx;
+ Word32 inv_fade_len_fx = 0;
+ switch ( output_Fs )
+ {
+ case 16000:
+ inv_fade_len_fx = 71582792;
+ break;
+ case 32000:
+ inv_fade_len_fx = 35791396;
+ break;
+ case 48000:
+ inv_fade_len_fx = 23860930;
+ break;
+ default:
+ assert( 0 );
+ }
- sts[1]->mem_deemph = 0;
+ /* cross-fading between TD synchro memory and the DFT output */
+ IF( sba_dirac_stereo_flag )
+ {
+ pPrev_synth_fx = hCPE->prev_synth_fx[n];
+ }
+ ELSE
+ {
+ pPrev_synth_fx = sts[n]->prev_synth_buffer32_fx;
+ }
- sts[1]->tilt_code = 0.0f;
- sts[1]->gc_threshold = 0.0f;
+ IF( hCPE->last_element_mode != IVAS_CPE_MDCT )
+ {
+ FOR( i = delay_comp_DFT; i < delay_comp_TD; i++ )
+ {
+ Word64 res1 = (Word64) pPrev_synth_fx[i] * ( delay_comp_TD - i );
+ Word64 res2 = (Word64) output_fx[n][i] * ( i - delay_comp_DFT );
+ Word64 res = W_shr( res1, 6 ) + W_shr( res2, 6 );
+ res = res * inv_fade_len_fx;
+ output_fx[n][i] = (Word32) W_shr( res, 31 - 6 );
+ // change 6 to less number to get better precision
+ }
+ }
+ }
+ ELSE IF( dft_mono_brate_switch == -1 )
+ {
+ Word32 inv_fade_len_1_fx = 0;
+ Word32 inv_fade_len_2_fx = 0;
- set_f( sts[1]->mem_syn1, 0, M );
- set_f( sts[1]->mem_syn2, 0, M );
- set_f( sts[1]->mem_syn3, 0, M );
- set_f( sts[1]->mem_syn_r_float, 0.0f, L_SYN_MEM );
+ switch ( output_Fs )
+ {
+ case 16000:
+ inv_fade_len_1_fx = 71582792;
+ inv_fade_len_2_fx = 107374184;
+ break;
+ case 32000:
+ inv_fade_len_1_fx = 35791396;
+ inv_fade_len_2_fx = 53687092;
+ break;
+ case 48000:
+ inv_fade_len_1_fx = 23860930;
+ inv_fade_len_2_fx = 35791396;
+ break;
+ default:
+ assert( 0 );
+ }
+ FOR( i = 0; i < delay_diff; i++ )
+ {
+ Word64 res1 = (Word64) output_fx[0][i + delay_comp_DFT] * ( delay_diff - i );
+ Word64 res2 = (Word64) p_output_mem_fx[0][i] * i;
+ Word64 res = W_shr( res1, 6 ) + W_shr( res2, 6 );
+ res = res * inv_fade_len_1_fx;
+ output_fx[0][i + delay_comp_DFT] = (Word32) W_shr( res, 31 - 6 );
+ }
- sts[1]->last_L_frame = sts[0]->last_L_frame;
+ FOR( i = 0; i < delay_cldfb; i++ )
+ {
+ Word64 res1 = (Word64) tmp_out_fx[0][i] * ( delay_cldfb - i );
+ Word64 res2 = (Word64) output_fx[0][i + delay_comp_TD] * i;
+ Word64 res = W_shr( res1, 6 ) + W_shr( res2, 6 );
+ res = res * inv_fade_len_2_fx;
+ output_fx[0][i + delay_comp_TD] = (Word32) W_shr( res, 31 - 6 );
+ }
+ }
+ }
+ }
- /* populate PCh memories into the SCh */
+ /*----------------------------------------------------------------*
+ * TD/MDCT stereo synchro
+ *----------------------------------------------------------------*/
+
+ IF( sba_dirac_stereo_flag )
+ {
+ // delete the below
+#if 1
+ IF( hCPE->hStereoDft != NULL )
+ {
+ IF( hCPE->hStereoDft->hTcxLtpDec != NULL )
+ {
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
+ {
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_out_float[p] = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_out_32[p] / ( 1u << OUTPUT_Q );
+ }
+ FOR( Word32 p = 0; p < TCXLTP_MAX_DELAY; p++ )
+ {
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_in_float[p] = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_in_32[p] / ( 1u << OUTPUT_Q );
+ }
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_post_prev_float = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_post_prev / ONE_IN_Q15;
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_float = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain / ONE_IN_Q15;
+ }
+ }
+ FOR( n = 0; n < CPE_CHANNELS; n++ )
+ {
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
+ {
+ output[n][p] = (float) output_fx[n][p] / ( 1u << 11 );
+ }
+ IF( hCPE->output_mem[n] != NULL )
+ {
+ FOR( Word32 k = 0; k < NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS ); k++ )
+ {
+ hCPE->output_mem[n][k] = (float) hCPE->output_mem_fx[n][k] / ( 1u << 11 );
+ }
+ }
+ IF( hCPE->hCoreCoder[n] != NULL )
+ {
+ IF( hCPE->hCoreCoder[n]->hTcxLtpDec != NULL )
+ {
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_out_float[p] = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_out_32[p] / ( 1u << OUTPUT_Q );
+ }
+ FOR( Word32 p = 0; p < TCXLTP_MAX_DELAY; p++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_in_float[p] = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_in_32[p] / ( 1u << OUTPUT_Q );
+ }
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_post_prev_float = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_post_prev / ONE_IN_Q15;
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_float = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain / ONE_IN_Q15;
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS ); k++ )
+ {
+ hCPE->hCoreCoder[n]->prev_synth_buffer[k] = (float) hCPE->hCoreCoder[n]->prev_synth_buffer32_fx[k] / ( 1 << OUTPUT_Q );
+ }
+ FOR( Word32 k = 0; k < HQ_DELTA_MAX * HQ_DELAY_COMP; k++ )
+ {
+ hCPE->hCoreCoder[n]->delay_buf_out[k] = (float) hCPE->hCoreCoder[n]->delay_buf_out32_fx[k] / ( 1 << OUTPUT_Q );
+ }
+ IF( hCPE->hCoreCoder[n]->hTcxDec != NULL )
+ {
+ FOR( Word32 k = 0; k < 111; k++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_float[k] = (float) hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_32[k] / ( 1 << OUTPUT_Q );
+ }
+ }
+ }
+ IF( hCPE->input_mem[n] != NULL )
+ {
+ FOR( Word32 ind = 0; ind < STEREO_DFT32MS_OVL_16k; ind++ )
+ {
+ hCPE->input_mem_LB[n][ind] = ( (float) hCPE->input_mem_LB_fx[n][ind] / ( 1 << OUTPUT_Q ) );
+ }
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS ); k++ )
+ {
+ hCPE->prev_hb_synth[n][k] = (float) hCPE->prev_hb_synth_fx[n][k] / ( 1 << OUTPUT_Q );
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS ); k++ )
+ {
+ hCPE->prev_synth[n][k] = (float) hCPE->prev_synth_fx[n][k] / ( 1 << OUTPUT_Q );
+ }
+ }
+#endif
+
+ // keep return
+ 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_fx[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_buffer32_fx[i] = p_output_mem_fx[n][i - delay_comp_DFT];
+ }
+
+ FOR( i = delay_comp_TD; i < delay_comp_TD + delay_cldfb; i++ )
+ {
+ tmp_out_fx[n][i - delay_comp_TD] = p_output_mem_fx[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 )
+ {
+ Copy32( sts[0]->prev_synth_buffer32_fx, sts[1]->prev_synth_buffer32_fx, delay_comp_TD );
+ Copy32( tmp_out_fx[0], tmp_out_fx[1], delay_cldfb );
+ Copy32( p_output_mem_fx[0], p_output_mem_fx[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 )
+ {
+ L_lerp_fx_q11( hCPE->input_mem_LB_fx[n], tmp_out_TD_fx[n], dft32ms_ovl, NS2SA( sts[n]->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) );
+ }
+ ELSE /* TCX/HQ core */
+ {
+ L_lerp_fx_q11( hCPE->input_mem_LB_fx[n], tmp_out_TD_fx[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_fx[n][i] = sts[n]->delay_buf_out32_fx[i - delay_diff];
+ }
+ }
+ }
+
+ IF( hCPE->nchan_out == CPE_CHANNELS )
+ {
+ /* upmix the resampled LB / the TCX synchro memory */
+ tdm_upmix_plain_fx( tmp_out_TD2_fx[0], tmp_out_TD2_fx[1], tmp_out_TD_fx[0], tmp_out_TD_fx[1], tdm_ratio_tabl_fx[hCPE->hStereoTD->tdm_last_ratio_idx], tdm_den_ratio_tabl_fx[hCPE->hStereoTD->tdm_last_ratio_idx], 0, dft32ms_ovl, 1 );
+ }
+ ELSE
+ {
+ Copy32( tmp_out_TD_fx[0], tmp_out_TD2_fx[0], dft32ms_ovl );
+ }
+
+ FOR( n = 0; n < hCPE->nchan_out; n++ )
+ {
+ IF( sts[0]->core == ACELP_CORE ) /* ACELP core in primary channel */
+ {
+ switch ( output_Fs )
+ {
+ case 16000:
+ tmpF_fx = 71582792;
+ break;
+ case 32000:
+ tmpF_fx = 35791396;
+ break;
+ case 48000:
+ tmpF_fx = 23860930;
+ break;
+ default:
+ assert( 0 );
+ }
+ /* 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++ )
+ {
+
+ Word64 res1 = (Word64) output_fx[n][output_frame - dft32ms_ovl + delay_cldfb + i] * ( delay_diff - i );
+ Word64 res2 = (Word64) tmp_out_TD2_fx[n][i] * i;
+ Word64 res = W_shr( res1, 6 ) + W_shr( res2, 6 );
+ res = res * tmpF_fx;
+ p_output_mem_fx[n][i] = (Word32) W_shr( res, 31 - 6 );
+ }
+ }
+ ELSE /* TCX core */
+ {
+ /* reconstruct the 3.125 - 1.25 ms OLA part */
+ FOR( i = 0; i < delay_diff; i++ )
+ {
+ p_output_mem_fx[n][i] = output_fx[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_fx[n][i] = tmp_out_TD2_fx[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 )
+ {
+ Word32 step_fx = 0;
+ tmpF_fx = ONE_IN_Q31;
+ switch ( output_Fs )
+ {
+ case 16000:
+ step_fx = 33554432;
+ break;
+ case 32000:
+ step_fx = 16777216;
+ break;
+ case 48000:
+ step_fx = 11184811;
+ break;
+ default:
+ assert( 0 );
+ }
+ /* FOR the first switching frame from DFT to TD, downmix memory too */
+ FOR( n = 0; n < delay_comp_TD; n++ )
+ {
+ sts[0]->prev_synth_buffer32_fx[n] = Mpy_32_32( sts[0]->prev_synth_buffer32_fx[n], tmpF_fx );
+ tmpF_fx = L_sub_sat( tmpF_fx, step_fx );
+ }
+ }
+
+ IF( hCPE->element_mode == IVAS_CPE_MDCT && hCPE->nchan_out == 1 && !is_DTXrate( hCPE->element_brate ) && is_DTXrate( hCPE->last_element_brate ) )
+ {
+ Copy32( sts[0]->prev_synth_buffer32_fx, sts[1]->prev_synth_buffer32_fx, 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 )
+ {
+ Copy32( sts[n]->prev_synth_buffer32_fx + delay_comp_DFT, hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_32, delay_diff );
+ delay_signal_fx( output_fx[n], output_frame, hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_32, delay_diff );
+ ivas_post_proc_fx( NULL, hCPE, n, output_fx[n], output_fx, output_frame, 0 );
+
+ delay_signal_fx( output_fx[n], output_frame, sts[n]->prev_synth_buffer32_fx, delay_comp_DFT );
+ Copy32( hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_32, sts[n]->prev_synth_buffer32_fx + delay_comp_DFT, delay_diff );
+ }
+ ELSE
+ {
+ delay_signal_fx( output_fx[n], output_frame, sts[n]->prev_synth_buffer32_fx, 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++ )
+ {
+ switch ( output_Fs )
+ {
+ case 16000:
+ tmpF_fx = 107374184;
+ break;
+ case 32000:
+ tmpF_fx = 53687092;
+ break;
+ case 48000:
+ tmpF_fx = 35791396;
+ break;
+ default:
+ assert( 0 );
+ }
+ FOR( i = 0; i < delay_cldfb; i++ )
+ {
+ tmp_out_fx[n][i] = Mpy_32_32( tmp_out_fx[n][i], tmpF_fx ) * ( delay_cldfb - i );
+ }
+ }
+ }
+
+ /* cross-fading between DFT OLA memory and TD output */
+ FOR( n = 0; n < nChannels; n++ )
+ {
+ IF( hCPE->element_mode == IVAS_CPE_MDCT )
+ {
+ switch ( output_Fs )
+ {
+ case 16000:
+ tmpF_fx = 71582792;
+ break;
+ case 32000:
+ tmpF_fx = 35791396;
+ break;
+ case 48000:
+ tmpF_fx = 23860930;
+ break;
+ default:
+ assert( 0 );
+ }
+ FOR( i = 0; i < delay_diff; i++ )
+ {
+
+ Word64 res1 = (Word64) output_fx[n][i + delay_comp_DFT] * ( delay_diff - i );
+ Word64 res2 = (Word64) p_output_mem_fx[n][i] * i;
+ Word64 res = W_shr( res1, 6 ) + W_shr( res2, 6 );
+ res = res * tmpF_fx;
+ output_fx[n][i + delay_comp_DFT] = (Word32) W_shr( res, 31 - 6 );
+ }
+ }
+ switch ( output_Fs )
+ {
+ case 16000:
+ tmpF_fx = 107374184;
+ break;
+ case 32000:
+ tmpF_fx = 53687092;
+ break;
+ case 48000:
+ tmpF_fx = 35791396;
+ break;
+ default:
+ assert( 0 );
+ }
+ FOR( i = 0; i < delay_cldfb; i++ )
+ {
+ Word64 res1 = (Word64) tmp_out_fx[n][i] * ( delay_cldfb - i );
+ Word64 res2 = (Word64) output_fx[n][i + delay_comp_TD] * i;
+ Word64 res = W_shr( res1, 6 ) + W_shr( res2, 6 );
+ res = res * tmpF_fx;
+ output_fx[n][i + delay_comp_TD] = (Word32) W_shr( res, 31 - 6 );
+ }
+ }
+ }
+ }
+
+
+ IF( hCPE->hStereoDft != NULL )
+ {
+ IF( hCPE->hStereoDft->hTcxLtpDec != NULL )
+ {
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
+ {
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_out_float[p] = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_out_32[p] / ( 1u << OUTPUT_Q );
+ }
+ FOR( Word32 p = 0; p < TCXLTP_MAX_DELAY; p++ )
+ {
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_in_float[p] = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_in_32[p] / ( 1u << OUTPUT_Q );
+ }
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_post_prev_float = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_post_prev / ONE_IN_Q15;
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_float = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain / ONE_IN_Q15;
+ }
+ }
+ FOR( n = 0; n < CPE_CHANNELS; n++ )
+ {
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
+ {
+ output[n][p] = (float) output_fx[n][p] / ( 1u << 11 );
+ }
+ IF( hCPE->output_mem[n] != NULL )
+ {
+ FOR( Word32 k = 0; k < NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS ); k++ )
+ {
+ hCPE->output_mem[n][k] = (float) hCPE->output_mem_fx[n][k] / ( 1u << 11 );
+ }
+ }
+ IF( hCPE->hCoreCoder[n] != NULL )
+ {
+ IF( hCPE->hCoreCoder[n]->hTcxLtpDec != NULL )
+ {
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_out_float[p] = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_out_32[p] / ( 1u << OUTPUT_Q );
+ }
+ FOR( Word32 p = 0; p < TCXLTP_MAX_DELAY; p++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_in_float[p] = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_in_32[p] / ( 1u << OUTPUT_Q );
+ }
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_post_prev_float = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_post_prev / ONE_IN_Q15;
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_float = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain / ONE_IN_Q15;
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS ); k++ )
+ {
+ hCPE->hCoreCoder[n]->prev_synth_buffer[k] = (float) hCPE->hCoreCoder[n]->prev_synth_buffer32_fx[k] / ( 1 << OUTPUT_Q );
+ }
+ FOR( Word32 k = 0; k < HQ_DELTA_MAX * HQ_DELAY_COMP; k++ )
+ {
+ hCPE->hCoreCoder[n]->delay_buf_out[k] = (float) hCPE->hCoreCoder[n]->delay_buf_out32_fx[k] / ( 1 << OUTPUT_Q );
+ }
+ IF( hCPE->hCoreCoder[n]->hTcxDec != NULL )
+ {
+ FOR( Word32 k = 0; k < 111; k++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_float[k] = (float) hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_32[k] / ( 1 << OUTPUT_Q );
+ }
+ }
+ }
+ IF( hCPE->input_mem[n] != NULL )
+ {
+ FOR( Word32 ind = 0; ind < STEREO_DFT32MS_OVL_16k; ind++ )
+ {
+ hCPE->input_mem_LB[n][ind] = ( (float) hCPE->input_mem_LB_fx[n][ind] / ( 1 << OUTPUT_Q ) );
+ }
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS ); k++ )
+ {
+ hCPE->prev_hb_synth[n][k] = (float) hCPE->prev_hb_synth_fx[n][k] / ( 1 << OUTPUT_Q );
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS ); k++ )
+ {
+ hCPE->prev_synth[n][k] = (float) hCPE->prev_synth_fx[n][k] / ( 1 << OUTPUT_Q );
+ }
+ }
+
+
+ return;
+}
+
+void synchro_synthesis_fixed_clean(
+ const Word16 ivas_total_brate, /* i : IVAS total bitrate */
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *output_fx[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 */
+)
+{
+
+ // Delete below
+ FOR( Word32 n = 0; n < CPE_CHANNELS; n++ )
+ {
+ IF( hCPE->hStereoDft != NULL )
+ {
+ IF( hCPE->hStereoDft->hTcxLtpDec != NULL )
+ {
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
+ {
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_out_32[p] = (Word32) ( hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_out_float[p] * ( 1u << OUTPUT_Q ) );
+ }
+ FOR( Word32 p = 0; p < TCXLTP_MAX_DELAY; p++ )
+ {
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_in_32[p] = (Word32) ( hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_in_float[p] * ( 1u << OUTPUT_Q ) );
+ }
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_post_prev = (Word16) ( hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_post_prev_float * ONE_IN_Q15 );
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain = (Word16) ( hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_float * ONE_IN_Q15 );
+ }
+ }
+ IF( hCPE->hCoreCoder[n] != NULL )
+ {
+ IF( hCPE->hCoreCoder[n]->hTcxLtpDec != NULL )
+ {
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_out_32[p] = (Word32) ( hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_out_float[p] * ( 1u << OUTPUT_Q ) );
+ }
+ FOR( Word32 p = 0; p < TCXLTP_MAX_DELAY; p++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_in_32[p] = (Word32) ( hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_in_float[p] * ( 1u << OUTPUT_Q ) );
+ }
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_post_prev = (Word16) ( hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_post_prev_float * ONE_IN_Q15 );
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain = (Word16) ( hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_float * ONE_IN_Q15 );
+ }
+
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS ); k++ )
+ {
+ hCPE->hCoreCoder[n]->prev_synth_buffer32_fx[k] = (Word32) ( hCPE->hCoreCoder[n]->prev_synth_buffer[k] * ( 1 << OUTPUT_Q ) );
+ }
+ FOR( Word32 k = 0; k < HQ_DELTA_MAX * HQ_DELAY_COMP; k++ )
+ {
+ hCPE->hCoreCoder[n]->delay_buf_out32_fx[k] = (Word32) ( hCPE->hCoreCoder[n]->delay_buf_out[k] * ( 1 << OUTPUT_Q ) );
+ }
+ IF( hCPE->hCoreCoder[n]->hTcxDec != NULL )
+ {
+ FOR( Word32 k = 0; k < 111; k++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_32[k] = (Word32) ( hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_float[k] * ( 1 << OUTPUT_Q ) );
+ }
+ }
+ }
+
+ IF( hCPE->output_mem[n] != NULL )
+ {
+ FOR( Word32 k = 0; k < NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS ); k++ )
+ {
+ hCPE->output_mem_fx[n][k] = (Word32) ( hCPE->output_mem[n][k] * ( 1 << OUTPUT_Q ) );
+ }
+ }
+ IF( hCPE->input_mem[n] != NULL )
+ {
+ FOR( Word32 ind = 0; ind < STEREO_DFT32MS_OVL_16k; ind++ )
+ {
+ hCPE->input_mem_LB_fx[n][ind] = (Word32) ( hCPE->input_mem_LB[n][ind] * ( 1 << OUTPUT_Q ) );
+ }
+ }
+
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS ); k++ )
+ {
+ hCPE->prev_hb_synth_fx[n][k] = (Word32) ( hCPE->prev_hb_synth[n][k] * ( 1 << OUTPUT_Q ) );
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS ); k++ )
+ {
+ hCPE->prev_synth_fx[n][k] = (Word32) ( hCPE->prev_synth[n][k] * ( 1 << OUTPUT_Q ) );
+ }
+ }
+ // till here
+
+ Word16 n, delay_comp_TD, delay_comp_DFT;
+ Word32 output_Fs;
+ Decoder_State **sts;
+ Word16 i, delay_cldfb, dft32ms_ovl;
+
+ Word32 *p_output_mem_fx[CPE_CHANNELS];
+ Word32 tmp_out_fx[CPE_CHANNELS][NS2SA( 48000, DELAY_CLDFB_NS )];
+ Word32 tmp_out_TD_fx[CPE_CHANNELS][STEREO_DFT32MS_OVL_MAX];
+ Word32 tmp_out_TD2_fx[CPE_CHANNELS][STEREO_DFT32MS_OVL_MAX];
+
+ Word16 use_cldfb_for_last_dft;
+ Word16 dft_mono_brate_switch;
+ Word16 delay_diff;
+ Word32 tmpF_fx = 0;
+ 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_fx( hCPE, output_fx[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 = (Word16) ( ( 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_fx[0] != NULL )
+ {
+ FOR( n = 0; n < CPE_CHANNELS; n++ )
+ {
+ p_output_mem_fx[n] = hCPE->output_mem_fx[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_buffer32_fx[i] = p_output_mem_fx[0][i - delay_comp_DFT];
+ }
+
+ FOR( i = delay_comp_TD; i < delay_comp_TD + delay_cldfb; i++ )
+ {
+ tmp_out_fx[0][i - delay_comp_TD] = p_output_mem_fx[0][i - delay_comp_DFT];
+ }
+ }
+
+ IF( hCPE->nchan_out == 1 && hCPE->last_element_mode == IVAS_CPE_MDCT )
+ {
+ FOR( Word32 ind = 0; ind < delay_comp_DFT; ind++ )
+ {
+ Word32 temp = sts[0]->prev_synth_buffer32_fx[ind] + sts[1]->prev_synth_buffer32_fx[ind];
+ sts[0]->prev_synth_buffer32_fx[ind] = Mpy_32_32( temp, INV_SQRT2_FX );
+ }
+ }
+
+ 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. */
+ Copy32( sts[0]->prev_synth_buffer32_fx + delay_comp_DFT, hCPE->hCoreCoder[0]->hTcxDec->FBTCXdelayBuf_32, delay_diff );
+ delay_signal_fx( output_fx[0], output_frame, hCPE->hCoreCoder[0]->hTcxDec->FBTCXdelayBuf_32, delay_diff );
+ }
+
+ IF( hCPE->element_mode != IVAS_CPE_MDCT )
+ {
+ ivas_post_proc_fx( NULL, hCPE, 0, output_fx[0], output_fx, 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_fx( output_fx[n], output_frame, hCPE->prev_synth_fx[n], delay_comp_DFT );
+ }
+ ELSE
+ {
+ delay_signal_fx( output_fx[n], output_frame, sts[n]->prev_synth_buffer32_fx, delay_comp_DFT );
+ }
+ }
+ IF( use_cldfb_for_last_dft )
+ {
+ Copy32( hCPE->hCoreCoder[0]->hTcxDec->FBTCXdelayBuf_32, sts[0]->prev_synth_buffer32_fx + 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 )
+ {
+ Word32 *pPrev_synth_fx;
+ Word32 inv_fade_len_fx = 0;
+ SWITCH( output_Fs )
+ {
+ case 16000:
+ inv_fade_len_fx = 71582792;
+ break;
+ case 32000:
+ inv_fade_len_fx = 35791396;
+ break;
+ case 48000:
+ inv_fade_len_fx = 23860930;
+ break;
+ default:
+ assert( 0 );
+ }
+
+ /* cross-fading between TD synchro memory and the DFT output */
+ IF( sba_dirac_stereo_flag )
+ {
+ pPrev_synth_fx = hCPE->prev_synth_fx[n];
+ }
+ ELSE
+ {
+ pPrev_synth_fx = sts[n]->prev_synth_buffer32_fx;
+ }
+
+ IF( hCPE->last_element_mode != IVAS_CPE_MDCT )
+ {
+ FOR( i = delay_comp_DFT; i < delay_comp_TD; i++ )
+ {
+ Word64 res1 = (Word64) pPrev_synth_fx[i] * ( delay_comp_TD - i );
+ Word64 res2 = (Word64) output_fx[n][i] * ( i - delay_comp_DFT );
+ Word64 res = W_shr( res1, 6 ) + W_shr( res2, 6 );
+ res = res * inv_fade_len_fx;
+ output_fx[n][i] = (Word32) W_shr( res, 31 - 6 );
+ // change 6 to less number to get better precision
+ }
+ }
+ }
+ ELSE IF( dft_mono_brate_switch == -1 )
+ {
+ Word32 inv_fade_len_1_fx = 0;
+ Word32 inv_fade_len_2_fx = 0;
+
+ SWITCH( output_Fs )
+ {
+ case 16000:
+ inv_fade_len_1_fx = 71582792;
+ inv_fade_len_2_fx = 107374184;
+ break;
+ case 32000:
+ inv_fade_len_1_fx = 35791396;
+ inv_fade_len_2_fx = 53687092;
+ break;
+ case 48000:
+ inv_fade_len_1_fx = 23860930;
+ inv_fade_len_2_fx = 35791396;
+ break;
+ default:
+ assert( 0 );
+ }
+ FOR( i = 0; i < delay_diff; i++ )
+ {
+ Word64 res1 = (Word64) output_fx[0][i + delay_comp_DFT] * ( delay_diff - i );
+ Word64 res2 = (Word64) p_output_mem_fx[0][i] * i;
+ Word64 res = W_shr( res1, 6 ) + W_shr( res2, 6 );
+ res = res * inv_fade_len_1_fx;
+ output_fx[0][i + delay_comp_DFT] = (Word32) W_shr( res, 31 - 6 );
+ }
+
+ FOR( i = 0; i < delay_cldfb; i++ )
+ {
+ Word64 res1 = (Word64) tmp_out_fx[0][i] * ( delay_cldfb - i );
+ Word64 res2 = (Word64) output_fx[0][i + delay_comp_TD] * i;
+ Word64 res = W_shr( res1, 6 ) + W_shr( res2, 6 );
+ res = res * inv_fade_len_2_fx;
+ output_fx[0][i + delay_comp_TD] = (Word32) W_shr( res, 31 - 6 );
+ }
+ }
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ * TD/MDCT stereo synchro
+ *----------------------------------------------------------------*/
+
+ IF( sba_dirac_stereo_flag )
+ {
+ // delete the below
+#if 1
+ IF( hCPE->hStereoDft != NULL )
+ {
+ IF( hCPE->hStereoDft->hTcxLtpDec != NULL )
+ {
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
+ {
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_out_float[p] = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_out_32[p] / ( 1u << OUTPUT_Q );
+ }
+ FOR( Word32 p = 0; p < TCXLTP_MAX_DELAY; p++ )
+ {
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_in_float[p] = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_in_32[p] / ( 1u << OUTPUT_Q );
+ }
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_post_prev_float = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_post_prev / ONE_IN_Q15;
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_float = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain / ONE_IN_Q15;
+ }
+ }
+ FOR( n = 0; n < CPE_CHANNELS; n++ )
+ {
+ IF( hCPE->output_mem[n] != NULL )
+ {
+ FOR( Word32 k = 0; k < NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS ); k++ )
+ {
+ hCPE->output_mem[n][k] = (float) hCPE->output_mem_fx[n][k] / ( 1u << 11 );
+ }
+ }
+ IF( hCPE->hCoreCoder[n] != NULL )
+ {
+ IF( hCPE->hCoreCoder[n]->hTcxLtpDec != NULL )
+ {
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_out_float[p] = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_out_32[p] / ( 1u << OUTPUT_Q );
+ }
+ FOR( Word32 p = 0; p < TCXLTP_MAX_DELAY; p++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_in_float[p] = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_in_32[p] / ( 1u << OUTPUT_Q );
+ }
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_post_prev_float = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_post_prev / ONE_IN_Q15;
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_float = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain / ONE_IN_Q15;
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS ); k++ )
+ {
+ hCPE->hCoreCoder[n]->prev_synth_buffer[k] = (float) hCPE->hCoreCoder[n]->prev_synth_buffer32_fx[k] / ( 1 << OUTPUT_Q );
+ }
+ FOR( Word32 k = 0; k < HQ_DELTA_MAX * HQ_DELAY_COMP; k++ )
+ {
+ hCPE->hCoreCoder[n]->delay_buf_out[k] = (float) hCPE->hCoreCoder[n]->delay_buf_out32_fx[k] / ( 1 << OUTPUT_Q );
+ }
+ IF( hCPE->hCoreCoder[n]->hTcxDec != NULL )
+ {
+ FOR( Word32 k = 0; k < 111; k++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_float[k] = (float) hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_32[k] / ( 1 << OUTPUT_Q );
+ }
+ }
+ }
+ IF( hCPE->input_mem[n] != NULL )
+ {
+ FOR( Word32 ind = 0; ind < STEREO_DFT32MS_OVL_16k; ind++ )
+ {
+ hCPE->input_mem_LB[n][ind] = ( (float) hCPE->input_mem_LB_fx[n][ind] / ( 1 << OUTPUT_Q ) );
+ }
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS ); k++ )
+ {
+ hCPE->prev_hb_synth[n][k] = (float) hCPE->prev_hb_synth_fx[n][k] / ( 1 << OUTPUT_Q );
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS ); k++ )
+ {
+ hCPE->prev_synth[n][k] = (float) hCPE->prev_synth_fx[n][k] / ( 1 << OUTPUT_Q );
+ }
+ }
+#endif
+
+ // keep return
+ 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_fx[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_buffer32_fx[i] = p_output_mem_fx[n][i - delay_comp_DFT];
+ }
+
+ FOR( i = delay_comp_TD; i < delay_comp_TD + delay_cldfb; i++ )
+ {
+ tmp_out_fx[n][i - delay_comp_TD] = p_output_mem_fx[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 )
+ {
+ Copy32( sts[0]->prev_synth_buffer32_fx, sts[1]->prev_synth_buffer32_fx, delay_comp_TD );
+ Copy32( tmp_out_fx[0], tmp_out_fx[1], delay_cldfb );
+ Copy32( p_output_mem_fx[0], p_output_mem_fx[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 )
+ {
+ L_lerp_fx_q11( hCPE->input_mem_LB_fx[n], tmp_out_TD_fx[n], dft32ms_ovl, NS2SA( sts[n]->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) );
+ }
+ ELSE /* TCX/HQ core */
+ {
+ L_lerp_fx_q11( hCPE->input_mem_LB_fx[n], tmp_out_TD_fx[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_fx[n][i] = sts[n]->delay_buf_out32_fx[i - delay_diff];
+ }
+ }
+ }
+
+ IF( hCPE->nchan_out == CPE_CHANNELS )
+ {
+ /* upmix the resampled LB / the TCX synchro memory */
+ tdm_upmix_plain_fx( tmp_out_TD2_fx[0], tmp_out_TD2_fx[1], tmp_out_TD_fx[0], tmp_out_TD_fx[1], tdm_ratio_tabl_fx[hCPE->hStereoTD->tdm_last_ratio_idx], tdm_den_ratio_tabl_fx[hCPE->hStereoTD->tdm_last_ratio_idx], 0, dft32ms_ovl, 1 );
+ }
+ ELSE
+ {
+ Copy32( tmp_out_TD_fx[0], tmp_out_TD2_fx[0], dft32ms_ovl );
+ }
+
+ FOR( n = 0; n < hCPE->nchan_out; n++ )
+ {
+ IF( sts[0]->core == ACELP_CORE ) /* ACELP core in primary channel */
+ {
+ SWITCH( output_Fs )
+ {
+ case 16000:
+ tmpF_fx = 71582792;
+ break;
+ case 32000:
+ tmpF_fx = 35791396;
+ break;
+ case 48000:
+ tmpF_fx = 23860930;
+ break;
+ default:
+ assert( 0 );
+ }
+ /* 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++ )
+ {
+
+ Word64 res1 = (Word64) output_fx[n][output_frame - dft32ms_ovl + delay_cldfb + i] * ( delay_diff - i );
+ Word64 res2 = (Word64) tmp_out_TD2_fx[n][i] * i;
+ Word64 res = W_shr( res1, 6 ) + W_shr( res2, 6 );
+ res = res * tmpF_fx;
+ p_output_mem_fx[n][i] = (Word32) W_shr( res, 31 - 6 );
+ }
+ }
+ ELSE /* TCX core */
+ {
+ /* reconstruct the 3.125 - 1.25 ms OLA part */
+ FOR( i = 0; i < delay_diff; i++ )
+ {
+ p_output_mem_fx[n][i] = output_fx[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_fx[n][i] = tmp_out_TD2_fx[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 )
+ {
+ Word32 step_fx = 0;
+ tmpF_fx = ONE_IN_Q31;
+ SWITCH( output_Fs )
+ {
+ case 16000:
+ step_fx = 33554432;
+ break;
+ case 32000:
+ step_fx = 16777216;
+ break;
+ case 48000:
+ step_fx = 11184811;
+ break;
+ default:
+ assert( 0 );
+ }
+ /* FOR the first switching frame from DFT to TD, downmix memory too */
+ FOR( n = 0; n < delay_comp_TD; n++ )
+ {
+ sts[0]->prev_synth_buffer32_fx[n] = Mpy_32_32( sts[0]->prev_synth_buffer32_fx[n], tmpF_fx );
+ tmpF_fx = L_sub_sat( tmpF_fx, step_fx );
+ }
+ }
+
+ IF( hCPE->element_mode == IVAS_CPE_MDCT && hCPE->nchan_out == 1 && !is_DTXrate( hCPE->element_brate ) && is_DTXrate( hCPE->last_element_brate ) )
+ {
+ Copy32( sts[0]->prev_synth_buffer32_fx, sts[1]->prev_synth_buffer32_fx, 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 )
+ {
+ Copy32( sts[n]->prev_synth_buffer32_fx + delay_comp_DFT, hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_32, delay_diff );
+ delay_signal_fx( output_fx[n], output_frame, hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_32, delay_diff );
+ ivas_post_proc_fx( NULL, hCPE, n, output_fx[n], output_fx, output_frame, 0 );
+
+ delay_signal_fx( output_fx[n], output_frame, sts[n]->prev_synth_buffer32_fx, delay_comp_DFT );
+ Copy32( hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_32, sts[n]->prev_synth_buffer32_fx + delay_comp_DFT, delay_diff );
+ }
+ ELSE
+ {
+ delay_signal_fx( output_fx[n], output_frame, sts[n]->prev_synth_buffer32_fx, 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++ )
+ {
+ SWITCH( output_Fs )
+ {
+ case 16000:
+ tmpF_fx = 107374184;
+ break;
+ case 32000:
+ tmpF_fx = 53687092;
+ break;
+ case 48000:
+ tmpF_fx = 35791396;
+ break;
+ default:
+ assert( 0 );
+ }
+ FOR( i = 0; i < delay_cldfb; i++ )
+ {
+ tmp_out_fx[n][i] = Mpy_32_32( tmp_out_fx[n][i], tmpF_fx ) * ( delay_cldfb - i );
+ }
+ }
+ }
+
+ /* cross-fading between DFT OLA memory and TD output */
+ FOR( n = 0; n < nChannels; n++ )
+ {
+ IF( hCPE->element_mode == IVAS_CPE_MDCT )
+ {
+ SWITCH( output_Fs )
+ {
+ case 16000:
+ tmpF_fx = 71582792;
+ break;
+ case 32000:
+ tmpF_fx = 35791396;
+ break;
+ case 48000:
+ tmpF_fx = 23860930;
+ break;
+ default:
+ assert( 0 );
+ }
+ FOR( i = 0; i < delay_diff; i++ )
+ {
+
+ Word64 res1 = (Word64) output_fx[n][i + delay_comp_DFT] * ( delay_diff - i );
+ Word64 res2 = (Word64) p_output_mem_fx[n][i] * i;
+ Word64 res = W_shr( res1, 6 ) + W_shr( res2, 6 );
+ res = res * tmpF_fx;
+ output_fx[n][i + delay_comp_DFT] = (Word32) W_shr( res, 31 - 6 );
+ }
+ }
+ SWITCH( output_Fs )
+ {
+ case 16000:
+ tmpF_fx = 107374184;
+ break;
+ case 32000:
+ tmpF_fx = 53687092;
+ break;
+ case 48000:
+ tmpF_fx = 35791396;
+ break;
+ default:
+ assert( 0 );
+ }
+ FOR( i = 0; i < delay_cldfb; i++ )
+ {
+ Word64 res1 = (Word64) tmp_out_fx[n][i] * ( delay_cldfb - i );
+ Word64 res2 = (Word64) output_fx[n][i + delay_comp_TD] * i;
+ Word64 res = W_shr( res1, 6 ) + W_shr( res2, 6 );
+ res = res * tmpF_fx;
+ output_fx[n][i + delay_comp_TD] = (Word32) W_shr( res, 31 - 6 );
+ }
+ }
+ }
+ }
+
+
+ IF( hCPE->hStereoDft != NULL )
+ {
+ IF( hCPE->hStereoDft->hTcxLtpDec != NULL )
+ {
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
+ {
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_out_float[p] = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_out_32[p] / ( 1u << OUTPUT_Q );
+ }
+ FOR( Word32 p = 0; p < TCXLTP_MAX_DELAY; p++ )
+ {
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_in_float[p] = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_mem_in_32[p] / ( 1u << OUTPUT_Q );
+ }
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_post_prev_float = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_post_prev / ONE_IN_Q15;
+ hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain_float = (float) hCPE->hStereoDft->hTcxLtpDec->tcxltp_gain / ONE_IN_Q15;
+ }
+ }
+ FOR( n = 0; n < CPE_CHANNELS; n++ )
+ {
+ IF( hCPE->output_mem[n] != NULL )
+ {
+ FOR( Word32 k = 0; k < NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS ); k++ )
+ {
+ hCPE->output_mem[n][k] = (float) hCPE->output_mem_fx[n][k] / ( 1u << 11 );
+ }
+ }
+ IF( hCPE->hCoreCoder[n] != NULL )
+ {
+ IF( hCPE->hCoreCoder[n]->hTcxLtpDec != NULL )
+ {
+ FOR( Word32 p = 0; p < L_FRAME48k; p++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_out_float[p] = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_out_32[p] / ( 1u << OUTPUT_Q );
+ }
+ FOR( Word32 p = 0; p < TCXLTP_MAX_DELAY; p++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_in_float[p] = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_mem_in_32[p] / ( 1u << OUTPUT_Q );
+ }
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_post_prev_float = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_post_prev / ONE_IN_Q15;
+ hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain_float = (float) hCPE->hCoreCoder[n]->hTcxLtpDec->tcxltp_gain / ONE_IN_Q15;
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS ); k++ )
+ {
+ hCPE->hCoreCoder[n]->prev_synth_buffer[k] = (float) hCPE->hCoreCoder[n]->prev_synth_buffer32_fx[k] / ( 1 << OUTPUT_Q );
+ }
+ FOR( Word32 k = 0; k < HQ_DELTA_MAX * HQ_DELAY_COMP; k++ )
+ {
+ hCPE->hCoreCoder[n]->delay_buf_out[k] = (float) hCPE->hCoreCoder[n]->delay_buf_out32_fx[k] / ( 1 << OUTPUT_Q );
+ }
+ IF( hCPE->hCoreCoder[n]->hTcxDec != NULL )
+ {
+ FOR( Word32 k = 0; k < 111; k++ )
+ {
+ hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_float[k] = (float) hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_32[k] / ( 1 << OUTPUT_Q );
+ }
+ }
+ }
+ IF( hCPE->input_mem[n] != NULL )
+ {
+ FOR( Word32 ind = 0; ind < STEREO_DFT32MS_OVL_16k; ind++ )
+ {
+ hCPE->input_mem_LB[n][ind] = ( (float) hCPE->input_mem_LB_fx[n][ind] / ( 1 << OUTPUT_Q ) );
+ }
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS ); k++ )
+ {
+ hCPE->prev_hb_synth[n][k] = (float) hCPE->prev_hb_synth_fx[n][k] / ( 1 << OUTPUT_Q );
+ }
+ FOR( Word32 k = 0; k < NS2SA( 48000, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS ); k++ )
+ {
+ hCPE->prev_synth[n][k] = (float) hCPE->prev_synth_fx[n][k] / ( 1 << OUTPUT_Q );
+ }
+ }
+
+
+ return;
+}
+
+#endif
+/*-------------------------------------------------------------------*
+ * Function stereo_switching_dec()
+ *
+ * Handling of memories in case of CPE modes switching
+ *-------------------------------------------------------------------*/
+
+void stereo_switching_dec(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ const int32_t ivas_total_brate /* i : IVAS total bitrate */
+)
+{
+ int16_t i, n;
+ int16_t dft32ms_ovl;
+ Decoder_State **sts;
+ float tmpF;
+ int16_t delay_comp_TD;
+
+ sts = hCPE->hCoreCoder;
+
+ delay_comp_TD = NS2SA( sts[0]->output_Fs, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS );
+
+ /* prevent CPE mode switching in the first received frame */
+ if ( sts[0]->ini_frame == 0 )
+ {
+ hCPE->last_element_mode = hCPE->element_mode;
+ hCPE->stereo_switching_counter = 10;
+ hCPE->NbFrameMod = 7;
+ hCPE->lt_es_em = 0.0f;
+ }
+
+ if ( hCPE->element_mode == hCPE->last_element_mode )
+ {
+ hCPE->stereo_switching_counter++;
+ hCPE->stereo_switching_counter = min( 10, hCPE->stereo_switching_counter );
+ }
+ else
+ {
+ hCPE->stereo_switching_counter = 0;
+ }
+
+ if ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->nchan_out == 1 && hCPE->element_brate >= IVAS_32k && hCPE->last_element_brate <= IVAS_24k4 )
+ {
+ dft32ms_ovl = (int16_t) ( ( STEREO_DFT32MS_OVL_MAX * sts[0]->output_Fs ) / 48000 );
+ set_zero( hCPE->output_mem[0], dft32ms_ovl );
+ }
+
+ if ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->last_element_mode != IVAS_CPE_DFT && hCPE->hCoreCoder[0]->ini_frame > 0 )
+ {
+ /* windowing the OLA memory */
+ dft32ms_ovl = (int16_t) ( ( STEREO_DFT32MS_OVL_MAX * sts[0]->output_Fs ) / 48000 );
+ for ( n = 0; n < CPE_CHANNELS; n++ )
+ {
+ if ( hCPE->last_element_mode == IVAS_CPE_MDCT )
+ {
+ /* copy memories from previous MDCT Stereo frame to output_mem */
+ mvr2r( hCPE->input_mem[n], hCPE->output_mem[n], dft32ms_ovl );
+ }
+
+ if ( ivas_total_brate > IVAS_SID_5k2 || n == 0 || hCPE->last_element_mode != IVAS_CPE_TD || hCPE->nchan_out == 1 )
+ {
+ for ( i = 0; i < dft32ms_ovl; i++ )
+ {
+ hCPE->output_mem[n][i] *= hCPE->hStereoDft->win32ms[STEREO_DFT32MS_STEP * ( dft32ms_ovl - 1 - i )];
+ }
+ }
+ else
+ {
+ tmpF = 1.0f / hCPE->hStereoTCA->prevTargetGain;
+ for ( i = 0; i < dft32ms_ovl; i++ )
+ {
+ hCPE->output_mem[n][i] *= tmpF * hCPE->hStereoDft->win32ms[STEREO_DFT32MS_STEP * ( dft32ms_ovl - 1 - i )];
+ }
+ for ( i = 0; i < delay_comp_TD; i++ )
+ {
+ hCPE->hCoreCoder[1]->prev_synth_buffer[i] *= tmpF;
+ }
+ for ( i = 0; i < L_DEC_MEM_LEN_ICA; i++ )
+ {
+ hCPE->hStereoTCA->memChanR[i] *= tmpF;
+ }
+ }
+ }
+
+ if ( hCPE->last_element_mode == IVAS_CPE_MDCT )
+ {
+ /* create passive downmix of MDCT Stereo memories for DFT input memory */
+ v_add( hCPE->input_mem_LB[0], hCPE->input_mem_LB[1], hCPE->input_mem_LB[0], STEREO_DFT32MS_OVL_16k );
+ v_multc( hCPE->input_mem_LB[0], 0.5f, hCPE->input_mem_LB[0], STEREO_DFT32MS_OVL_16k );
+
+ v_add( hCPE->input_mem[0], hCPE->input_mem[1], hCPE->input_mem[0], dft32ms_ovl );
+ v_multc( hCPE->input_mem[0], 0.5f, hCPE->input_mem[0], dft32ms_ovl );
+
+ if ( hCPE->nchan_out == 1 )
+ {
+ v_add( hCPE->output_mem[0], hCPE->output_mem[1], hCPE->output_mem[0], dft32ms_ovl );
+ v_multc( hCPE->output_mem[0], INV_SQRT_2, hCPE->output_mem[0], dft32ms_ovl );
+ }
+ }
+
+ /* Update the side_gain[] parameters */
+ if ( hCPE->last_element_mode != IVAS_CPE_MDCT )
+ {
+ tmpF = 0;
+ if ( hCPE->hStereoTCA != NULL )
+ {
+ tmpF = usdequant( hCPE->hStereoTCA->indx_ica_gD, STEREO_TCA_GDMIN, STEREO_TCA_GDSTEP );
+ }
+
+ set_f( hCPE->hStereoDft->side_gain + STEREO_DFT_NBDIV * STEREO_DFT_BAND_MAX, tmpF, STEREO_DFT_BAND_MAX );
+ }
+
+ /* reset residual coding / ESF (secondary channel) */
+ set_zero( hCPE->hStereoDft->res_cod_mem, STEREO_DFT_OVL_8k );
+ set_zero( hCPE->input_mem[1], NS2SA( sts[0]->output_Fs, STEREO_DFT32MS_OVL_NS ) );
+ }
+
+ if ( hCPE->element_mode == IVAS_CPE_TD && hCPE->last_element_mode != IVAS_CPE_TD && hCPE->hCoreCoder[0]->ini_frame > 0 )
+ {
+ hCPE->hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_MID_IS_PRIM;
+ hCPE->hStereoTD->tdm_last_SM_flag = 0;
+ hCPE->hStereoTD->tdm_prev_last_SM_flag = 0;
+
+ /* First frame after DFT frame AND the content is uncorrelated or xtalk -> the primary channel is forced to left */
+ if ( hCPE->hStereoTD->tdm_LRTD_flag == 1 )
+ {
+ hCPE->hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_LEFT_IS_PRIM;
+ }
+ }
+
+ /* no secondary channel in the previous frame -> memory resets */
+ if ( hCPE->element_mode > IVAS_CPE_DFT && hCPE->last_element_mode == IVAS_CPE_DFT )
+ {
+ if ( hCPE->last_element_brate <= IVAS_SID_5k2 && hCPE->nchan_out == 2 )
+ {
+ /* reset CLDFB memories */
+ cldfb_reset_memory_ivas( sts[0]->cldfbAna );
+ cldfb_reset_memory_ivas( sts[0]->cldfbBPF );
+ cldfb_reset_memory_ivas( sts[0]->cldfbSyn );
+
+ sts[0]->mem_deemph = 0;
+
+ sts[0]->tilt_code = 0.0f;
+ sts[0]->gc_threshold = 0.0f;
+
+ set_f( sts[0]->mem_syn1, 0, M );
+ set_f( sts[0]->mem_syn2, 0, M );
+ set_f( sts[0]->mem_syn3, 0, M );
+ set_f( sts[0]->mem_syn_r_float, 0.0f, L_SYN_MEM );
+
+ sts[1]->last_L_frame = sts[0]->last_L_frame;
+
+ /* reset PCh memories */
+ set_f( sts[0]->old_exc, 0, L_EXC_MEM_DEC );
+ set_f( sts[0]->lsf_old, 0, M );
+ set_f( sts[0]->lsp_old, 0, M );
+ }
+ sts[1]->last_extl = -1;
+
+ sts[1]->prev_bfi = sts[0]->prev_bfi;
+
+ set_f( sts[1]->old_pitch_buf, (float) L_SUBFR, 2 * NB_SUBFR16k );
+ sts[1]->old_fpitchFB_float = 2 * (float) L_SUBFR;
+
+ /* reset CLDFB memories */
+ cldfb_reset_memory_ivas( sts[1]->cldfbAna );
+ cldfb_reset_memory_ivas( sts[1]->cldfbBPF );
+ cldfb_reset_memory_ivas( sts[1]->cldfbSyn );
+
+ sts[1]->mem_deemph = 0;
+
+ sts[1]->tilt_code = 0.0f;
+ sts[1]->gc_threshold = 0.0f;
+
+ set_f( sts[1]->mem_syn1, 0, M );
+ set_f( sts[1]->mem_syn2, 0, M );
+ set_f( sts[1]->mem_syn3, 0, M );
+ set_f( sts[1]->mem_syn_r_float, 0.0f, L_SYN_MEM );
+
+ sts[1]->last_L_frame = sts[0]->last_L_frame;
+
+ /* populate PCh memories into the SCh */
mvr2r( sts[0]->old_exc, sts[1]->old_exc, L_EXC_MEM_DEC );
mvr2r( sts[0]->lsf_old, sts[1]->lsf_old, M );
mvr2r( sts[0]->lsp_old, sts[1]->lsp_old, M );
@@ -2310,6 +3763,105 @@ static float ncross_corr_self(
return c_c;
}
+static Word32 ncross_corr_self_fx(
+ Word32 *signal_fx,
+ const Word16 x,
+ const Word16 y,
+ const Word16 corr_len,
+ const Word16 subsampling )
+{
+ Word64 c_c_fx;
+ Word32 c_c_fx_return;
+ Word16 c_c_fx_q;
+ Word64 energy_xy_fx, energy_x_fx, energy_y_fx;
+ uint16_t j;
+ Word32 *signal_a_fx, *signal_b_fx;
+ Word32 temp_x, temp_y;
+ Word16 headroom_left_x, headroom_left_y;
+ Word16 x_inv_q, y_inv_q;
+ Word16 x_q, y_q;
+ Word16 res_q;
+ c_c_fx = 0;
+ energy_x_fx = 0;
+ energy_y_fx = 0;
+ signal_a_fx = &signal_fx[x];
+ signal_b_fx = &signal_fx[y];
+ FOR ( j = 0; j < corr_len; j += subsampling )
+ {
+ c_c_fx += ( (Word64) ( signal_a_fx[j] ) * ( signal_b_fx[j] ) );
+ energy_x_fx += (Word64) ( signal_a_fx[j] ) * ( signal_a_fx[j] );
+ energy_y_fx += (Word64) ( signal_b_fx[j] ) * ( signal_b_fx[j] );
+ }
+
+ headroom_left_x = W_norm( energy_x_fx );
+ headroom_left_y = W_norm( energy_y_fx );
+ IF ( headroom_left_x < 32 )
+ {
+ energy_x_fx = W_shr( energy_x_fx, (Word16)( 32 - headroom_left_x ) );
+ x_q = (Word16)( 31 - ( ( 2 * OUTPUT_Q ) - ( 32 - headroom_left_x ) ) );
+ }
+ ELSE
+ {
+ x_q = 31 - ( 2 * OUTPUT_Q );
+ }
+ IF ( headroom_left_y < 32 )
+ {
+ energy_y_fx = W_shr( energy_y_fx, (Word16)( 32 - headroom_left_y ) );
+ y_q = (Word16)( 31 - ( ( 2 * OUTPUT_Q ) - ( 32 - headroom_left_y ) ) );
+ }
+ ELSE
+ {
+ y_q = 31 - ( 2 * OUTPUT_Q );
+ }
+
+ x_inv_q = x_q;
+ y_inv_q = y_q;
+
+ temp_x = Sqrt32((Word32)energy_x_fx, &x_q );
+ if ( x_q < 0 )
+ {
+ temp_x = L_shr( temp_x, -1 * x_q );
+ x_q = 0;
+ }
+
+ temp_y = Sqrt32((Word32)energy_y_fx, &y_q );
+ IF ( y_q < 0 )
+ {
+ temp_y = L_shr( temp_y, -1 * y_q );
+ y_q = 0;
+ }
+
+ energy_xy_fx = Mpy_32_32( temp_x, temp_y );
+ res_q = y_q + x_q;
+
+ IF ( ( energy_xy_fx < L_shr( ONE_IN_Q31, (Word16)res_q ) ) || energy_xy_fx == 0 )
+ {
+ energy_xy_fx = ONE_IN_Q31; /* conceal silent frames */
+ res_q = 0;
+ c_c_fx = W_shl( c_c_fx, 31 - ( 2 * OUTPUT_Q ) );
+ }
+ ELSE
+ {
+ Word32 temp_x_inv = ISqrt32( (Word32)energy_x_fx, &x_inv_q );
+ Word32 temp_y_inv = ISqrt32((Word32)energy_y_fx, &y_inv_q );
+ Word16 headroom_left_c_c;
+ energy_xy_fx = (Word32)Mpy_32_32( temp_x_inv, temp_y_inv );
+ res_q = x_inv_q + y_inv_q;
+ headroom_left_c_c = W_norm( c_c_fx );
+ c_c_fx_q = OUTPUT_Q * 2;
+ IF( headroom_left_c_c < 32 )
+ {
+ c_c_fx = W_shr( c_c_fx, (Word16)(32 - headroom_left_c_c) );
+ c_c_fx_q = c_c_fx_q - ( 32 - headroom_left_c_c );
+ }
+ c_c_fx = (Word64)Mpy_32_32( (Word32)c_c_fx, (Word32)energy_xy_fx );
+ c_c_fx_q = (Word16)c_c_fx_q + ( 31 - res_q ) - 31;
+ c_c_fx = (Word32)W_shl_sat_l( c_c_fx, (Word16)(31 - c_c_fx_q) );
+ }
+
+ c_c_fx_return = (Word32)c_c_fx;
+ return c_c_fx_return;
+}
/*-------------------------------------------------------------------*
* Function smooth_dft2td_transition()
@@ -2463,3 +4015,181 @@ void smooth_dft2td_transition(
return;
}
+
+#ifdef IVAS_FLOAT_FIXED
+void smooth_dft2td_transition_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *output_fx[CPE_CHANNELS], /* i/o: synthesis @external Fs */
+ const Word16 output_frame /* i : output frame lenght */
+)
+{
+
+ //Delete below
+ for (int n = 0; n < hCPE->nchan_out; n++)
+ {
+ FOR(Word16 lp = 0; lp < 12; lp++)
+ {
+ hCPE->hCoreCoder[n]->old_pitch_buf_fx[lp] = (Word32)(hCPE->hCoreCoder[n]->old_pitch_buf[lp] * (1u << 16));
+ }
+ }
+
+ Decoder_State **sts;
+ Word16 ipit, i, ipit_max, ipit_min, idiff, ilen, j, ch, lsearch, corr_len, subsampl;
+ Word32 flen_fx, ftmp_corr_fx, fmaxcorr_fx, fac_fs_fx;
+ Word32 tmp_out_fx[L_FRAME48k + L_FRAME48k / 2], tmp_out2_fx[L_FRAME48k], *ptO2_fx, *ptO_fx, *pt1_fx, *ptE_fx;
+
+ IF ( hCPE == NULL )
+ {
+ return;
+ }
+
+ /* initialization */
+ sts = hCPE->hCoreCoder;
+ IF ( ( hCPE->element_mode == IVAS_CPE_TD && ( hCPE->last_element_mode == IVAS_CPE_DFT || hCPE->last_element_mode == IVAS_CPE_MDCT ) && ( sts[0]->clas_dec == VOICED_CLAS && sts[0]->coder_type < TRANSITION && sts[0]->coder_type > UNVOICED && sts[0]->last_coder_type > UNVOICED && sts[1]->coder_type > UNVOICED ) ) )
+ {
+ /* length of OVA */
+ ilen = output_frame / 2;
+
+ /* correlation length */
+ corr_len = output_frame / 20;
+ subsampl = 4;
+
+ FOR ( ch = 0; ch < hCPE->nchan_out; ch++ )
+ {
+ /* core to external sampling frequency ratio */
+ Word16 q = norm_l(output_frame);
+ Word32 check = BASOP_Util_Divide3232_Scale(output_frame, sts[ch]->L_frame, &q);
+ fac_fs_fx = check * (1 << (26 - (15 - q)));
+ /* Find minimum and maximum pitch*/
+ ipit_min = minimum_32_fx( sts[ch]->old_pitch_buf_fx + 4, 4, &flen_fx) + 4;
+ ipit_max = maximum_32_fx( sts[ch]->old_pitch_buf_fx + 4, 4, &flen_fx) + 4;
+ ipit_min = (Word16)L_shr(L_add(Mpy_32_32( sts[ch]->old_pitch_buf_fx[ipit_min], fac_fs_fx ), ONE_IN_Q10 ),11);
+ ipit_max = (Word16)L_shr(L_add(Mpy_32_32(sts[ch]->old_pitch_buf_fx[ipit_max], fac_fs_fx), ONE_IN_Q10),11);
+
+ IF ( ( ipit_max + corr_len ) > ilen ) /*ensure the search is performed on the available memory*/
+ {
+ continue;
+ }
+
+ lsearch = ipit_max - ipit_min + corr_len;
+ lsearch = min( lsearch, output_frame / 4 );
+
+ /* ptr init for search of the best correlation in the past frame */
+ ptE_fx = hCPE->prev_synth_chs_fx[ch] + output_frame - ipit_max - corr_len;
+
+ idiff = 0;
+ fmaxcorr_fx = -ONE_IN_Q31;
+ FOR ( i = 0; i < lsearch; i++ )
+ {
+ ftmp_corr_fx = ncross_corr_self_fx(ptE_fx, i, ipit_max, corr_len, subsampl);
+ IF (ftmp_corr_fx > fmaxcorr_fx)
+ {
+ idiff = i;
+ }
+ fmaxcorr_fx = max( fmaxcorr_fx, ftmp_corr_fx );
+ }
+
+ ipit = ipit_max - idiff;
+
+ ptO_fx = tmp_out_fx + output_frame;
+
+ /* If the correlation is too low, don't use the prediction */
+ IF ( fmaxcorr_fx < DFT2TD_CORR_THRESH_FX )
+ {
+ Copy32( &output_fx[ch][0], ptO_fx, ilen );
+ }
+ ELSE
+ {
+ Copy32( hCPE->prev_synth_chs_fx[ch], tmp_out_fx, output_frame );
+ pt1_fx = tmp_out_fx + output_frame - ipit;
+ FOR ( i = 0; i < ilen; i++ )
+ {
+ ptO_fx[i] = pt1_fx[i];
+ }
+ }
+
+ /* Set buffer for the reserved buffer of the current frame */
+ ptO2_fx = tmp_out2_fx + output_frame - ilen;
+ set32_fx( tmp_out2_fx + output_frame - ilen, 0, ilen );
+ FOR ( i = 0; i < output_frame; i++ )
+ {
+ tmp_out2_fx[i] = output_fx[ch][output_frame - 1 - i];
+ }
+ /* ptr init for search of the best correlation of the current frame */
+ ptE_fx = ptO2_fx - ( ipit_max + corr_len );
+
+ idiff = 0;
+ fmaxcorr_fx = -ONE_IN_Q31;
+ FOR ( i = 0; i < lsearch; i++ )
+ {
+ ftmp_corr_fx = ncross_corr_self_fx(ptE_fx, i, ipit_max, corr_len, subsampl);
+ IF (ftmp_corr_fx > fmaxcorr_fx)
+ {
+ idiff = i;
+ }
+ fmaxcorr_fx = max( fmaxcorr_fx, ftmp_corr_fx);
+ }
+
+
+ ipit = ipit_max - idiff;
+
+ /* If the correlation is too low, don't use the prediction */
+ IF ( fmaxcorr_fx > DFT2TD_CORR_THRESH_FX )
+ {
+ pt1_fx = tmp_out2_fx + output_frame - ilen - ipit;
+ FOR ( i = 0; i < ilen; i++ )
+ {
+ ptO2_fx[i] = pt1_fx[i];
+ }
+ }
+
+ /* perform OVA between predicted signals */
+ SWITCH (ilen)
+ {
+ case 160:
+ flen_fx = 13421772;
+ break;
+ case 320:
+ flen_fx = 6710886;
+ break;
+ case 480:
+ flen_fx = 4473924;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ FOR ( i = 0; i < 4; i++ )
+ {
+ Word64 temp_a = W_shr(((4 - i) * (Word64)output_fx[ch][i] + i * ptO_fx[i]), 2)* (ilen - i);
+ Word64 temp_b = tmp_out2_fx[output_frame - 1 - i] * i;
+ output_fx[ch][i] = (Word32)W_shr((W_add(temp_a, temp_b) * flen_fx), 31);
+ }
+ FOR ( ; i < ilen - 4; i++ )
+ {
+ Word64 temp_a = (Word64)ptO_fx[i] * (ilen - i);
+ Word64 temp_b = (Word64)tmp_out2_fx[output_frame - 1 - i] * i;
+ output_fx[ch][i] = (Word32)W_shr((W_add(temp_a, temp_b) * flen_fx), 31);
+ }
+ j = 0;
+ FOR ( ; i < ilen; i++ )
+ {
+ Word64 temp_a = (Word64)ptO_fx[i] * (ilen - i);
+ Word64 temp_b = W_shr((W_add((Word64)(4 - j) * tmp_out2_fx[output_frame - 1 - i], (Word64)j * output_fx[ch][i]) * i), 2);
+ output_fx[ch][i] = (Word32)W_shr((W_add(temp_a, temp_b) * flen_fx), 31);
+ j++;
+ }
+ }
+ }
+ ELSE IF ( hCPE->element_mode == IVAS_CPE_DFT )
+ {
+ /* Updates */
+ FOR ( ch = 0; ch < hCPE->nchan_out; ch++ )
+ {
+ Copy32( output_fx[ch], hCPE->prev_synth_chs_fx[ch], output_frame );
+ }
+ }
+
+ return;
+}
+#endif
\ No newline at end of file
diff --git a/lib_dec/ivas_stereo_td_dec.c b/lib_dec/ivas_stereo_td_dec.c
index fafdc138a628b7881e7e725675f8950fdc645af3..82a1655b4960df88e9001ce0deb4e6744eac5b4c 100644
--- a/lib_dec/ivas_stereo_td_dec.c
+++ b/lib_dec/ivas_stereo_td_dec.c
@@ -36,6 +36,8 @@
#include "cnst.h"
#include "rom_com.h"
#include "prot.h"
+#include "prot_fx1.h"
+#include "prot_fx2.h"
#include "ivas_prot.h"
#include "ivas_rom_com.h"
#include "ivas_cnst.h"
@@ -75,12 +77,50 @@ void stereo_td_init_dec(
}
+void stereo_td_init_dec_fx(
+ STEREO_TD_DEC_DATA_HANDLE hStereoTD, /* i/o: TD stereo decoder handle */
+ const int16_t last_element_mode /* i : last element mode */
+)
+{
+ hStereoTD->tdm_SM_flag = 0;
+ hStereoTD->tdm_last_SM_flag = 0;
+ hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_MID_IS_PRIM;
+ hStereoTD->tdm_prev_last_SM_flag = 0;
+ hStereoTD->tdm_LRTD_flag = 0;
+ hStereoTD->prevSP_ratio = 0.5f;
+ hStereoTD->prevSP_ratio_fx = ONE_IN_Q30; //.5
+ hStereoTD->SP_ratio_LT = 0.0f;
+ hStereoTD->SP_ratio_LT_fx = 0;
+ hStereoTD->c_LR_LT = 0.5f;
+ hStereoTD->c_LR_LT_fx = ONE_IN_Q30; //.5
+
+ hStereoTD->flag_skip_DMX = 0;
+
+ if ( last_element_mode == IVAS_CPE_MDCT )
+ {
+ hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_LEFT_IS_PRIM;
+ hStereoTD->tdm_LRTD_flag = 1;
+ }
+
+ set_f( hStereoTD->TCX_old_syn_Overl, 0.0f, L_FRAME16k / 2 );
+ set32_fx( hStereoTD->TCX_old_syn_Overl_fx, 0, L_FRAME16k / 2 );
+
+ return;
+}
+
+
/*-------------------------------------------------------------------*
* tdm_configure_dec()
*
* Configure TD stereo decoder
*-------------------------------------------------------------------*/
-
+Word32 power_table[32 + 1] = {
+ 53687092, 60237908, 67588048, 75835024, 85088304, 95470648, 107119832, 120190432,
+ 134855872, 151310800, 169773488, 190488992, 213732176, 239811440, 269072832, 301904704,
+ 338742656, 380075520, 426451744, 478486688, 536870912, 602379200, 675880448, 758350272,
+ 850883136, 954706496, 1071198464, 1201904384, 1348558720, 1513107968, 1697734912, 1904890240,
+ 2137321728
+}; // Q29
void tdm_configure_dec(
const int16_t ivas_format, /* i : IVAS format */
const int16_t ism_mode, /* i : ISM mode in combined format */
@@ -228,6 +268,10 @@ void tdm_configure_dec(
}
hCPE->hStereoDftDmx->targetGain = usdequant( tmpS, STEREO_TCA_GDMIN, STEREO_TCA_GDSTEP );
hCPE->hStereoDftDmx->targetGain = powf( 10, hCPE->hStereoDftDmx->targetGain );
+
+#ifdef IVAS_FLOAT_FIXED
+ hCPE->hStereoDftDmx->targetGain_fx = power_table[tmpS];
+#endif
}
else
{
@@ -245,9 +289,11 @@ void tdm_configure_dec(
}
hCPE->hStereoTCA->targetGain = usdequant( hCPE->hStereoTCA->indx_ica_gD, STEREO_TCA_GDMIN, STEREO_TCA_GDSTEP );
hCPE->hStereoTCA->targetGain = powf( 10, hCPE->hStereoTCA->targetGain );
- }
-
+#ifdef IVAS_FLOAT_FIXED
+ hCPE->hStereoTCA->targetGain_fx = power_table[hCPE->hStereoTCA->indx_ica_gD];
+#endif
+ }
/* set the BW of the secondary channel */
if ( hStereoTD->tdm_LRTD_flag && sts[1]->bits_frame_channel >= IVAS_16k4 / FRAMES_PER_SEC )
{
@@ -312,7 +358,43 @@ void tdm_upmix_plain(
return;
}
+void tdm_upmix_plain_fx(
+ Word32 Left_fx[], /* o : left channel */
+ Word32 Right_fx[], /* o : right channel */
+ const Word32 PCh_2_L_fx[], /* i : primary channel */
+ const Word32 SCh_2_R_fx[], /* i : secondary channel */
+ const Word32 LR_ratio_fx, /* i : mixing ratio */
+ const Word32 inv_den_LR_ratio_fx, /* i : inverse mixing ration */
+ const Word16 start_index, /* i : start index */
+ const Word16 end_index, /* i : end index */
+ const Word16 plus_minus_flag /* i : plus/minus flag */
+)
+{
+ Word16 i;
+ IF( plus_minus_flag == 1 )
+ {
+ FOR( i = start_index; i < end_index; i++ )
+ {
+ Word32 temp_left = L_add( Mpy_32_32( L_sub( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_fx ), SCh_2_R_fx[i] );
+ Left_fx[i] = L_shl_sat( Mpy_32_32( temp_left, inv_den_LR_ratio_fx ), 1 );
+ Word32 temp_right = L_add( Mpy_32_32( L_add( PCh_2_L_fx[i], SCh_2_R_fx[i] ), L_negate( LR_ratio_fx ) ), PCh_2_L_fx[i] );
+ Right_fx[i] = L_shl_sat( Mpy_32_32( temp_right, inv_den_LR_ratio_fx ), 1 );
+ }
+ }
+ ELSE
+ {
+ FOR( i = start_index; i < end_index; i++ )
+ {
+ Word32 temp_left = L_sub( Mpy_32_32( L_add( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_fx ), SCh_2_R_fx[i] );
+ Left_fx[i] = L_shl_sat( Mpy_32_32( temp_left, inv_den_LR_ratio_fx ), 1 );
+ Word32 temp_right = L_sub( Mpy_32_32( L_sub( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_fx ), PCh_2_L_fx[i] );
+ Right_fx[i] = L_shl_sat( Mpy_32_32( temp_right, inv_den_LR_ratio_fx ), 1 );
+ }
+ }
+
+ return;
+}
/*-------------------------------------------------------------------*
* Function tdm_downmix_fade()
@@ -391,6 +473,221 @@ static void tdm_upmix_fade(
}
+Word32 inv_time[960 + 1] = {
+ 0, 2147483647, 1073741824, 715827904, 536870912, 429496736, 357913952, 306783392,
+ 268435456, 238609296, 214748368, 195225792, 178956976, 165191056, 153391696, 143165584,
+ 134217728, 126322568, 119304648, 113025456, 107374184, 102261128, 97612896, 93368856,
+ 89478488, 85899344, 82595528, 79536432, 76695848, 74051160, 71582792, 69273664,
+ 67108864, 65075264, 63161284, 61356676, 59652324, 58040100, 56512728, 55063684,
+ 53687092, 52377648, 51130564, 49941480, 48806448, 47721860, 46684428, 45691140,
+ 44739244, 43826196, 42949672, 42107524, 41297764, 40518560, 39768216, 39045156,
+ 38347924, 37675152, 37025580, 36398028, 35791396, 35204648, 34636832, 34087044,
+ 33554432, 33038210, 32537632, 32051994, 31580642, 31122952, 30678338, 30246248,
+ 29826162, 29417584, 29020050, 28633116, 28256364, 27889398, 27531842, 27183338,
+ 26843546, 26512144, 26188824, 25873296, 25565282, 25264514, 24970740, 24683720,
+ 24403224, 24129030, 23860930, 23598722, 23342214, 23091222, 22845570, 22605092,
+ 22369622, 22139006, 21913098, 21691754, 21474836, 21262214, 21053762, 20849356,
+ 20648882, 20452226, 20259280, 20069940, 19884108, 19701684, 19522578, 19346700,
+ 19173962, 19004280, 18837576, 18673770, 18512790, 18354562, 18199014, 18046082,
+ 17895698, 17747798, 17602324, 17459216, 17318416, 17179870, 17043522, 16909320,
+ 16777216, 16647160, 16519105, 16393005, 16268816, 16146494, 16025997, 15907286,
+ 15790321, 15675063, 15561476, 15449523, 15339169, 15230380, 15123124, 15017368,
+ 14913081, 14810232, 14708792, 14608732, 14510025, 14412642, 14316558, 14221746,
+ 14128182, 14035841, 13944699, 13854733, 13765921, 13678240, 13591669, 13506186,
+ 13421773, 13338408, 13256072, 13174746, 13094412, 13015052, 12936648, 12859184,
+ 12782641, 12707004, 12632257, 12558384, 12485370, 12413200, 12341860, 12271335,
+ 12201612, 12132676, 12064515, 11997115, 11930465, 11864551, 11799361, 11734883,
+ 11671107, 11608020, 11545611, 11483870, 11422785, 11362347, 11302546, 11243370,
+ 11184811, 11126858, 11069503, 11012737, 10956549, 10900932, 10845877, 10791375,
+ 10737418, 10683998, 10631107, 10578737, 10526881, 10475530, 10424678, 10374317,
+ 10324441, 10275041, 10226113, 10177648, 10129640, 10082083, 10034970, 9988296,
+ 9942054, 9896238, 9850842, 9805861, 9761289, 9717121, 9673350, 9629972,
+ 9586981, 9544372, 9502140, 9460280, 9418788, 9377658, 9336885, 9296466,
+ 9256395, 9216668, 9177281, 9138228, 9099507, 9061112, 9023041, 8985287,
+ 8947849, 8910721, 8873899, 8837381, 8801162, 8765239, 8729608, 8694266,
+ 8659208, 8624432, 8589935, 8555712, 8521761, 8488078, 8454660, 8421505,
+ 8388608, 8355967, 8323580, 8291442, 8259552, 8227906, 8196502, 8165337,
+ 8134408, 8103712, 8073247, 8043010, 8012998, 7983210, 7953643, 7924294,
+ 7895160, 7866240, 7837531, 7809031, 7780738, 7752648, 7724761, 7697074,
+ 7669584, 7642290, 7615190, 7588281, 7561562, 7535030, 7508684, 7482521,
+ 7456540, 7430739, 7405116, 7379669, 7354396, 7329295, 7304366, 7279605,
+ 7255012, 7230584, 7206321, 7182219, 7158279, 7134497, 7110873, 7087405,
+ 7064091, 7040930, 7017920, 6995060, 6972349, 6949785, 6927366, 6905092,
+ 6882960, 6860970, 6839120, 6817408, 6795834, 6774396, 6753093, 6731923,
+ 6710886, 6689980, 6669204, 6648556, 6628036, 6607642, 6587373, 6567228,
+ 6547206, 6527306, 6507526, 6487866, 6468324, 6448900, 6429592, 6410399,
+ 6391320, 6372355, 6353502, 6334760, 6316128, 6297606, 6279192, 6260885,
+ 6242685, 6224590, 6206600, 6188713, 6170930, 6153248, 6135667, 6118187,
+ 6100806, 6083523, 6066338, 6049249, 6032257, 6015360, 5998557, 5981848,
+ 5965232, 5948708, 5932275, 5915933, 5899680, 5883517, 5867441, 5851454,
+ 5835553, 5819739, 5804010, 5788365, 5772805, 5757329, 5741935, 5726623,
+ 5711392, 5696243, 5681173, 5666184, 5651273, 5636440, 5621685, 5607007,
+ 5592405, 5577879, 5563429, 5549053, 5534751, 5520523, 5506368, 5492285,
+ 5478274, 5464335, 5450466, 5436667, 5422938, 5409278, 5395687, 5382164,
+ 5368709, 5355321, 5341999, 5328743, 5315553, 5302429, 5289368, 5276372,
+ 5263440, 5250571, 5237765, 5225021, 5212339, 5199718, 5187158, 5174659,
+ 5162220, 5149841, 5137520, 5125259, 5113056, 5100911, 5088824, 5076793,
+ 5064820, 5052902, 5041041, 5029235, 5017485, 5005789, 4994148, 4982560,
+ 4971027, 4959546, 4948119, 4936744, 4925421, 4914150, 4902930, 4891762,
+ 4880644, 4869577, 4858560, 4847593, 4836675, 4825806, 4814986, 4804214,
+ 4793490, 4782814, 4772186, 4761604, 4751070, 4740582, 4730140, 4719744,
+ 4709394, 4699089, 4688829, 4678613, 4668442, 4658316, 4648233, 4638193,
+ 4628197, 4618244, 4608334, 4598466, 4588640, 4578856, 4569114, 4559413,
+ 4549753, 4540134, 4530556, 4521018, 4511520, 4502062, 4492643, 4483264,
+ 4473924, 4464623, 4455360, 4446136, 4436949, 4427801, 4418690, 4409617,
+ 4400581, 4391582, 4382619, 4373694, 4364804, 4355950, 4347133, 4338351,
+ 4329604, 4320892, 4312216, 4303574, 4294967, 4286394, 4277856, 4269351,
+ 4260880, 4252443, 4244039, 4235668, 4227330, 4219025, 4210752, 4202512,
+ 4194304, 4186128, 4177983, 4169871, 4161790, 4153740, 4145721, 4137733,
+ 4129776, 4121849, 4113953, 4106087, 4098251, 4090445, 4082668, 4074921,
+ 4067204, 4059515, 4051856, 4044225, 4036623, 4029050, 4021505, 4013988,
+ 4006499, 3999038, 3991605, 3984199, 3976821, 3969470, 3962147, 3954850,
+ 3947580, 3940337, 3933120, 3925930, 3918765, 3911627, 3904515, 3897429,
+ 3890369, 3883334, 3876324, 3869340, 3862380, 3855446, 3848537, 3841652,
+ 3834792, 3827956, 3821145, 3814358, 3807595, 3800856, 3794140, 3787449,
+ 3780781, 3774136, 3767515, 3760917, 3754342, 3747790, 3741260, 3734754,
+ 3728270, 3721808, 3715369, 3708952, 3702558, 3696185, 3689834, 3683505,
+ 3677198, 3670912, 3664647, 3658404, 3652183, 3645982, 3639802, 3633644,
+ 3627506, 3621389, 3615292, 3609216, 3603160, 3597125, 3591109, 3585114,
+ 3579139, 3573184, 3567248, 3561332, 3555436, 3549559, 3543702, 3537864,
+ 3532045, 3526245, 3520465, 3514703, 3508960, 3503236, 3497530, 3491843,
+ 3486174, 3480524, 3474892, 3469279, 3463683, 3458105, 3452546, 3447004,
+ 3441480, 3435973, 3430485, 3425013, 3419560, 3414123, 3408704, 3403302,
+ 3397917, 3392549, 3387198, 3381864, 3376546, 3371246, 3365961, 3360694,
+ 3355443, 3350208, 3344990, 3339788, 3334602, 3329432, 3324278, 3319140,
+ 3314018, 3308911, 3303821, 3298746, 3293686, 3288642, 3283614, 3278601,
+ 3273603, 3268620, 3263653, 3258700, 3253763, 3248840, 3243933, 3239040,
+ 3234162, 3229298, 3224450, 3219615, 3214796, 3209990, 3205199, 3200422,
+ 3195660, 3190911, 3186177, 3181457, 3176751, 3172058, 3167380, 3162715,
+ 3158064, 3153426, 3148803, 3144192, 3139596, 3135012, 3130442, 3125886,
+ 3121342, 3116812, 3112295, 3107791, 3103300, 3098822, 3094356, 3089904,
+ 3085465, 3081038, 3076624, 3072222, 3067833, 3063457, 3059093, 3054742,
+ 3050403, 3046076, 3041761, 3037459, 3033169, 3028891, 3024624, 3020370,
+ 3016128, 3011898, 3007680, 3003473, 2999278, 2995095, 2990924, 2986764,
+ 2982616, 2978479, 2974354, 2970240, 2966137, 2962046, 2957966, 2953897,
+ 2949840, 2945793, 2941758, 2937734, 2933720, 2929718, 2925727, 2921746,
+ 2917776, 2913817, 2909869, 2905931, 2902005, 2898088, 2894182, 2890287,
+ 2886402, 2882528, 2878664, 2874810, 2870967, 2867134, 2863311, 2859498,
+ 2855696, 2851904, 2848121, 2844349, 2840586, 2836834, 2833092, 2829359,
+ 2825636, 2821923, 2818220, 2814526, 2810842, 2807168, 2803503, 2799848,
+ 2796202, 2792566, 2788939, 2785322, 2781714, 2778116, 2774526, 2770946,
+ 2767375, 2763814, 2760261, 2756718, 2753184, 2749659, 2746142, 2742635,
+ 2739137, 2735648, 2732167, 2728695, 2725233, 2721779, 2718333, 2714897,
+ 2711469, 2708050, 2704639, 2701237, 2697843, 2694458, 2691082, 2687714,
+ 2684354, 2681003, 2677660, 2674325, 2670999, 2667681, 2664371, 2661070,
+ 2657776, 2654491, 2651214, 2647945, 2644684, 2641431, 2638186, 2634949,
+ 2631720, 2628499, 2625285, 2622080, 2618882, 2615692, 2612510, 2609336,
+ 2606169, 2603010, 2599859, 2596715, 2593579, 2590450, 2587329, 2584216,
+ 2581110, 2578011, 2574920, 2571836, 2568760, 2565691, 2562629, 2559575,
+ 2556528, 2553488, 2550455, 2547430, 2544412, 2541400, 2538396, 2535399,
+ 2532410, 2529427, 2526451, 2523482, 2520520, 2517565, 2514617, 2511676,
+ 2508742, 2505815, 2502894, 2499981, 2497074, 2494173, 2491280, 2488393,
+ 2485513, 2482640, 2479773, 2476913, 2474059, 2471212, 2468372, 2465538,
+ 2462710, 2459889, 2457075, 2454267, 2451465, 2448670, 2445881, 2443098,
+ 2440322, 2437552, 2434788, 2432031, 2429280, 2426535, 2423796, 2421063,
+ 2418337, 2415617, 2412903, 2410195, 2407493, 2404797, 2402107, 2399423,
+ 2396745, 2394073, 2391407, 2388747, 2386093, 2383444, 2380802, 2378165,
+ 2375535, 2372910, 2370291, 2367677, 2365070, 2362468, 2359872, 2357281,
+ 2354697, 2352118, 2349544, 2346976, 2344414, 2341857, 2339306, 2336761,
+ 2334221, 2331687, 2329158, 2326634, 2324116, 2321604, 2319096, 2316595,
+ 2314098, 2311607, 2309122, 2306642, 2304167, 2301697, 2299233, 2296774,
+ 2294320, 2291871, 2289428, 2286990, 2284557, 2282129, 2279706, 2277289,
+ 2274876, 2272469, 2270067, 2267670, 2265278, 2262891, 2260509, 2258132,
+ 2255760, 2253393, 2251031, 2248674, 2246321, 2243974, 2241632, 2239294,
+ 2236962
+};
+static void tdm_upmix_fade_fx(
+ Word32 Left_fx[], /* o : left channel */
+ Word32 Right_fx[], /* o : right channel */
+ const Word32 PCh_2_L_fx[], /* i : primary channel */
+ const Word32 SCh_2_R_fx[], /* i : secondary channel */
+ const Word32 LR_ratio_mem_fx, /* i : last mixing ratio */
+ const Word32 inv_den_LR_ratio_mem_fx, /* i : last inverse mixing ration */
+ const Word32 LR_ratio_fx, /* i : mixing ratio */
+ const Word32 inv_den_LR_ratio_fx, /* i : inverse mixing ration */
+ const Word16 start_index, /* i : start index */
+ const Word16 end_index, /* i : end index */
+ const Word16 fading_type /* i : fading type */
+)
+{
+ Word16 i;
+ Word32 step_fx, step2_fx, fade_in_fx, fade_out_fx;
+
+ step_fx = inv_time[end_index - start_index];
+ fade_out_fx = ONE_IN_Q31;
+ fade_in_fx = 0;
+
+ fade_out_fx = Mpy_32_32( fade_out_fx, inv_den_LR_ratio_mem_fx );
+ fade_in_fx = Mpy_32_32( fade_in_fx, inv_den_LR_ratio_fx );
+ step2_fx = Mpy_32_32( step_fx, inv_den_LR_ratio_fx );
+ step_fx = Mpy_32_32( step_fx, inv_den_LR_ratio_mem_fx );
+
+ IF( fading_type == 0 ) /* Switching from YX scheme to SM scheme */
+ {
+ FOR( i = start_index; i < end_index; i++ )
+ {
+ Word32 temp_left1 = Mpy_32_32( L_add( Mpy_32_32( L_sub( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_mem_fx ), SCh_2_R_fx[i] ), fade_out_fx );
+ Word32 temp_left2 = Mpy_32_32( L_sub( Mpy_32_32( L_add( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_fx ), SCh_2_R_fx[i] ), fade_in_fx );
+ Left_fx[i] = L_shl_sat( L_add( temp_left1, temp_left2 ), 1 );
+ Word32 temp_right1 = Mpy_32_32( L_add( Mpy_32_32( L_add( PCh_2_L_fx[i], SCh_2_R_fx[i] ), L_negate( LR_ratio_mem_fx ) ), PCh_2_L_fx[i] ), fade_out_fx );
+ Word32 temp_right2 = Mpy_32_32( L_sub( Mpy_32_32( L_sub( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_fx ), PCh_2_L_fx[i] ), fade_in_fx );
+ Right_fx[i] = L_shl_sat( L_add( temp_right1, temp_right2 ), 1 );
+
+ fade_in_fx = L_add( fade_in_fx, step2_fx );
+ fade_out_fx = L_sub( fade_out_fx, step_fx );
+ }
+ }
+ ELSE IF( fading_type == 1 ) /* SM scheme */
+ {
+ FOR( i = start_index; i < end_index; i++ )
+ {
+ Word32 temp_left1 = Mpy_32_32( L_sub( Mpy_32_32( L_add( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_mem_fx ), SCh_2_R_fx[i] ), fade_out_fx );
+ Word32 temp_left2 = Mpy_32_32( L_sub( Mpy_32_32( L_add( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_fx ), SCh_2_R_fx[i] ), fade_in_fx );
+ Left_fx[i] = L_shl_sat( L_add( temp_left1, temp_left2 ), 1 );
+
+ Word32 temp_right1 = Mpy_32_32( L_sub( Mpy_32_32( L_sub( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_mem_fx ), PCh_2_L_fx[i] ), fade_out_fx );
+ Word32 temp_right2 = Mpy_32_32( L_sub( Mpy_32_32( L_sub( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_fx ), PCh_2_L_fx[i] ), fade_in_fx );
+ Right_fx[i] = L_shl_sat( L_add( temp_right1, temp_right2 ), 1 );
+
+ fade_in_fx = L_add( fade_in_fx, step2_fx );
+ fade_out_fx = L_sub( fade_out_fx, step_fx );
+ }
+ }
+ ELSE IF( fading_type == 2 ) /* Switching from SM scheme to YX scheme */
+ {
+ FOR( i = start_index; i < end_index; i++ )
+ {
+ Word32 temp_left1 = Mpy_32_32( L_sub( Mpy_32_32( L_add( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_mem_fx ), SCh_2_R_fx[i] ), fade_out_fx );
+ Word32 temp_left2 = Mpy_32_32( L_add( Mpy_32_32( L_sub( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_fx ), SCh_2_R_fx[i] ), fade_in_fx );
+ Left_fx[i] = L_shl_sat( L_add( temp_left1, temp_left2 ), 1 );
+
+ Word32 temp_right1 = Mpy_32_32( L_sub( Mpy_32_32( L_sub( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_mem_fx ), PCh_2_L_fx[i] ), fade_out_fx );
+ Word32 temp_right2 = Mpy_32_32( L_add( Mpy_32_32( L_add( PCh_2_L_fx[i], SCh_2_R_fx[i] ), L_negate( LR_ratio_fx ) ), PCh_2_L_fx[i] ), fade_in_fx );
+ Right_fx[i] = L_shl_sat( L_add( temp_right1, temp_right2 ), 1 );
+
+ fade_in_fx = L_add( fade_in_fx, step2_fx );
+ fade_out_fx = L_sub( fade_out_fx, step_fx );
+ }
+ }
+ ELSE IF( fading_type == 3 ) /* YX scheme */
+ {
+ FOR( i = start_index; i < end_index; i++ )
+ {
+ Word32 temp_left1 = Mpy_32_32( L_add( Mpy_32_32( L_sub( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_mem_fx ), SCh_2_R_fx[i] ), fade_out_fx );
+ Word32 temp_left2 = Mpy_32_32( L_add( Mpy_32_32( L_sub( PCh_2_L_fx[i], SCh_2_R_fx[i] ), LR_ratio_fx ), SCh_2_R_fx[i] ), fade_in_fx );
+ Left_fx[i] = L_shl_sat( L_add( temp_left1, temp_left2 ), 1 );
+
+ Word32 temp_right1 = Mpy_32_32( L_add( Mpy_32_32( L_add( PCh_2_L_fx[i], SCh_2_R_fx[i] ), L_negate( LR_ratio_mem_fx ) ), PCh_2_L_fx[i] ), fade_out_fx );
+ Word32 temp_right2 = Mpy_32_32( L_add( Mpy_32_32( L_add( PCh_2_L_fx[i], SCh_2_R_fx[i] ), L_negate( LR_ratio_fx ) ), PCh_2_L_fx[i] ), fade_in_fx );
+ Right_fx[i] = L_shl_sat( L_add( temp_right1, temp_right2 ), 1 );
+
+ fade_in_fx = L_add( fade_in_fx, step2_fx );
+ fade_out_fx = L_sub( fade_out_fx, step_fx );
+ }
+ }
+
+ return;
+}
/*-------------------------------------------------------------------*
* stereo_tdm_combine()
*
@@ -557,3 +854,184 @@ void stereo_tdm_combine(
return;
}
+
+#ifdef IVAS_FLOAT_FIXED
+void stereo_tdm_combine_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *PCh_2_L_fx, /* i/o: Primary channel -> output as left channel */
+ Word32 *SCh_2_R_fx, /* i/o: Secondary channel -> output as right channel*/
+ const Word16 output_frame, /* i : Number of samples */
+ const Word16 flag_HB, /* i : flag to distinguish between core (0) and HB (1) synthesis */
+ const Word16 tdm_ratio_idx /* i : TDM ratio index */
+)
+{
+ Word16 i;
+ Word32 output_Fs;
+ Word32 LR_ratio_fx, LR_ratio_mem_fx;
+ Word32 Left_fx[L_FRAME48k], Right_fx[L_FRAME48k];
+ Word16 upmixing_delay;
+ Word16 stereo_tdm_coder_type;
+ Word16 tdm_n_OVA;
+ Word16 tdm_last_ratio_idx = hCPE->hStereoTD->tdm_last_ratio_idx;
+
+ output_Fs = hCPE->hCoreCoder[0]->output_Fs;
+ tdm_n_OVA = NS2SA( output_Fs, TDM_L_NOVA_NS );
+
+ IF( flag_HB )
+ {
+ upmixing_delay = NS2SA( output_Fs, ACELP_LOOK_NS + DELAY_BWE_TOTAL_NS );
+ }
+ ELSE
+ {
+ upmixing_delay = NS2SA( output_Fs, ACELP_LOOK_NS + DELAY_CLDFB_NS );
+ }
+
+ LR_ratio_fx = tdm_ratio_tabl_fx[tdm_ratio_idx];
+ LR_ratio_mem_fx = tdm_ratio_tabl_fx[tdm_last_ratio_idx];
+
+ IF( hCPE->hStereoTD->flag_skip_DMX )
+ {
+ stereo_tdm_coder_type = 10; /* no DMX */
+ Copy32( PCh_2_L_fx, Left_fx, output_frame );
+ Copy32( SCh_2_R_fx, Right_fx, output_frame );
+ }
+ ELSE IF( hCPE->hStereoTD->tdm_last_SM_flag == 1 )
+ {
+ IF( hCPE->hStereoTD->tdm_prev_last_SM_flag == 0 )
+ {
+ stereo_tdm_coder_type = 0; /* mode 1 : Switching from YX scheme to SM scheme*/
+ }
+ ELSE
+ {
+ stereo_tdm_coder_type = 1; /* mode 2 : SM scheme*/
+ }
+ }
+ ELSE
+ {
+ IF( hCPE->hStereoTD->tdm_prev_last_SM_flag == 1 )
+ {
+ stereo_tdm_coder_type = 2; /* mode 3 : Switching from SM scheme to YX scheme*/
+ }
+ ELSE
+ {
+ stereo_tdm_coder_type = 3; /* mode 4 : YX scheme*/
+ }
+ }
+
+ SWITCH( stereo_tdm_coder_type )
+ {
+ case ( 0 ):
+ {
+ /* Do the upmixing of the first upmixing_delay samples with the old coefficient and formular for YX scheme */
+ tdm_upmix_plain_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_mem_fx, tdm_den_ratio_tabl_fx[tdm_last_ratio_idx], 0, upmixing_delay, 1 );
+
+ /* Switching from YX scheme to SM scheme */
+ tdm_upmix_fade_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_mem_fx, tdm_den_ratio_tabl_fx[tdm_last_ratio_idx], LR_ratio_fx, tdm_den_ratio_tabl_fx[tdm_ratio_idx], upmixing_delay, upmixing_delay + tdm_n_OVA, 0 );
+
+ /* Do the upmixing of the other samples with the new coefficient and formular for SM scheme */
+ tdm_upmix_plain_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_fx, tdm_den_ratio_tabl_fx[tdm_ratio_idx], upmixing_delay + tdm_n_OVA, output_frame, 0 );
+ }
+ break;
+ case ( 1 ):
+ {
+ /* Do the upmixing of the first upmixing_delay samples with the old coefficient and formular for SM scheme */
+ tdm_upmix_plain_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_mem_fx, tdm_den_ratio_tabl_fx[tdm_last_ratio_idx], 0, upmixing_delay, 0 );
+
+ /* Do the upmixing of the other samples with the new coefficient and formular for SM scheme */
+ if ( LR_ratio_fx == LR_ratio_mem_fx )
+ {
+ tdm_upmix_plain_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_mem_fx, tdm_den_ratio_tabl_fx[tdm_last_ratio_idx], upmixing_delay, output_frame, 0 );
+ }
+ else
+ {
+ tdm_upmix_fade_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_mem_fx, tdm_den_ratio_tabl_fx[tdm_last_ratio_idx], LR_ratio_fx, tdm_den_ratio_tabl_fx[tdm_ratio_idx], upmixing_delay, upmixing_delay + tdm_n_OVA, 1 );
+ tdm_upmix_plain_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_fx, tdm_den_ratio_tabl_fx[tdm_ratio_idx], upmixing_delay + tdm_n_OVA, output_frame, 0 );
+ }
+ }
+ break;
+ case ( 2 ):
+ {
+ /* Do the upmixing of the first upmixing_delay samples with the old coefficient and formular for SM scheme */
+ tdm_upmix_plain_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_mem_fx, tdm_den_ratio_tabl_fx[tdm_last_ratio_idx], 0, upmixing_delay, 0 );
+
+ /* Switching from SM scheme to YX scheme */
+ tdm_upmix_fade_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_mem_fx, tdm_den_ratio_tabl_fx[tdm_last_ratio_idx], LR_ratio_fx, tdm_den_ratio_tabl_fx[tdm_ratio_idx], upmixing_delay, upmixing_delay + tdm_n_OVA, 2 );
+
+ /* Do the upmixing of the other samples with the new coefficient and formular for YX scheme */
+ tdm_upmix_plain_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_fx, tdm_den_ratio_tabl_fx[tdm_ratio_idx], upmixing_delay + tdm_n_OVA, output_frame, 1 );
+ }
+ break;
+ case ( 3 ):
+ {
+ /* Do the upmixing of the first upmixing_delay samples with the old coefficient and formular for YX scheme */
+ tdm_upmix_plain_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_mem_fx, tdm_den_ratio_tabl_fx[tdm_last_ratio_idx], 0, upmixing_delay, 1 );
+
+ /* Do the upmixing of the other samples with the new coefficient and formular for YX scheme */
+ if ( LR_ratio_fx == LR_ratio_mem_fx )
+ {
+ tdm_upmix_plain_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_mem_fx, tdm_den_ratio_tabl_fx[tdm_last_ratio_idx], upmixing_delay, output_frame, 1 );
+ }
+ else
+ {
+ tdm_upmix_fade_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_mem_fx, tdm_den_ratio_tabl_fx[tdm_last_ratio_idx], LR_ratio_fx, tdm_den_ratio_tabl_fx[tdm_ratio_idx], upmixing_delay, upmixing_delay + tdm_n_OVA, 3 );
+ tdm_upmix_plain_fx( Left_fx, Right_fx, PCh_2_L_fx, SCh_2_R_fx, LR_ratio_fx, tdm_den_ratio_tabl_fx[tdm_ratio_idx], upmixing_delay + tdm_n_OVA, output_frame, 1 );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ FOR( i = 0; i < output_frame; i++ )
+ {
+ PCh_2_L_fx[i] = Left_fx[i];
+ SCh_2_R_fx[i] = Right_fx[i];
+ }
+
+ /* DFT -> TD stereo switching: equalize signal energies */
+ IF( hCPE->last_element_mode != IVAS_CPE_TD )
+ {
+ Word32 incr_fx, fac_fx;
+
+ IF( hCPE->hStereoDftDmx != NULL )
+ {
+ fac_fx = ONE_IN_Q29;
+ }
+ ELSE
+ {
+ fac_fx = hCPE->hStereoTCA->targetGain_fx;
+ }
+
+
+ IF( fac_fx < ONE_IN_Q29 )
+ {
+ Word32 step = 0;
+ SWITCH( output_Fs )
+ {
+ case ( 16000 ):
+ step = 15339168;
+ break;
+ case ( 32000 ):
+ step = 7669584;
+ break;
+ case ( 48000 ):
+ step = 5113056;
+ break;
+ default:
+ assert( 0 );
+ break;
+ }
+ incr_fx = Mpy_32_32( L_sub( ONE_IN_Q29, fac_fx ), step );
+
+ FOR( i = 0; i < NS2SA( output_Fs, ACELP_LOOK_NS ); i++ )
+ {
+ PCh_2_L_fx[i] = L_shl_sat( Mpy_32_32( PCh_2_L_fx[i], fac_fx ), 2 );
+
+ fac_fx = L_add( incr_fx, fac_fx );
+ }
+ }
+ }
+ return;
+}
+
+
+#endif
\ No newline at end of file
diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h
index 5468047c15b1070cfe95477012ff710d6abb71e9..b9dd78613f1e926ff85ee9a6fbe379806f9b8aee 100644
--- a/lib_dec/stat_dec.h
+++ b/lib_dec/stat_dec.h
@@ -174,7 +174,9 @@ typedef struct
int16_t ms_last_inactive_bwidth; /* stereo CNA - bandwidth from the last inactive frame */
int16_t ms_cnt_bw_up; /* stereo CNA - downward counter of frames since the last NB->WB switch */
float cna_LR_LT; /* stereo CNA - long-term L/R correlation factor calculated on stereo upmix */
+ Word16 cna_LR_LT_fx; /* stereo CNA - long-term L/R correlation factor calculated on stereo upmix */
float cna_ILD_LT; /* stereo CNA - long-term ILD factor calculated on stereo upmix */
+ Word16 cna_ILD_LT_fx; /* stereo CNA - long-term ILD factor calculated on stereo upmix */
float cna_g_state[STEREO_DFT_BAND_MAX]; /* stereo CNA - side gains from the last inactive frame */
float cna_cm[STEREO_DFT_BAND_MAX]; /* stereo CNA - coherence from the last inactive frame */
int16_t first_cna_noise_updated; /* stereo CNA - flag indicating that comfort noise has been properly initialized during warmup */