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 */