Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : #include <stdint.h>
34 : #include "options.h"
35 : #include <math.h>
36 : #include "cnst.h"
37 : #include "rom_com.h"
38 : #include "prot_fx.h"
39 : #include "ivas_rom_com.h"
40 : #include "ivas_cnst.h"
41 : #include "rom_enc.h"
42 : #include "wmc_auto.h"
43 : #include "ivas_prot_fx.h"
44 : #include "ivas_rom_com_fx.h"
45 :
46 :
47 : /*-------------------------------------------------------------------*
48 : * Local constants
49 : *-------------------------------------------------------------------*/
50 :
51 : #define RMS_MIN_FX_Q20 ( 1572864000 ) /* 1500 in Q20 */ /* Minimum energy for ratio index*/
52 : #define RMS_MIN2_FX_Q21 ( 2097152000 ) /* 1000 in Q21 */ /* Minimum energy for LR encoding*/
53 : #define CORR_THRES_FX_Q15 ( 31130 ) /* 0.95f in Q15 */ /* Maximal open loop correlation */
54 : #define DT_ENER_THR_FX_Q16 ( 13107200 ) /* 200 in Q16 */ /* Energy variation threshold */
55 :
56 : #define RMS_MIN 1500 /* Minimum energy for ratio index*/
57 : #define RMS_MIN2 1000 /* Minimum energy for LR encoding*/
58 : #define CORR_THRES 0.95f /* Maximal open loop correlation */
59 : #define RMS_MIN_Q16 98304000 /* 1500 in Q16 */ /* Minimum energy for ratio index*/
60 : #define RMS_MIN2_Q16 65536000 /* 1000 in Q16 */ /* Minimum energy for LR encoding*/
61 : #define CORR_THRES_Q15 31130 /* Maximal open loop correlation */
62 :
63 : #define ALP_REF_FX_Q31 ( 1717986918 ) /* 0.8f in Q31 */ /* smoothing factor */
64 : #define BET_REF_FX_Q31 ( ONE_IN_Q31 - ALP_REF_FX_Q31 )
65 :
66 : #define ALP1_FX_Q31 ( 1073741824 ) /* 0.5f in Q31 */ /* smoothing factor in case of correlation are going in different directions */
67 : #define BET1_FX_Q31 ( ONE_IN_Q31 - ALP1_FX_Q31 ) /* increase the update rate */
68 :
69 : #define ALP2_FX_Q31 ( 429496729 ) /* 0.2f in Q31 */ /* smoothing factor in case of correlation are going in different directions in SM mode*/
70 : #define BET2_FX_Q31 ( ONE_IN_Q31 - ALP2_FX_Q31 ) /* increase the update rate in SM mode*/
71 :
72 : #define RATIO_MAX 1.5f /* Maximum correlation ratio */
73 :
74 : #define RATIO_MAX_FX_Q30 ( 1610612736 ) /* 1.5f in Q30 */ /* Maximum correlation ratio */
75 : #define RATIO_MAX_FX_Q24 ( 25165824 ) /* 1.5f in Q24 */ /* Maximum correlation ratio */
76 : #define RATIO_MAX_FX_Q23 ( 12582912 ) /* 1.5f in Q23 */ /* Maximum correlation ratio */
77 : #define LIMIT_ADAP_FAC_FX_Q16 ( 9830 ) /* 0.15f in Q16 */
78 : #define MIN_ADAP_FAC_FX_Q16 ( 6554 ) /*0.1f in Q16*/
79 : #define M_ADAP_FX_Q31 ( 1932735 ) /* 0.0009f in Q31 */
80 : #define B_ADAP_FX_Q16 ( 10486 ) /* 0.16f in Q16 */
81 :
82 : #define PC_LIMIT 64
83 : #define RATIO_PG_HR 0.94f
84 : #define RATIO_PG_HR_FX 2018634629 // 0.94f in Q31
85 : #define RATIO_PG 0.92f
86 : #define RATIO_PG_FX 1975684956 // 0.92f in Q31
87 : #define PG2ND 3.0f
88 : #define PG2ND_FX 6291456 // 3.0f in Q21
89 : #define EUCLDST 0.04f
90 : #define EUCLDST_FX 85899346 // 0.04f in Q31
91 : #define RATIO_PG2 0.86f
92 : #define RATIO_PG2_FX 1846835937 // 0.86f in Q31
93 : #define PG2ND2 3.0f
94 : #define PG2ND2_FX 6291456 // 3.0f in Q21
95 : #define EUCLDST2 0.08f
96 : #define EUCLDST2_FX 171798692 // 0.08f in Q31
97 :
98 : #define RMS_THR 100
99 : #define RMS_THR_Q16 ( 6553600 )
100 : #define RATIO_PG_LRTD 0.96f
101 : #define RATIO_PG_LRTD_FX 2061584302 // 0.96f in Q31
102 :
103 : #define IVAS_BRATE_OMASA_STEREO_SW_THR 15000
104 :
105 : // #define ONE_BY_100_Q15 ( 328 )
106 : #define ONE_BY_100_Q31 ( 21474896 )
107 : #define TEN_IN_Q27 ( 1342177280 ) /* 10.0f in Q27 */
108 : #define TEN_IN_Q16 ( 655360 ) /* 10.0f in Q16 */
109 :
110 : /*-------------------------------------------------------------------*
111 : * Local function prototypes
112 : *-------------------------------------------------------------------*/
113 :
114 : static Word16 stereo_tdm_ener_analysis_SM_fx( CPE_ENC_HANDLE hCPE, Encoder_State **sts, const Word16 input_frame /*Q0*/, Word16 *tdm_SM_flag /*Q0*/ );
115 :
116 : static void Get_corr_n_fx( const Word16 L[] /*q_in*/, const Word16 R[] /*q_in*/, Word32 *ic_Lm, Word16 *q_ic_Lm, Word32 *ic_Rm, Word16 *q_ic_Rm, const Word16 len, Word32 *es_em, const Word16 tdm_SM_calc_flag );
117 :
118 : static Word16 stereo_smooth_LR_transition_fx( Word16 *tdm_prev_stable_idx, Word16 *tdm_ratio_transition_mov_flag, Word16 tdm_last_ratio_idx, Word16 *tdm_prev_desired_idx, Word16 *tdm_ratio_transition_cnt, const Word16 tdm_SM_flag, Word16 desired_idx );
119 :
120 : static Word16 limit_idx_Dwnmix_fx( const Word16 idx_in /*Q0*/, const Word16 unclr_decision /*Q0*/, const Word16 inst_idx /*Q0*/, const Word16 previous_idx /*Q0*/, const Word16 tdm_last_LRTD_PriCh_cnt /*Q0*/, const Word16 tdm_last_LRTD_frame_cnt /*Q0*/ );
121 :
122 : static Word16 limit_idx_NoDwnmix_fx( const Word16 idx_in /*Q0*/, const Word16 side_can_change /*Q0*/, const Word32 d_lt_corr_raw, const Word16 q_d_lt_corr_raw );
123 :
124 : static void Get_LR_rms_fx( const Word16 *Left_in /*q_inp*/, const Word16 *Right_in /*q_inp*/, const Word16 input_frame, Word32 *rms_L, Word16 *q_rms_L, Word32 *rms_R, Word16 *q_rms_R );
125 :
126 : static Word16 Get_dt_lt_ener_fx( CPE_ENC_HANDLE hCPE, const Word16 IsSideMono, const Word16 input_frame, const Word16 tdm_last_SM_flag, const Word32 rms_L, const Word16 q_rms_L, const Word32 rms_R, const Word16 q_rms_R, Word32 *tdm_lt_rms_L /*Q16*/, Word32 *tdm_lt_rms_R /*Q16*/, Word32 *tdm_last_ener_lt_L /*Q16*/, Word32 *tdm_last_ener_lt_R /*Q16*/, Word32 *tdm_LT_es_em /*Q21*/, Word16 *tdm_hyst_cnt, Word16 *tdm_NOOP_SM_flag_loc, Word32 *ener_R_dt /*Q16*/, Word32 *ener_L_dt /*Q16*/, Word32 *corr_LM, Word16 *q_corr_LM, Word32 *corr_RM, Word16 *q_corr_RM );
127 :
128 : static void NOOP_decision_fx( CPE_ENC_HANDLE hCPE, const Word16 tdm_NOOP_flag_loc /*Q0*/, const Word16 tmp_SM_flag /*Q0*/, const Word32 rms_L, const Word16 q_rms_L, const Word32 rms_R, const Word16 q_rms_R, Word16 *tdm_SM_flag_loc /*Q0*/ );
129 :
130 : static Word32 Comp_diff_lt_corr_fx( CPE_ENC_HANDLE hCPE, const Word16 IsSideMono /*Q0*/, const Word32 rms_L, const Word16 q_rms_L, const Word32 rms_R, const Word16 q_rms_R, const Word32 ener_L_dt /*Q16*/, const Word32 ener_R_dt /*Q16*/, Word32 corr_LM, Word16 q_corr_LM, Word32 corr_RM, Word16 q_corr_RM, const Word32 tdm_lt_rms_L /*Q16*/, const Word32 tdm_lt_rms_R /*Q16*/, Word32 *tdm_lt_corr_LM /*Q24*/, Word32 *tdm_lt_corr_RM /*Q24*/, Word32 *tdm_last_diff_lt_corr, Word16 *q_tdm_last_diff_lt_corr, Word32 *inst_ratio_L_out /*Q24*/, Word32 *diff_lt_corr, Word16 *q_d_lt_corr_raw );
131 :
132 :
133 : /*-------------------------------------------------------------------*
134 : * Function stereo_tdm_ener_analysis()
135 : *
136 : *-------------------------------------------------------------------*/
137 3827 : Word16 stereo_tdm_ener_analysis_fx(
138 : const Word16 ivas_format, /* i : IVAS format */
139 : CPE_ENC_HANDLE hCPE, /* i : CPE structure */
140 : const Word16 input_frame, /* i : Number of samples Q0*/
141 : Word16 *tdm_SM_or_LRTD_Pri, /* o : channel combination scheme flag in TD stereo OR LRTD primary channel Q0*/
142 : Word16 *tdm_ratio_idx_SM /* o : TDM ratio index for SM mode Q0*/
143 : )
144 : {
145 : Word32 diff_lt_corr_fx /*Q24*/;
146 : Word32 ratio_L_fx, dist_fx;
147 : Word16 i, side_can_change;
148 : Word16 idx, tdm_SM_flag_loc;
149 : Word16 tmp_SM_flag;
150 : Word16 desired_idx;
151 : Word32 rms_thd_fx; // Q16
152 : Word16 tdm_NOOP_flag_loc, tdm_NOOP_flag;
153 : STEREO_TD_ENC_DATA_HANDLE hStereoTD;
154 : Encoder_State **sts;
155 : Word32 d_lt_corr_raw_fx;
156 : Word16 q_d_lt_corr_raw;
157 : Word32 inst_ratio_L_fx; // Q24
158 : Word16 tdm_LRTD_pri_side;
159 : Word32 rms_L_fx, rms_R_fx;
160 : Word16 q_rms_L, q_rms_R;
161 : Word32 corr_RM_fx, corr_LM_fx;
162 : Word16 q_corr_LM, q_corr_RM;
163 : Word32 ener_R_dt_fx, ener_L_dt_fx;
164 :
165 3827 : hStereoTD = hCPE->hStereoTD;
166 3827 : sts = hCPE->hCoreCoder;
167 :
168 3827 : desired_idx = 0;
169 3827 : move16();
170 3827 : inst_ratio_L_fx = 0;
171 3827 : move32();
172 3827 : diff_lt_corr_fx = 0;
173 3827 : move32();
174 : /*----------------------------------------------------------------*
175 : * Compute L and R energy and Long term RMS of each channel
176 : *----------------------------------------------------------------*/
177 :
178 3827 : Get_LR_rms_fx( sts[0]->input_fx, sts[1]->input_fx, input_frame, &rms_L_fx, &q_rms_L, &rms_R_fx, &q_rms_R );
179 :
180 : /*----------------------------------------------------------------*
181 : * Compute the 1st order energy difference difference
182 : * Compute the gain of L&R channel compared to mono
183 : * - estimate the long term evolution of the L to Mono gain
184 : * - estimate the long term evolution of the R to Mono gain
185 : * - estimate the long term difference between the long term
186 : * - evolution of the L and R to Mono gain
187 : *----------------------------------------------------------------*/
188 :
189 3827 : tdm_SM_flag_loc = hStereoTD->tdm_last_SM_flag; /* Q0 */
190 3827 : move16();
191 :
192 3827 : tmp_SM_flag = Get_dt_lt_ener_fx( hCPE, 0, input_frame, hStereoTD->tdm_last_SM_flag, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R,
193 : &hStereoTD->tdm_lt_rms_L_fx, &hStereoTD->tdm_lt_rms_R_fx, &hStereoTD->tdm_last_ener_lt_L_fx, &hStereoTD->tdm_last_ener_lt_R_fx,
194 : &hStereoTD->tdm_LT_es_em_fx, &hStereoTD->tdm_hyst_cnt, &tdm_NOOP_flag_loc,
195 : &ener_R_dt_fx, &ener_L_dt_fx, &corr_LM_fx, &q_corr_LM, &corr_RM_fx, &q_corr_RM );
196 :
197 3827 : hStereoTD->tdm_SM_reset_flag = 0;
198 3827 : move16();
199 :
200 : /*----------------------------------------------------------------*
201 : * Check if the signal has Near Out Of Phase characteristics
202 : * and trigger side/mono configuration if needed
203 : *----------------------------------------------------------------*/
204 :
205 3827 : NOOP_decision_fx( hCPE, tdm_NOOP_flag_loc, tmp_SM_flag, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R, &tdm_SM_flag_loc );
206 :
207 : /*----------------------------------------------------------------*
208 : * Adjust stereo downmixing adaptation rate factor
209 : * in function of the signal energy. If signal energy is low,
210 : * adaptation rate factor is lower. This prevent stereo image
211 : * move on speech offset
212 : *----------------------------------------------------------------*/
213 3827 : d_lt_corr_raw_fx = Comp_diff_lt_corr_fx( hCPE, 0, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R, ener_L_dt_fx, ener_R_dt_fx, corr_LM_fx, q_corr_LM, corr_RM_fx, q_corr_RM, hStereoTD->tdm_lt_rms_L_fx, hStereoTD->tdm_lt_rms_R_fx, &hStereoTD->tdm_lt_corr_LM_fx,
214 : &hStereoTD->tdm_lt_corr_RM_fx, &hStereoTD->tdm_last_diff_lt_corr_fx, &hStereoTD->q_tdm_last_diff_lt_corr, &inst_ratio_L_fx, &diff_lt_corr_fx, &q_d_lt_corr_raw );
215 :
216 3827 : IF( GT_16( q_d_lt_corr_raw, 31 ) )
217 : {
218 1365 : d_lt_corr_raw_fx = L_shr( d_lt_corr_raw_fx, sub( q_d_lt_corr_raw, Q31 ) ); /* Q31 */
219 1365 : q_d_lt_corr_raw = Q31;
220 1365 : move16();
221 : }
222 :
223 : /*----------------------------------------------------------------*
224 : * UNCLR classifier (detection of uncorrelated L and R channels)
225 : * Xtalk classifier (detection of cross-talk L and R channels)
226 : *----------------------------------------------------------------*/
227 :
228 3827 : unclr_classifier_td_fx( hCPE );
229 3827 : xtalk_classifier_td_fx( hCPE );
230 :
231 : /* switch to LRTD on cross-talk segments where two speakers are weakly correlated */
232 3827 : hStereoTD->prev_fr_LRTD_TD_dec = hCPE->hStereoClassif->lrtd_mode; /* Q0 */
233 3827 : move16();
234 :
235 : /*----------------------------------------------------------------*
236 : * When the energies of channels are low enough, compute the ratio
237 : * of L and R needed to create new mono/side signals
238 : *----------------------------------------------------------------*/
239 :
240 3827 : IF( EQ_16( ivas_format, MASA_ISM_FORMAT ) )
241 : {
242 0 : test();
243 0 : test();
244 0 : if ( ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) || EQ_16( hCPE->hStereoTD->prev_fr_LRTD_TD_dec, 1 ) ) && ( LE_32( L_add( L_sub( hCPE->element_brate, 50 * FRAMES_PER_SEC ), L_add( hCPE->brate_surplus, hCPE->brate_surplus ) ), IVAS_BRATE_OMASA_STEREO_SW_THR ) ) )
245 : {
246 0 : hStereoTD->prev_fr_LRTD_TD_dec = 0;
247 0 : move16();
248 : }
249 : }
250 :
251 3827 : rms_thd_fx = RMS_MIN_Q16; /* Q16 */
252 3827 : move32();
253 3827 : IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) )
254 : {
255 3827 : rms_thd_fx = L_shr( rms_thd_fx, 2 ); /*Q16*/ /*rms_thd_fx *= 0.25f*/
256 3827 : test();
257 3827 : test();
258 3827 : IF( LE_32( hStereoTD->tdm_lt_rms_L_fx, 4915200 /* 75 in Q16*/ ) || LE_32( hStereoTD->tdm_lt_rms_R_fx, 4915200 /* 75 in Q16*/ ) /*|| sts[0]->last_coder_type == TRANSITION */ )
259 : {
260 442 : rms_thd_fx = L_shr( rms_thd_fx, 5 ); /* Q16*/ /*rms_thd_fx *= 0.03125f*/
261 : }
262 3385 : ELSE IF( GE_16( sts[0]->hVAD->hangover_cnt, 8 ) && GE_16( sts[1]->hVAD->hangover_cnt, 8 ) )
263 : {
264 0 : rms_thd_fx = imult3216( rms_thd_fx, 5 /*1/0.2f*/ ); /*Q16*/ /*rms_thd_fx /= 0.2f*/
265 : }
266 :
267 : /* Overwrite the LR decision flag in case the signals is already considered as S/M or when the signal is very similar between left and right channel */
268 3827 : test();
269 3827 : test();
270 3827 : test();
271 3827 : test();
272 3827 : test();
273 3827 : test();
274 3827 : test();
275 3827 : test();
276 3827 : test();
277 3827 : test();
278 3827 : test();
279 3827 : test();
280 3827 : test();
281 3827 : test();
282 3827 : test();
283 3827 : test();
284 3827 : test();
285 3827 : IF( EQ_16( tdm_SM_flag_loc, 1 ) )
286 : {
287 0 : hStereoTD->prev_fr_LRTD_TD_dec = 0;
288 0 : move16();
289 : }
290 3827 : ELSE IF( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) && GT_16( hStereoTD->tdm_FD2LRTD_SW_cnt, 10 ) &&
291 : ( hCPE->hStereoClassif->vad_flag_glob == 0 || ( hCPE->hStereoClassif->unclr_decision == 0 && ( LT_32( hCPE->hStereoClassif->xtalk_score_fx, -1717986918 /* -0.8f in Q31*/ ) || LT_32( hCPE->hStereoClassif->xtalk_wscore_fx, -279172874 /*-0.13f in Q31*/ ) ) ) ||
292 : ( EQ_16( hCPE->hStereoClassif->unclr_decision, 1 ) && sts[0]->last_clas == UNVOICED_CLAS && sts[1]->last_clas == UNVOICED_CLAS && LT_32( L_abs( hCPE->hStereoClassif->unclr_wscore_fx ), 10737418 /* 0.005f in Q31 */ ) ) ) )
293 : {
294 : /* This forces the LRTD to switch to TD when inactive content happens on both channel */
295 37 : hStereoTD->prev_fr_LRTD_TD_dec = 0;
296 37 : move16();
297 : }
298 3790 : ELSE IF( hStereoTD->tdm_LRTD_flag == 0 &&
299 : ( hCPE->hStereoClassif->vad_flag_glob == 0 || ( hCPE->hStereoClassif->unclr_decision == 0 && ( hCPE->hStereoClassif->xtalk_score_fx <= 0 || LE_32( hCPE->hStereoClassif->xtalk_wscore_fx, 214748364 /*0.1f in Q31 */ ) ) ) ||
300 : ( EQ_16( hCPE->hStereoClassif->unclr_decision, 1 ) && ( sts[0]->last_clas == UNVOICED_CLAS && sts[1]->last_clas == UNVOICED_CLAS ) && LT_32( L_abs( hCPE->hStereoClassif->unclr_wscore_fx ), 53687091 /*0.025f in Q31 */ ) )
301 : /* (sts[0]->last_clas == UNVOICED_CLAS && sts[1]->last_clas == UNVOICED_CLAS && hCPE->hStereoClassif->xtalk_wscore <= 0.0f)*/ ) )
302 : {
303 : /* This forces the LRTD to switch to TD when inactive content happens on both channel */
304 127 : hStereoTD->prev_fr_LRTD_TD_dec = 0;
305 127 : move16();
306 : }
307 : }
308 :
309 3827 : side_can_change = 0;
310 3827 : move16();
311 :
312 : /* update LRTD->DFT stereo hangover counters */
313 3827 : IF( EQ_16( hStereoTD->prev_fr_LRTD_TD_dec, 1 ) )
314 : {
315 3663 : hStereoTD->tdm_last_LRTD_frame_cnt = 0;
316 3663 : move16();
317 : }
318 : ELSE
319 : {
320 164 : hStereoTD->tdm_last_LRTD_frame_cnt = add( hStereoTD->tdm_last_LRTD_frame_cnt, 1 );
321 164 : move16();
322 164 : hStereoTD->tdm_last_LRTD_frame_cnt = s_min( hStereoTD->tdm_last_LRTD_frame_cnt, 100 );
323 164 : move16();
324 : }
325 :
326 3827 : IF( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) )
327 : {
328 62 : side_can_change = 1;
329 62 : move16();
330 : }
331 :
332 3827 : rms_L_fx = L_shl( rms_L_fx, sub( Q16, q_rms_L ) ); /* All the following energy comparison are done in Q16 */
333 3827 : rms_R_fx = L_shl( rms_R_fx, sub( Q16, q_rms_R ) );
334 3827 : test();
335 3827 : IF( EQ_16( hStereoTD->prev_fr_LRTD_TD_dec, 1 ) && side_can_change == 0 )
336 : {
337 3601 : test();
338 3601 : test();
339 3601 : test();
340 3601 : test();
341 3601 : IF( ( LE_32( hStereoTD->tdm_lt_rms_L_fx, rms_thd_fx ) && LE_32( hStereoTD->tdm_lt_rms_R_fx, L_shl( rms_thd_fx, 1 ) ) ) ||
342 : ( LE_32( hStereoTD->tdm_lt_rms_R_fx, rms_thd_fx ) && LE_32( hStereoTD->tdm_lt_rms_L_fx, L_shl( rms_thd_fx, 1 ) ) ) ||
343 : ( sts[0]->hVAD->hangover_cnt != 0 && LT_32( sts[1]->hNoiseEst->Etot_last_32fx, 201326592 /*12 in Q24*/ ) ) ||
344 : ( sts[1]->hVAD->hangover_cnt != 0 && LT_32( sts[0]->hNoiseEst->Etot_last_32fx, 201326592 /*12 in Q24*/ ) ) ||
345 : ( NE_16( sts[0]->hSpMusClas->past_dec[0], sts[1]->hSpMusClas->past_dec[0] ) ) )
346 : {
347 2090 : test();
348 2090 : test();
349 2090 : test();
350 2090 : test();
351 2090 : test();
352 2090 : test();
353 2090 : test();
354 2090 : test();
355 2090 : IF( ( ( LT_32( rms_L_fx, RMS_THR_Q16 ) && LT_32( rms_R_fx, RMS_THR_Q16 ) && LT_32( L_abs( L_sub( rms_R_fx, rms_L_fx ) ), RMS_THR_Q16 / 2 ) && GT_32( L_abs( d_lt_corr_raw_fx ), L_shr( 644245094 /*0.3f in Q31*/, sub( Q31, q_d_lt_corr_raw ) ) ) ) ||
356 : ( LT_16( abs_s( sub( sts[0]->old_corr_fx, sts[1]->old_corr_fx ) ), 4915 /*0.15f in Q15*/ ) && GT_16( sts[0]->old_corr_fx, 22937 /*0.7f in Q15*/ ) && LT_16( sts[0]->old_corr_fx, 27853 /*0.85f in Q15*/ ) && LT_32( L_abs( L_sub( rms_L_fx, rms_R_fx ) ), rms_thd_fx ) && GT_32( L_abs( d_lt_corr_raw_fx ), L_shr( 644245094 /*0.3f in Q31*/, sub( Q31, q_d_lt_corr_raw ) ) ) ) ) /* Both channels are low energy, clean background switching is allowed */
357 : )
358 : {
359 163 : side_can_change = 1;
360 163 : move16();
361 : }
362 : }
363 : }
364 226 : ELSE IF( side_can_change == 0 ) /*if( hStereoTD->prev_fr_LRTD_TD_dec == 0 )*/
365 : {
366 164 : test();
367 164 : test();
368 164 : test();
369 164 : test();
370 164 : test();
371 164 : test();
372 164 : test();
373 164 : test();
374 164 : test();
375 164 : test();
376 164 : test();
377 164 : test();
378 164 : IF( ( ( LT_16( sts[0]->old_corr_fx, CORR_THRES_Q15 ) && LT_16( sts[1]->old_corr_fx, CORR_THRES_Q15 ) ) || ( LE_32( hStereoTD->tdm_lt_rms_L_fx, RMS_MIN2_Q16 ) && LE_32( hStereoTD->tdm_lt_rms_R_fx, RMS_MIN2_Q16 ) ) ) &&
379 : ( ( ( LE_32( hStereoTD->tdm_lt_rms_L_fx, rms_thd_fx ) && LE_32( hStereoTD->tdm_lt_rms_R_fx, L_shl( rms_thd_fx, 1 ) ) ) || ( LE_32( hStereoTD->tdm_lt_rms_R_fx, rms_thd_fx ) && LE_32( hStereoTD->tdm_lt_rms_L_fx, L_shl( rms_thd_fx, 1 ) ) ) ) ||
380 : ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( sts[0]->tdm_LRTD_flag == 0 || ( EQ_16( sts[0]->tdm_LRTD_flag, 1 ) && ( ( LT_32( rms_L_fx, L_shl( rms_thd_fx, 1 ) ) && LT_32( rms_R_fx, L_shl( rms_thd_fx, 1 ) ) ) || ( NE_16( sts[0]->hSpMusClas->past_dec[0], sts[1]->hSpMusClas->past_dec[0] ) ) ) ) ) ) /* Even if the UNCLR is set to 1, the content should be encoded with TD, lower swichting requierment */
381 : ) )
382 : {
383 156 : side_can_change = 1;
384 156 : move16();
385 : }
386 : }
387 :
388 3827 : test();
389 3827 : test();
390 3827 : IF( GE_32( hCPE->hStereoClassif->xtalk_wscore_fx, 107374182 /*0.05f in Q31*/ ) && hStereoTD->prev_fr_LRTD_TD_dec == 0 && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) )
391 : {
392 2 : side_can_change = 0;
393 2 : move16();
394 : }
395 3827 : test();
396 3827 : test();
397 3827 : IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_MDCT ) || EQ_16( hStereoTD->flag_skip_DMX, 1 ) )
398 : {
399 100 : desired_idx = LRTD_STEREO_LEFT_IS_PRIM;
400 100 : move16();
401 100 : hStereoTD->tdm_prev_desired_idx = LRTD_STEREO_LEFT_IS_PRIM;
402 100 : move16();
403 100 : ratio_L_fx = ONE_IN_Q31; /*Q31*/
404 100 : move32();
405 100 : hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_LEFT_IS_PRIM;
406 100 : move16();
407 100 : hStereoTD->tdm_ratio_transition_mov_flag = 0;
408 100 : move16();
409 100 : hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_LEFT_IS_PRIM;
410 100 : move16();
411 100 : hStereoTD->tdm_ratio_transition_cnt = 0;
412 100 : move16();
413 100 : idx = TDM_NQ; /* Reserved quantizer index for special case */
414 100 : move16();
415 : }
416 3727 : ELSE IF( side_can_change || LE_16( sts[1]->ini_frame, 1 ) )
417 : {
418 398 : ratio_L_fx = L_max( diff_lt_corr_fx, -RATIO_MAX_FX_Q24 ); // Q24
419 398 : ratio_L_fx = L_min( ratio_L_fx, RATIO_MAX_FX_Q24 ); // Q24
420 398 : ratio_L_fx = Madd_32_32( ONE_IN_Q24, 1432371593 /*0.667f in Q31*/, ratio_L_fx ); // Q24
421 :
422 398 : test();
423 398 : test();
424 398 : IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) || LT_16( hStereoTD->tdm_FD2LRTD_SW_cnt, 4 ) ) )
425 : {
426 90 : ratio_L_fx = hCPE->hStereoTD->tdm_last_ratio_fx; // Q31 /* note: the last_ratio is set in before in stereo_set_tdm() */
427 90 : move32();
428 : }
429 : ELSE
430 : {
431 : /*ratio_L = ( 1.0f - cosf( EVS_PI * ratio_L / 2.0f ) ) / 2.0f;*/
432 308 : ratio_L_fx = L_deposit_h( sub_sat( ONE_IN_Q14, getCosWord16( extract_l( Mpy_32_32( 1647099 /* EVS_PI/2 in Q20 */, ratio_L_fx ) ) ) ) ); // Q31 (Q14 + Q1(division by 2.0f) + Q16)
433 : }
434 :
435 398 : test();
436 398 : test();
437 398 : test();
438 398 : IF( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) || ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( hCPE->hStereoClassif->prev_lrtd_mode == 0 || GT_16( abs_s( sub( hCPE->hStereoTCA->indx_ica_gD, 20 ) ), 2 ) ) ) )
439 : {
440 277 : IF( GE_32( ratio_L_fx, 1138166333 /*0.53f in Q31*/ ) ) /* small hysteresis is used to prevent undesired switching during inactive segment */
441 : {
442 143 : desired_idx = LRTD_STEREO_LEFT_IS_PRIM - 1;
443 143 : move16();
444 : }
445 134 : ELSE IF( LT_32( ratio_L_fx, 1009317315 /*0.47f in Q31*/ ) )
446 : {
447 99 : desired_idx = LRTD_STEREO_RIGHT_IS_PRIM + 1;
448 99 : move16();
449 : }
450 35 : ELSE IF( GT_32( L_sub( rms_L_fx, rms_R_fx ), 655360 /*10 in Q16*/ ) )
451 : {
452 0 : desired_idx = LRTD_STEREO_LEFT_IS_PRIM - 1;
453 0 : move16();
454 : }
455 : ELSE
456 : {
457 35 : desired_idx = LRTD_STEREO_RIGHT_IS_PRIM + 1;
458 35 : move16();
459 : }
460 :
461 277 : test();
462 277 : test();
463 277 : IF( NE_16( desired_idx, hStereoTD->tdm_prev_desired_idx ) && EQ_16( hStereoTD->tdm_last_LRTD_frame_cnt, 1 ) && LE_16( sts[0]->last_coder_type, UNVOICED ) ) /* TD transtionning to FD, we don't want an inversion of channels on the first transition frame */
464 : {
465 0 : desired_idx = hStereoTD->tdm_prev_desired_idx;
466 0 : move16();
467 : }
468 : ELSE
469 : {
470 277 : hStereoTD->tdm_prev_desired_idx = desired_idx;
471 277 : move16();
472 : }
473 277 : idx = desired_idx;
474 277 : move16();
475 : }
476 : ELSE
477 : {
478 121 : test();
479 121 : test();
480 121 : IF( GE_32( hCPE->element_brate, IVAS_48k ) && sts[0]->hVAD->hangover_cnt != 0 && LT_32( L_max( hStereoTD->tdm_lt_rms_L_fx, hStereoTD->tdm_lt_rms_R_fx ), 33554432 /* 512.0f in Q16*/ ) )
481 : {
482 0 : ratio_L_fx = check_bounds_l( ratio_L_fx, 644245094 /*0.3f in Q31*/, 1503238554 /*0.7f in Q31*/ ); /* Q31 */
483 : }
484 :
485 121 : test();
486 121 : test();
487 121 : test();
488 121 : test();
489 121 : IF( ( GT_32( hCPE->hStereoTCA->instTargetGain_fx, 644245094 /*1.2f in Q29*/ ) || GT_32( hCPE->hStereoTCA->targetGain_fx, ONE_IN_Q29 ) ) && LT_32( ratio_L_fx, 858993459 /*0.4f in Q31*/ ) )
490 : {
491 59 : ratio_L_fx = 858993459; /*0.4f in Q31*/
492 59 : move32();
493 : }
494 62 : ELSE IF( ( LT_32( hCPE->hStereoTCA->instTargetGain_fx, 429496730 /*0.8f*/ ) || LT_32( hCPE->hStereoTCA->targetGain_fx, ONE_IN_Q29 ) ) && GT_32( ratio_L_fx, 1288490189 /*0.6f in Q31*/ ) )
495 : {
496 0 : ratio_L_fx = 1288490189; /* 0.6f in Q31 */
497 0 : move32();
498 : }
499 :
500 121 : dist_fx = L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx[0] ) ); // Q31
501 :
502 121 : desired_idx = 0;
503 121 : move16();
504 3751 : FOR( i = 1; i < TDM_NQ; i++ )
505 : {
506 3630 : IF( LE_32( L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx[i] ) ), dist_fx ) )
507 : {
508 1730 : dist_fx = L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx[i] ) ); // Q31
509 1730 : desired_idx = i;
510 1730 : move16();
511 : }
512 : }
513 :
514 121 : idx = stereo_smooth_LR_transition_fx( &hStereoTD->tdm_prev_stable_idx, &hStereoTD->tdm_ratio_transition_mov_flag, hStereoTD->tdm_last_ratio_idx, &hStereoTD->tdm_prev_desired_idx, &hStereoTD->tdm_ratio_transition_cnt, tdm_SM_flag_loc, desired_idx ); /* Q0 */
515 :
516 : /* Change the switching level in case of dual mono (in case the scenario still accept left right switching */
517 : /* This logic is needed in case the content is exactly the same in the 2 channel and it is expected to get back to LRTD, to prevent the secondary channel to be completely empty */
518 121 : IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) )
519 : {
520 121 : IF( LE_16( idx, LRTD_STEREO_MID_IS_PRIM ) )
521 : {
522 69 : idx = s_min( idx, LRTD_STEREO_MID_IS_PRIM - 1 );
523 : }
524 : ELSE
525 : {
526 52 : idx = s_max( idx, LRTD_STEREO_MID_IS_PRIM + 1 );
527 : }
528 :
529 121 : hStereoTD->tdm_prev_desired_idx = idx;
530 121 : move16();
531 : }
532 : /* 0 and 30 are reserved to signal L-R only coding */
533 : }
534 : }
535 : ELSE
536 : {
537 3329 : idx = hStereoTD->tdm_last_ratio_idx;
538 3329 : move16();
539 : }
540 :
541 3827 : hStereoTD->tdm_inst_ratio_idx = LRTD_STEREO_RIGHT_IS_PRIM;
542 3827 : move16();
543 3827 : tdm_LRTD_pri_side = -1;
544 3827 : move16();
545 3827 : IF( LT_16( hStereoTD->tdm_FD2LRTD_SW_cnt, 5 ) )
546 : {
547 245 : desired_idx = 15;
548 245 : move16();
549 : }
550 : ELSE
551 : {
552 3582 : desired_idx = 0;
553 3582 : move16();
554 3582 : dist_fx = L_abs( L_sub( inst_ratio_L_fx, L_shr( tdm_ratio_tabl_fx[0], 7 ) ) ); // Q24
555 :
556 111042 : FOR( i = 1; i < TDM_NQ; i++ )
557 : {
558 107460 : IF( LE_32( L_abs( L_sub( inst_ratio_L_fx, L_shr( tdm_ratio_tabl_fx[i], 7 ) ) ), dist_fx ) )
559 : {
560 51770 : dist_fx = L_abs( L_sub( inst_ratio_L_fx, L_shr( tdm_ratio_tabl_fx[i], 7 ) ) ); // Q24
561 51770 : desired_idx = i;
562 51770 : move16();
563 : }
564 : }
565 : }
566 :
567 3827 : IF( LT_16( sub( sts[1]->lp_speech_fx, sts[1]->lp_noise_fx ), 12800 /*50.0f in Q8*/ ) ) /* likely presence of noisy content */
568 : {
569 : /* pointing in the right direction, inverse it else do nothing */
570 33 : test();
571 33 : test();
572 33 : test();
573 33 : test();
574 33 : IF( ( GT_16( idx, LRTD_STEREO_MID_IS_PRIM ) && GT_16( desired_idx, LRTD_STEREO_MID_IS_PRIM ) ) || ( LT_16( idx, LRTD_STEREO_MID_IS_PRIM ) && LT_16( desired_idx, LRTD_STEREO_MID_IS_PRIM ) ) )
575 : {
576 : Word16 idx_offet;
577 0 : idx_offet = 5;
578 0 : move16();
579 0 : IF( GT_16( desired_idx, LRTD_STEREO_MID_IS_PRIM ) ) /* slightly Favor the 2nd channel */
580 : {
581 0 : idx_offet = negate( idx_offet );
582 : }
583 0 : desired_idx = add( desired_idx, idx_offet );
584 0 : desired_idx = check_bounds_s_fx( desired_idx, 0, 30 ); /* Q0 */
585 : }
586 : }
587 :
588 3827 : test();
589 3827 : IF( sts[1]->clas != UNVOICED_CLAS || sts[0]->clas != UNVOICED_CLAS )
590 : {
591 2936 : desired_idx = check_bounds_s_fx( desired_idx, 5, 25 ); /* Q0 */
592 : }
593 :
594 3827 : hStereoTD->tdm_inst_ratio_idx = desired_idx;
595 3827 : move16();
596 3827 : IF( /*hCPE->last_element_mode == IVAS_CPE_MDCT ||*/ EQ_16( hStereoTD->flag_skip_DMX, 1 ) )
597 : {
598 : /*force tdm_inst_ratio_idx to the reserved index */
599 100 : hStereoTD->tdm_inst_ratio_idx = idx;
600 100 : move16();
601 100 : tdm_LRTD_pri_side = 1; /* left channel */
602 100 : move16();
603 : }
604 3727 : ELSE IF( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) )
605 : {
606 3598 : idx = limit_idx_NoDwnmix_fx( idx, side_can_change, d_lt_corr_raw_fx, q_d_lt_corr_raw );
607 :
608 3598 : hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_LEFT_IS_PRIM;
609 3598 : move16();
610 3598 : tdm_LRTD_pri_side = 0; /* right channel */
611 3598 : move16();
612 3598 : IF( idx != LRTD_STEREO_RIGHT_IS_PRIM )
613 : {
614 3330 : tdm_LRTD_pri_side = 1; /* left channel */
615 3330 : move16();
616 3330 : hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_RIGHT_IS_PRIM;
617 3330 : move16();
618 : }
619 : }
620 : ELSE
621 : {
622 129 : test();
623 129 : test();
624 129 : idx = limit_idx_Dwnmix_fx( idx, ( hCPE->hStereoClassif->unclr_decision || ( EQ_16( sts[0]->flag_noisy_speech_snr, 1 ) && GT_32( hCPE->hStereoClassif->xtalk_wscore_fx, 214748365 /*0.1f*/ ) ) ), desired_idx, hStereoTD->tdm_last_ratio_idx, hStereoTD->tdm_last_LRTD_PriCh_cnt, hStereoTD->tdm_last_LRTD_frame_cnt );
625 : }
626 :
627 3827 : IF( GT_16( abs_s( sub( hStereoTD->tdm_last_ratio_idx, idx ) ), LRTD_STEREO_MID_IS_PRIM ) )
628 : {
629 35 : hStereoTD->tdm_last_LRTD_PriCh_cnt = 0;
630 35 : move16();
631 : }
632 : ELSE
633 : {
634 3792 : hStereoTD->tdm_last_LRTD_PriCh_cnt = add( hStereoTD->tdm_last_LRTD_PriCh_cnt, 1 );
635 3792 : move16();
636 : }
637 :
638 3827 : ratio_L_fx = tdm_ratio_tabl_fx_Q30[idx]; // Q30
639 3827 : move32();
640 :
641 3827 : test();
642 3827 : IF( EQ_16( hStereoTD->tdm_SM_modi_flag, 1 ) && hStereoTD->tdm_LRTD_flag == 0 )
643 : {
644 0 : idx = shr( add( hStereoTD->tdm_last_ratio_idx, add( LRTD_STEREO_MID_IS_PRIM, 1 ) ), 1 );
645 0 : ratio_L_fx = tdm_ratio_tabl_fx_Q30[idx]; // Q30
646 0 : move32();
647 : }
648 :
649 3827 : test();
650 3827 : test();
651 3827 : test();
652 3827 : IF( ( EQ_16( hStereoTD->tdm_ratio_transition_mov_flag, 1 ) && GE_16( hStereoTD->tdm_ratio_transition_cnt, 31 ) ) || ( ( EQ_16( hStereoTD->tdm_last_SM_flag, tdm_SM_flag_loc ) ) && ( EQ_16( idx, hStereoTD->tdm_prev_stable_idx ) ) ) )
653 : {
654 46 : hStereoTD->tdm_ratio_transition_cnt = 0;
655 46 : move16();
656 46 : hStereoTD->tdm_ratio_transition_mov_flag = 0;
657 46 : move16();
658 : }
659 :
660 3827 : test();
661 3827 : if ( hStereoTD->tdm_ratio_transition_mov_flag == 0 || tdm_SM_flag_loc == 0 )
662 : {
663 3827 : hStereoTD->tdm_prev_stable_idx = idx;
664 3827 : move16();
665 : }
666 :
667 : /* NOOP ratio calculation */
668 3827 : IF( tdm_SM_flag_loc )
669 : {
670 0 : IF( hStereoTD->tdm_SM_reset_flag )
671 : {
672 0 : hStereoTD->tdm_lt_corr_RM_SM_fx = 167772 /*0.01f Q24*/;
673 0 : move32();
674 0 : hStereoTD->tdm_lt_corr_LM_SM_fx = 167772 /*0.01f Q24*/;
675 0 : move32();
676 0 : hStereoTD->tdm_last_ratio_SM_fx = hStereoTD->tdm_last_ratio_fx; /* Q31 */
677 0 : move32();
678 0 : hStereoTD->tdm_last_ratio_idx_SM = hStereoTD->tdm_last_ratio_idx; /* Q0 */
679 0 : move16();
680 0 : hStereoTD->tdm_lt_rms_L_SM_fx = 2621440; // 40.0f Q16
681 0 : move32();
682 0 : hStereoTD->tdm_lt_rms_R_SM_fx = 2621440; // 40.0f Q16
683 0 : move32();
684 0 : hStereoTD->tdm_last_diff_lt_corr_SM_fx = 0;
685 0 : move32();
686 0 : hStereoTD->q_tdm_last_diff_lt_corr_SM = 0;
687 0 : move16();
688 0 : hStereoTD->tdm_last_ener_lt_R_SM_fx = 0;
689 0 : move32();
690 0 : hStereoTD->tdm_last_ener_lt_L_SM_fx = 0;
691 0 : move32();
692 :
693 0 : hStereoTD->tdm_noop_mov_flag = 0;
694 0 : move16();
695 0 : hStereoTD->tdm_noop_cnt = 0;
696 0 : move16();
697 0 : hStereoTD->tdm_last_SM_flag_noop = 0;
698 0 : move16();
699 0 : hStereoTD->tdm_prev_stable_idx_SM = 0;
700 0 : move16();
701 0 : hStereoTD->tdm_prev_desired_idx_SM = 0;
702 0 : move16();
703 0 : hStereoTD->tdm_LT_es_em_SM_fx = 209715; // 0.1f Q21;
704 0 : move32();
705 0 : hStereoTD->tdm_hyst_cnt_SM = 0;
706 0 : move16();
707 : }
708 :
709 0 : *tdm_ratio_idx_SM = stereo_tdm_ener_analysis_SM_fx( hCPE, sts, input_frame, &tdm_NOOP_flag ); /* Q0 */
710 0 : move16();
711 : }
712 : ELSE
713 : {
714 3827 : *tdm_ratio_idx_SM = LRTD_STEREO_MID_IS_PRIM;
715 3827 : move16();
716 3827 : tdm_NOOP_flag = 1;
717 3827 : move16();
718 : }
719 :
720 3827 : sts[0]->tdm_LRTD_flag = hStereoTD->tdm_LRTD_flag;
721 3827 : move16();
722 3827 : sts[1]->tdm_LRTD_flag = hStereoTD->tdm_LRTD_flag;
723 3827 : move16();
724 :
725 : /* set channel combination scheme flag */
726 3827 : *tdm_SM_or_LRTD_Pri = tdm_SM_flag_loc; /* Q0 */
727 3827 : move16();
728 3827 : if ( EQ_16( hCPE->hStereoTD->tdm_LRTD_flag, 1 ) )
729 : {
730 3698 : *tdm_SM_or_LRTD_Pri = tdm_LRTD_pri_side; /* Q0 */
731 3698 : move16();
732 : }
733 :
734 3827 : hCPE->hStereoClassif->ratio_L_fx = ratio_L_fx; /* 31 - ratio_L_e */
735 3827 : move32();
736 3827 : hCPE->hStereoClassif->ratio_L_e = 1;
737 3827 : move16();
738 :
739 3827 : return idx;
740 : }
741 :
742 : /*-------------------------------------------------------------------*
743 : * Function Get_LR_rms_fx()
744 : *
745 : * Get current frame left and right rms values
746 : *-------------------------------------------------------------------*/
747 :
748 3827 : static void Get_LR_rms_fx(
749 : const Word16 *Left_in, /* q_inp */
750 : const Word16 *Right_in, /* q_inp */
751 : const Word16 input_frame, /* Q0 */
752 : Word32 *rms_L, /* q_rms_L */
753 : Word16 *q_rms_L,
754 : Word32 *rms_R, /* q_rms_R */
755 : Word16 *q_rms_R )
756 : {
757 : Word32 ener_l, ener_r;
758 : Word32 ener_l_tmp, ener_r_tmp;
759 : Word16 guard_bits;
760 : Word64 W_ener_l_tmp, W_ener_r_tmp;
761 : Word16 i;
762 : Word16 exp_out_l, exp_out_r, exp_diff;
763 :
764 3827 : W_ener_l_tmp = 0;
765 3827 : move64();
766 3827 : W_ener_r_tmp = 0;
767 3827 : move64();
768 3827 : ener_l = ONE_BY_100_Q31; /* Q31 */
769 3827 : move32();
770 3827 : ener_r = ONE_BY_100_Q31; /* Q31 */
771 3827 : move32();
772 :
773 3827 : guard_bits = sub( 32, find_guarded_bits_fx( input_frame ) );
774 2507827 : FOR( i = 0; i < input_frame; i++ )
775 : {
776 2504000 : W_ener_l_tmp = W_mac0_16_16( W_ener_l_tmp, Left_in[i], Left_in[i] ); // Q0
777 2504000 : W_ener_r_tmp = W_mac0_16_16( W_ener_r_tmp, Right_in[i], Right_in[i] ); // Q0
778 : }
779 : /* Scaling back to the original proposal */
780 3827 : ener_l_tmp = W_extract_h( W_shl( W_ener_l_tmp, guard_bits ) ); // guard_bits - 32
781 3827 : ener_r_tmp = W_extract_h( W_shl( W_ener_r_tmp, guard_bits ) ); // guard_bits - 32
782 :
783 3827 : ener_l = BASOP_Util_Add_Mant32Exp( ener_l, 0, ener_l_tmp, sub( Q31, sub( guard_bits, 32 ) ), &exp_out_l ); /* Q31-exp_out_l */
784 3827 : ener_r = BASOP_Util_Add_Mant32Exp( ener_r, 0, ener_r_tmp, sub( Q31, sub( guard_bits, 32 ) ), &exp_out_r ); /* Q31-exp_out_r */
785 :
786 3827 : ener_l_tmp = BASOP_Util_Divide3232_Scale( ener_l, input_frame, &exp_diff ); /* Q31- exp_out_l*/
787 3827 : exp_out_l = sub( add( exp_diff, exp_out_l ), Q15 );
788 3827 : ener_r_tmp = BASOP_Util_Divide3232_Scale( ener_r, input_frame, &exp_diff ); /* Q31-exp_out_r */
789 3827 : exp_out_r = sub( add( exp_diff, exp_out_r ), Q15 );
790 :
791 3827 : *rms_L = Sqrt32( ener_l_tmp, &exp_out_l ); // Q31 - exp_out_l
792 3827 : move32();
793 3827 : *q_rms_L = sub( Q31, exp_out_l );
794 3827 : move16();
795 3827 : *rms_R = Sqrt32( ener_r_tmp, &exp_out_r ); // Q31 - exp_out_r
796 3827 : move32();
797 3827 : *q_rms_R = sub( Q31, exp_out_r );
798 3827 : move16();
799 :
800 3827 : return;
801 : }
802 :
803 :
804 : /*-------------------------------------------------------------------*
805 : * Function Get_dt_lt_ener_fx()
806 : *
807 : * Compute the gain of L&R channel compared to mono
808 : * - estimate the long term evolution of the L to Mono gain
809 : * - estimate the long term evolution of the R to Mono gain
810 : * - estimate the long term difference between the long term
811 : * - evolution of the L and R to Mono gain
812 : *-------------------------------------------------------------------*/
813 :
814 3827 : static Word16 Get_dt_lt_ener_fx(
815 : CPE_ENC_HANDLE hCPE,
816 : const Word16 IsSideMono, /* Q0 */
817 : const Word16 input_frame, /* Q0 */
818 : const Word16 tdm_last_SM_flag, /* Q0 */
819 : const Word32 rms_L, /* q_rms_L */
820 : const Word16 q_rms_L,
821 : const Word32 rms_R, /* q_rms_R */
822 : const Word16 q_rms_R,
823 : Word32 *tdm_lt_rms_L, /* Q16 */
824 : Word32 *tdm_lt_rms_R, /* Q16 */
825 : Word32 *tdm_last_ener_lt_L, /* Q16 */
826 : Word32 *tdm_last_ener_lt_R, /* Q16 */
827 : Word32 *tdm_LT_es_em, /* Q21 */
828 : Word16 *tdm_hyst_cnt, /* Q0 */
829 : Word16 *tdm_NOOP_SM_flag_loc, /* Q0 */
830 : Word32 *ener_R_dt, /* Q16 */
831 : Word32 *ener_L_dt, /* Q16 */
832 : Word32 *corr_LM, /* q_corr_LM */
833 : Word16 *q_corr_LM,
834 : Word32 *corr_RM, /* q_corr_RM */
835 : Word16 *q_corr_RM )
836 : {
837 : Encoder_State **sts;
838 : Word16 *Left_in_fx, *Right_in_fx;
839 : Word32 es_em_fx;
840 : Word16 tmp_SM_flag, tdm_SM_flag_loc;
841 : Word32 L_tmp, L_tmp1;
842 : Word16 exp_diff, tmp;
843 :
844 3827 : sts = hCPE->hCoreCoder;
845 :
846 3827 : Left_in_fx = sts[0]->input_fx; /* Left channel sts[0]->q_inp*/
847 3827 : Right_in_fx = sts[1]->input_fx; /* Right channel sts[1]->q_inp*/
848 :
849 3827 : tmp = sub( getScaleFactor16( sts[0]->input_fx, input_frame ), 1 );
850 3827 : Scale_sig( sts[0]->input_fx, input_frame, tmp ); /* sts[0]->q_inp + tmp */
851 3827 : sts[0]->q_inp = add( tmp, sts[0]->q_inp );
852 3827 : move16();
853 :
854 3827 : tmp = getScaleFactor16( sts[1]->input_fx, input_frame );
855 3827 : Scale_sig( sts[1]->input_fx, input_frame, tmp ); /* sts[1]->q_inp + tmp */
856 3827 : sts[1]->q_inp = add( tmp, sts[1]->q_inp );
857 3827 : move16();
858 :
859 3827 : Scale_sig( sts[0]->input_fx, input_frame, sub( s_min( sts[0]->q_inp, sts[1]->q_inp ), sts[0]->q_inp ) ); /* s_min( sts[0]->q_inp, sts[1]->q_inp ) */
860 3827 : Scale_sig( sts[1]->input_fx, input_frame, sub( s_min( sts[0]->q_inp, sts[1]->q_inp ), sts[1]->q_inp ) ); /* s_min( sts[0]->q_inp, sts[1]->q_inp ) */
861 3827 : sts[1]->q_inp = s_min( sts[0]->q_inp, sts[1]->q_inp );
862 3827 : move16();
863 3827 : sts[0]->q_inp = sts[1]->q_inp;
864 3827 : move16();
865 :
866 3827 : tdm_SM_flag_loc = tdm_last_SM_flag; /* Q0 */
867 3827 : move16();
868 :
869 3827 : test();
870 3827 : IF( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) && IsSideMono == 0 ) /* last coding mode not TD and normal mono/side case, quick update of lt energy */
871 : {
872 62 : *tdm_lt_rms_L = L_shl( Mpy_32_32( 1932735282 /* 0.9f in Q31 */, rms_L ), sub( Q16, q_rms_L ) ); // (Q31, q_rms_L) -> q_rms_L -> Q16
873 62 : move32();
874 62 : *tdm_lt_rms_R = L_shl( Mpy_32_32( 1932735282 /* 0.9f in Q31 */, rms_R ), sub( Q16, q_rms_R ) ); // (Q31, q_rms_R) -> q_rms_R -> Q16
875 62 : move32();
876 62 : L_tmp = Mpy_32_32( 1932735282 /* 0.9f in Q31 */, sts[0]->hNoiseEst->Etot_last_32fx ); //(Q31, Q24) -> Q24
877 62 : sts[1]->hNoiseEst->Etot_last_32fx = L_tmp; // (Q24 >> Q16) -> Q8
878 62 : sts[1]->hVAD->hangover_cnt = 0;
879 62 : move16();
880 : }
881 : ELSE
882 : {
883 3765 : L_tmp = Mpy_32_32( 1288490188 /* 0.6f in Q31 */, *tdm_lt_rms_L ); // Q16
884 3765 : L_tmp1 = Mpy_32_32( 858993459 /* 0.4f in Q31 */, rms_L ); // q_rms_L
885 3765 : *tdm_lt_rms_L = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q16, L_tmp1, sub( Q31, q_rms_L ), &exp_diff ); //(Q31 - exp_diff)
886 3765 : move32();
887 3765 : *tdm_lt_rms_L = L_shl( *tdm_lt_rms_L, sub( Q16, sub( Q31, exp_diff ) ) ); // Q16
888 3765 : move32();
889 3765 : L_tmp = Mpy_32_32( 1288490188 /* 0.6f in Q31 */, *tdm_lt_rms_R ); // Q16
890 3765 : L_tmp1 = Mpy_32_32( 858993459 /* 0.4f in Q31 */, rms_R ); // q_rms_L
891 3765 : *tdm_lt_rms_R = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q16, L_tmp1, sub( Q31, q_rms_R ), &exp_diff ); //(Q31 - exp_diff)
892 3765 : move32();
893 3765 : *tdm_lt_rms_R = L_shl( *tdm_lt_rms_R, sub( Q16, sub( Q31, exp_diff ) ) ); // Q16
894 3765 : move32();
895 : }
896 :
897 : /*----------------------------------------------------------------*
898 : * Compute the 1st order energy difference difference
899 : *----------------------------------------------------------------*/
900 :
901 3827 : *ener_R_dt = L_sub( *tdm_lt_rms_R, *tdm_last_ener_lt_R ); // Q16
902 3827 : move32();
903 3827 : *tdm_last_ener_lt_R = *tdm_lt_rms_R; // Q16
904 3827 : move32();
905 :
906 3827 : *ener_L_dt = L_sub( *tdm_lt_rms_L, *tdm_last_ener_lt_L ); // Q16
907 3827 : move32();
908 3827 : *tdm_last_ener_lt_L = *tdm_lt_rms_L; // Q16
909 3827 : move32();
910 :
911 : /*----------------------------------------------------------------*
912 : * Compute the gain of L&R channel compared to mono
913 : * - estimate the long term evolution of the L to Mono gain
914 : * - estimate the long term evolution of the R to Mono gain
915 : * - estimate the long term difference between the long term
916 : * - evolution of the L and R to Mono gain
917 : *----------------------------------------------------------------*/
918 :
919 3827 : Get_corr_n_fx( Left_in_fx, Right_in_fx, corr_LM, q_corr_LM, corr_RM, q_corr_RM, input_frame, &es_em_fx, IsSideMono );
920 :
921 3827 : hCPE->hStereoClassif->xtalk_fv_fx[E_diff_corrLM_corrRM] = BASOP_Util_Add_Mant32Exp( *corr_LM, sub( Q31, *q_corr_LM ), L_negate( *corr_RM ), sub( Q31, *q_corr_RM ), &exp_diff ); /* Q31-exp_diff */
922 3827 : move32();
923 3827 : hCPE->hStereoClassif->xtalk_fv_fx[E_diff_corrLM_corrRM] = L_shl( hCPE->hStereoClassif->xtalk_fv_fx[E_diff_corrLM_corrRM], sub( Q15, sub( Q31, exp_diff ) ) ); // Q15
924 3827 : move32();
925 :
926 3827 : IF( sts[0]->hVAD->hangover_cnt != 0 )
927 : {
928 399 : *tdm_LT_es_em = Mpy_32_32( 1932735282 /* 0.9f in Q31 */, *tdm_LT_es_em ); // Q21
929 399 : move32();
930 : }
931 : ELSE
932 : {
933 3428 : *tdm_LT_es_em = L_add( Mpy_32_32( 1932735282 /* 0.9f in Q31 */, *tdm_LT_es_em ), Mpy_32_32( 214748365 /* 0.1f in Q31 */, es_em_fx ) ); // Q21
934 3428 : move32();
935 : }
936 :
937 3827 : hCPE->hStereoClassif->xtalk_fv_fx[E_tdm_LT_es_em] = L_shr( *tdm_LT_es_em, 6 ); // Q15
938 3827 : move32();
939 :
940 3827 : tmp_SM_flag = 0;
941 3827 : move16();
942 :
943 3827 : test();
944 3827 : test();
945 3827 : test();
946 3827 : test();
947 3827 : test();
948 3827 : test();
949 3827 : IF( LT_16( s_min( sts[0]->old_corr_fx, sts[1]->old_corr_fx ), 27853 /* 0.85f in Q15 */ ) && LT_16( s_max( sts[0]->old_corr_fx, sts[1]->old_corr_fx ), 30147 /* 0.92f in Q15 */ ) &&
950 : ( GT_32( *tdm_LT_es_em, ONE_IN_Q22 /* 2.0f in Q21 */ ) || GT_32( es_em_fx, 5242880 /* 2.5f in Q21 */ ) ) && ( LE_16( sts[0]->hVAD->hangover_cnt, 1 ) && LE_16( sts[1]->hVAD->hangover_cnt, 3 ) && sts[0]->tdm_LRTD_flag == 0 ) )
951 : {
952 1 : tmp_SM_flag = 1;
953 1 : move16();
954 : }
955 3827 : if ( IsSideMono == 0 )
956 : {
957 3827 : *tdm_NOOP_SM_flag_loc = tdm_SM_flag_loc;
958 3827 : move16();
959 : }
960 :
961 3827 : IF( NE_16( tmp_SM_flag, tdm_SM_flag_loc ) )
962 : {
963 1 : test();
964 1 : test();
965 1 : test();
966 1 : IF( GE_16( *tdm_hyst_cnt, 2 ) && EQ_16( tmp_SM_flag, 1 ) && ( GT_16( sts[0]->tdm_pc, PC_LIMIT ) || GT_16( sts[1]->tdm_pc, PC_LIMIT ) ) )
967 : {
968 0 : tdm_hyst_cnt++;
969 0 : *tdm_NOOP_SM_flag_loc = tmp_SM_flag;
970 0 : move16();
971 0 : *tdm_hyst_cnt = 0;
972 0 : move16();
973 : }
974 1 : ELSE IF( GE_16( *tdm_hyst_cnt, 20 ) && tmp_SM_flag == 0 &&
975 : ( GT_16( sts[0]->tdm_pc, PC_LIMIT ) || GT_16( sts[1]->tdm_pc, PC_LIMIT ) ) && ( LE_32( *tdm_LT_es_em, ONE_IN_Q20 /* 0.5f in Q21 */ ) || LT_32( es_em_fx, -20971520 /* -10.0f in Q21 */ ) ) )
976 : {
977 0 : tdm_hyst_cnt++;
978 0 : *tdm_NOOP_SM_flag_loc = tmp_SM_flag;
979 0 : move16();
980 0 : *tdm_hyst_cnt = 0;
981 0 : move16();
982 : }
983 : }
984 : ELSE
985 : {
986 3826 : *tdm_hyst_cnt = 0;
987 3826 : move16();
988 : }
989 :
990 3827 : return tmp_SM_flag; /* Q0 */
991 : }
992 :
993 :
994 : /*-------------------------------------------------------------------*
995 : * Function NOOP_decision_fx()
996 : *
997 : * Set Near Out Of Phase decision
998 : *-------------------------------------------------------------------*/
999 :
1000 3827 : static void NOOP_decision_fx(
1001 : CPE_ENC_HANDLE hCPE,
1002 : const Word16 tdm_NOOP_flag_loc, /* Q0 */
1003 : const Word16 tmp_SM_flag, /* Q0 */
1004 : const Word32 rms_L, /* q_rms_L */
1005 : const Word16 q_rms_L,
1006 : const Word32 rms_R, /* q_rms_R */
1007 : const Word16 q_rms_R,
1008 : Word16 *tdm_SM_flag_loc /* Q0 */ )
1009 : {
1010 : Word16 tdm_NOOP_switch_flag;
1011 : STEREO_TD_ENC_DATA_HANDLE hStereoTD;
1012 : Encoder_State **sts;
1013 :
1014 3827 : hStereoTD = hCPE->hStereoTD;
1015 3827 : sts = hCPE->hCoreCoder;
1016 :
1017 3827 : tdm_NOOP_switch_flag = 0;
1018 3827 : move16();
1019 3827 : hStereoTD->tdm_NOOP_cnt = add( hStereoTD->tdm_NOOP_cnt, 1 );
1020 3827 : move16();
1021 3827 : IF( hCPE->hCoreCoder[0]->sp_aud_decision0 == 0 )
1022 : {
1023 3827 : test();
1024 3827 : test();
1025 3827 : test();
1026 3827 : test();
1027 3827 : test();
1028 3827 : test();
1029 3827 : test();
1030 3827 : test();
1031 3827 : IF( ( ( GT_16( hStereoTD->tdm_SM_last2_clas[0], VOICED_TRANSITION ) && ( hStereoTD->tdm_SM_last_clas[0] == UNVOICED_CLAS || EQ_16( hStereoTD->tdm_SM_last_clas[0], VOICED_TRANSITION ) ) ) ||
1032 : ( GT_16( hStereoTD->tdm_SM_last2_clas[1], VOICED_TRANSITION ) && ( hStereoTD->tdm_SM_last_clas[1] == UNVOICED_CLAS || EQ_16( hStereoTD->tdm_SM_last_clas[1], VOICED_TRANSITION ) ) ) ) &&
1033 : ( !( EQ_16( sts[0]->last_coder_type_raw, VOICED ) || EQ_16( sts[1]->last_coder_type_raw, VOICED ) ) && GT_16( hStereoTD->tdm_NOOP_cnt, 5 ) ) )
1034 : {
1035 132 : tdm_NOOP_switch_flag = 1;
1036 132 : move16();
1037 132 : hStereoTD->tdm_NOOP_cnt = 0;
1038 132 : move16();
1039 : }
1040 3695 : ELSE IF( ( hStereoTD->tdm_SM_last_clas[0] == UNVOICED_CLAS || hStereoTD->tdm_SM_last_clas[1] == UNVOICED_CLAS ) &&
1041 : ( !( EQ_16( sts[0]->last_coder_type_raw, VOICED ) || EQ_16( sts[1]->last_coder_type_raw, VOICED ) ) ) && ( LT_32( L_shr( rms_L, q_rms_L ), 400 ) && LT_32( L_shr( rms_R, q_rms_R ), 400 ) ) && GT_16( hStereoTD->tdm_NOOP_cnt, 5 ) )
1042 : {
1043 62 : tdm_NOOP_switch_flag = 1;
1044 62 : move16();
1045 62 : hStereoTD->tdm_NOOP_cnt = 0;
1046 62 : move16();
1047 : }
1048 : }
1049 : ELSE
1050 : {
1051 0 : if ( LT_32( sts[0]->ee_old_fx, 320000 /* 5000.f in Q6 */ ) && LT_32( sts[1]->ee_old_fx, 320000 /* 5000.f in Q6 */ ) )
1052 : {
1053 0 : tdm_NOOP_switch_flag = 1;
1054 0 : move16();
1055 : }
1056 : }
1057 :
1058 3827 : IF( NE_16( *tdm_SM_flag_loc, tdm_NOOP_flag_loc ) )
1059 : {
1060 0 : hStereoTD->tdm_SM_flag = 1;
1061 0 : move16();
1062 0 : IF( hCPE->hCoreCoder[0]->sp_aud_decision0 == 0 )
1063 : {
1064 0 : IF( EQ_16( tdm_NOOP_switch_flag, 1 ) )
1065 : {
1066 0 : *tdm_SM_flag_loc = tdm_NOOP_flag_loc;
1067 0 : move16();
1068 0 : if ( *tdm_SM_flag_loc )
1069 : {
1070 0 : hStereoTD->tdm_SM_reset_flag = 1;
1071 0 : move16();
1072 : }
1073 0 : hStereoTD->tdm_SM_flag = 0;
1074 0 : move16();
1075 : }
1076 : }
1077 : ELSE
1078 : {
1079 0 : IF( EQ_16( tdm_NOOP_switch_flag, 1 ) )
1080 : {
1081 0 : *tdm_SM_flag_loc = tdm_NOOP_flag_loc;
1082 0 : move16();
1083 0 : if ( *tdm_SM_flag_loc )
1084 : {
1085 0 : hStereoTD->tdm_SM_reset_flag = 1;
1086 0 : move16();
1087 : }
1088 0 : hStereoTD->tdm_SM_flag = 0;
1089 0 : move16();
1090 : }
1091 : }
1092 :
1093 0 : IF( EQ_16( tdm_NOOP_flag_loc, 1 ) )
1094 : {
1095 0 : hStereoTD->tdm_hyst_cnt = 2;
1096 0 : move16();
1097 : }
1098 : ELSE
1099 : {
1100 0 : hStereoTD->tdm_hyst_cnt = 20;
1101 0 : move16();
1102 : }
1103 : }
1104 :
1105 3827 : test();
1106 3827 : test();
1107 3827 : IF( GT_16( hStereoTD->tdm_SM_flag, 0 ) && EQ_16( tdm_NOOP_switch_flag, 1 ) && NE_16( *tdm_SM_flag_loc, tmp_SM_flag ) )
1108 : {
1109 0 : *tdm_SM_flag_loc = !( *tdm_SM_flag_loc );
1110 0 : move16();
1111 0 : hStereoTD->tdm_SM_flag = 0;
1112 0 : move16();
1113 0 : if ( *tdm_SM_flag_loc )
1114 : {
1115 0 : hStereoTD->tdm_SM_reset_flag = 1;
1116 0 : move16();
1117 : }
1118 : }
1119 :
1120 3827 : IF( EQ_16( hStereoTD->tdm_SM_modi_flag, 1 ) )
1121 : {
1122 0 : *tdm_SM_flag_loc = 1;
1123 0 : move16();
1124 0 : hStereoTD->tdm_SM_modi_flag = 0;
1125 0 : move16();
1126 0 : hStereoTD->tdm_SM_reset_flag = 1;
1127 0 : move16();
1128 : }
1129 : ELSE
1130 : {
1131 3827 : IF( EQ_16( *tdm_SM_flag_loc, 1 ) && EQ_16( hStereoTD->tdm_SM_reset_flag, 1 ) && LT_32( hStereoTD->tdm_last_ratio_fx, 1073741824 /* 0.5 in Q31 */ ) )
1132 : {
1133 0 : hStereoTD->tdm_SM_reset_flag = 0;
1134 0 : move16();
1135 0 : *tdm_SM_flag_loc = 0;
1136 0 : move16();
1137 0 : hStereoTD->tdm_SM_modi_flag = 1;
1138 0 : move16();
1139 : }
1140 : }
1141 :
1142 3827 : return;
1143 : }
1144 :
1145 :
1146 : /*-------------------------------------------------------------------*
1147 : * Function Comp_diff_lt_corr_fx()
1148 : *
1149 : * Adjust stereo downmixing adaptation rate factor
1150 : * in function of the signal energy.
1151 : *-------------------------------------------------------------------*/
1152 :
1153 3827 : static Word32 Comp_diff_lt_corr_fx(
1154 : CPE_ENC_HANDLE hCPE,
1155 : const Word16 IsSideMono, /* Q0 */
1156 : const Word32 rms_L, /* q_rms_L */
1157 : const Word16 q_rms_L,
1158 : const Word32 rms_R, /* q_rms_R */
1159 : const Word16 q_rms_R,
1160 : const Word32 ener_L_dt, /* Q16 */
1161 : const Word32 ener_R_dt, /* Q16 */
1162 : Word32 corr_LM, /* q_corr_LM */
1163 : Word16 q_corr_LM,
1164 : Word32 corr_RM, /* q_corr_RM */
1165 : Word16 q_corr_RM,
1166 : const Word32 tdm_lt_rms_L, /* Q16 */
1167 : const Word32 tdm_lt_rms_R, /* Q16 */
1168 : Word32 *tdm_lt_corr_LM, /* Q24 */
1169 : Word32 *tdm_lt_corr_RM, /* Q24 */
1170 : Word32 *tdm_last_diff_lt_corr, /* q_tdm_last_diff_lt_corr */
1171 : Word16 *q_tdm_last_diff_lt_corr,
1172 : Word32 *inst_ratio_L_out, /* Q24 */
1173 : Word32 *diff_lt_corr, /* q_d_lt_corr_raw */
1174 : Word16 *q_d_lt_corr_raw )
1175 : {
1176 : Encoder_State **sts;
1177 : Word32 adaprate_fx;
1178 : Word32 adaprate_tmp_fx;
1179 : Word32 madaprate_fx;
1180 : Word32 d_lt_corr_raw_fx;
1181 : Word32 L_tmp, L_tmp1, L_tmp2;
1182 : Word16 q_tmp, q_tmp1;
1183 : Word16 exp_diff;
1184 : Word32 inst_ratio_L_fx;
1185 : Word16 angle;
1186 : Word32 diff_lt_corr_LM_tmp_fx, diff_lt_corr_RM_tmp_fx;
1187 : Word16 q_diff_lt_corr_LM_tmp, q_diff_lt_corr_RM_tmp;
1188 : Word32 diff_lt_corr_tmp_fx;
1189 : Word16 q_diff_lt_corr_tmp;
1190 : Word32 d_lt_corr_fx;
1191 : Word16 q_d_lt_corr;
1192 : Word16 d_lt_corr_shift, shift, q_com;
1193 :
1194 3827 : sts = hCPE->hCoreCoder;
1195 :
1196 : /*----------------------------------------------------------------*
1197 : * Adjust stereo downmixing adaptation rate factor
1198 : * in function of the signal energy. If signal energy is low,
1199 : * adaptation rate factor is lower. This prevent stereo image
1200 : * move on speech offset
1201 : *----------------------------------------------------------------*/
1202 3827 : test();
1203 3827 : test();
1204 3827 : test();
1205 3827 : IF( IsSideMono == 0 && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( GT_32( L_shr( tdm_lt_rms_R, Q1 ), tdm_lt_rms_L ) || GT_32( L_shr( tdm_lt_rms_L, Q1 ), tdm_lt_rms_R ) ) )
1206 : {
1207 1523 : adaprate_fx = L_add( Mpy_32_32( M_ADAP_FX_Q31, L_max( tdm_lt_rms_R, tdm_lt_rms_L ) ), B_ADAP_FX_Q16 ); // Q16
1208 : }
1209 : ELSE
1210 : {
1211 2304 : adaprate_fx = L_add( Mpy_32_32( M_ADAP_FX_Q31, L_min( tdm_lt_rms_R, tdm_lt_rms_L ) ), B_ADAP_FX_Q16 ); // Q16
1212 : }
1213 :
1214 3827 : adaprate_fx = check_bounds_l( adaprate_fx, MIN_ADAP_FAC_FX_Q16, ONE_IN_Q16 ); // Q16
1215 :
1216 : /*----------------------------------------------------------------*
1217 : * In case of unvoiced content (expect when it is part of an onset),
1218 : * the adaptation rate is minimal.
1219 : *----------------------------------------------------------------*/
1220 3827 : test();
1221 3827 : test();
1222 3827 : test();
1223 3827 : test();
1224 3827 : IF( GT_16( sts[0]->ini_frame, 2 ) &&
1225 : ( ( LE_16( sts[0]->last_clas, VOICED_TRANSITION ) && sts[0]->hVAD->hangover_cnt == 0 ) ||
1226 : ( LE_16( sts[1]->last_clas, VOICED_TRANSITION ) && sts[1]->hVAD->hangover_cnt == 0 ) ) )
1227 : {
1228 2007 : adaprate_fx = L_min( adaprate_fx, LIMIT_ADAP_FAC_FX_Q16 ); // Q16
1229 : }
1230 :
1231 3827 : d_lt_corr_raw_fx = 0;
1232 3827 : move32();
1233 :
1234 3827 : IF( IsSideMono == 0 )
1235 : {
1236 3827 : test();
1237 3827 : test();
1238 3827 : test();
1239 3827 : test();
1240 3827 : IF( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) || ( ( LT_32( tdm_lt_rms_R, ONE_IN_Q16 ) || LT_32( tdm_lt_rms_L, ONE_IN_Q16 ) ) && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && LT_32( L_max( tdm_lt_rms_R, tdm_lt_rms_L ), TEN_IN_Q16 ) ) )
1241 : {
1242 80 : adaprate_fx = 64225; /* 0.98f in Q16 */ /* speed up the adaptation of the long term values to the current values after coming from DFT */
1243 80 : move32();
1244 : }
1245 3827 : adaprate_tmp_fx = L_max( adaprate_fx, 52429 /* 0.8f in Q16 */ ); // Q16
1246 3827 : madaprate_fx = L_sub( ONE_IN_Q16, adaprate_tmp_fx ); /* madaprate has temporary value, will updated few lines below */ // Q16
1247 :
1248 3827 : L_tmp = Mpy_32_32( adaprate_tmp_fx, corr_LM ); // (Q16, q_corr_LM) -> q_corr_LM - Q15
1249 3827 : L_tmp1 = Mpy_32_32( madaprate_fx, *tdm_lt_corr_LM ); // (Q16, Q24) -> Q9
1250 3827 : L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, sub( Q31, sub( q_corr_LM, Q15 ) ), L_tmp1, Q31 - Q9, &exp_diff ); // Q31 - exp_diff
1251 3827 : q_tmp = sub( Q31, exp_diff );
1252 :
1253 3827 : L_tmp2 = Mpy_32_32( adaprate_tmp_fx, corr_RM ); // (Q16, q_corr_RM) -> q_corr_RM - Q15
1254 3827 : L_tmp1 = Mpy_32_32( madaprate_fx, *tdm_lt_corr_RM ); // (Q16, Q24) -> Q9
1255 3827 : L_tmp1 = BASOP_Util_Add_Mant32Exp( L_tmp2, sub( Q31, sub( q_corr_RM, Q15 ) ), L_tmp1, Q31 - Q9, &exp_diff ); // Q31 - exp_diff
1256 3827 : q_tmp1 = sub( Q31, exp_diff );
1257 :
1258 3827 : d_lt_corr_raw_fx = BASOP_Util_Add_Mant32Exp( L_tmp, sub( Q31, q_tmp ), L_negate( L_tmp1 ), sub( Q31, q_tmp1 ), &exp_diff ); // Q31 - exp_diff
1259 3827 : *q_d_lt_corr_raw = sub( Q31, exp_diff );
1260 3827 : move16();
1261 3827 : q_com = s_min( *q_d_lt_corr_raw, Q29 );
1262 :
1263 3827 : inst_ratio_L_fx = 0;
1264 3827 : move32();
1265 3827 : inst_ratio_L_fx = L_max( L_shl( d_lt_corr_raw_fx, sub( q_com, *q_d_lt_corr_raw ) ), L_negate( L_shl( RATIO_MAX_FX_Q30, sub( q_com, Q30 ) ) ) ); // q_com
1266 3827 : inst_ratio_L_fx = L_min( inst_ratio_L_fx, L_shl( RATIO_MAX_FX_Q30, sub( q_com, Q30 ) ) ); // q_com
1267 3827 : inst_ratio_L_fx = L_add( Mpy_32_32( 1432371593 /* 0.667f in Q31 */, inst_ratio_L_fx ), L_shl( 1, q_com ) ); // q_com
1268 3827 : angle = extract_l( L_shl( Mpy_32_16_1( inst_ratio_L_fx, EVS_PI_FX ), sub( sub( Q13, sub( q_com, Q2 ) ), Q1 ) ) ); // (q_com, Q13) -> q_com - Q2 -> Q13 >> Q1
1269 3827 : *inst_ratio_L_out = L_shl( L_shr( L_sub( ONE_IN_Q14, L_deposit_l( getCosWord16( angle ) ) ), Q1 ), Q24 - Q14 ); // Q14 << Q10 -> Q24
1270 : }
1271 3827 : madaprate_fx = L_sub( ONE_IN_Q16, adaprate_fx ); // Q16
1272 3827 : corr_RM = BASOP_Util_Add_Mant32Exp( Mpy_32_32( adaprate_fx, corr_RM ), sub( Q31, sub( q_corr_RM, Q15 ) ), Mpy_32_32( madaprate_fx, *tdm_lt_corr_RM ), Q31 - Q9, &exp_diff ); // Q31 - exp_diff
1273 3827 : q_corr_RM = sub( Q31, exp_diff );
1274 3827 : corr_LM = BASOP_Util_Add_Mant32Exp( Mpy_32_32( adaprate_fx, corr_LM ), sub( Q31, sub( q_corr_LM, Q15 ) ), Mpy_32_32( madaprate_fx, *tdm_lt_corr_LM ), Q31 - Q9, &exp_diff ); // Q31 - exp_diff
1275 3827 : q_corr_LM = sub( Q31, exp_diff );
1276 :
1277 3827 : L_tmp = Mpy_32_32( ALP_REF_FX_Q31, *tdm_lt_corr_LM ); // Q24
1278 3827 : L_tmp1 = Mpy_32_32( BET_REF_FX_Q31, corr_LM ); // q_corr_LM
1279 3827 : diff_lt_corr_LM_tmp_fx = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_LM ), &exp_diff ); /* Q31-exp_diff */
1280 3827 : q_diff_lt_corr_LM_tmp = sub( Q31, exp_diff );
1281 3827 : L_tmp = Mpy_32_32( ALP_REF_FX_Q31, *tdm_lt_corr_RM ); // Q24
1282 3827 : L_tmp1 = Mpy_32_32( BET_REF_FX_Q31, corr_RM ); // q_corr_RM
1283 3827 : diff_lt_corr_RM_tmp_fx = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_RM ), &exp_diff ); /* Q31-exp_diff */
1284 3827 : q_diff_lt_corr_RM_tmp = sub( Q31, exp_diff );
1285 3827 : diff_lt_corr_tmp_fx = BASOP_Util_Add_Mant32Exp( diff_lt_corr_LM_tmp_fx, sub( Q31, q_diff_lt_corr_LM_tmp ), L_negate( diff_lt_corr_RM_tmp_fx ), sub( Q31, q_diff_lt_corr_RM_tmp ), &exp_diff ); // (Q31 - exp_diff)
1286 3827 : q_diff_lt_corr_tmp = sub( Q31, exp_diff );
1287 :
1288 3827 : d_lt_corr_fx = BASOP_Util_Add_Mant32Exp( diff_lt_corr_tmp_fx, sub( Q31, q_diff_lt_corr_tmp ), L_negate( *tdm_last_diff_lt_corr ), sub( Q31, *q_tdm_last_diff_lt_corr ), &exp_diff ); // (Q31 - exp_diff)
1289 3827 : q_d_lt_corr = sub( Q31, exp_diff );
1290 3827 : IF( GT_16( q_d_lt_corr, Q31 ) )
1291 : {
1292 3634 : d_lt_corr_shift = sub( Q31, q_d_lt_corr );
1293 3634 : shift = 0;
1294 3634 : move16();
1295 : }
1296 : ELSE
1297 : {
1298 193 : d_lt_corr_shift = 0;
1299 193 : move16();
1300 193 : shift = sub( q_d_lt_corr, Q31 );
1301 : }
1302 3827 : *tdm_last_diff_lt_corr = diff_lt_corr_tmp_fx; /* q_tdm_last_diff_lt_corr */
1303 3827 : move32();
1304 3827 : *q_tdm_last_diff_lt_corr = q_diff_lt_corr_tmp;
1305 3827 : move16();
1306 :
1307 : /*----------------------------------------------------------------*
1308 : * Correct the estimation depending of channels energies evolution
1309 : *----------------------------------------------------------------*/
1310 3827 : test();
1311 3827 : test();
1312 3827 : test();
1313 3827 : test();
1314 3827 : test();
1315 3827 : test();
1316 3827 : test();
1317 3827 : test();
1318 3827 : test();
1319 3827 : test();
1320 3827 : test();
1321 3827 : test();
1322 3827 : IF( EQ_16( IsSideMono, 1 ) &&
1323 : ( ( LT_32( L_shl( rms_L, sub( Q21, q_rms_L ) ), RMS_MIN2_FX_Q21 ) &&
1324 : LT_32( L_shl( rms_R, sub( Q21, q_rms_R ) ), RMS_MIN2_FX_Q21 ) ) &&
1325 : ( LT_32( tdm_lt_rms_L, L_shl( Mpy_32_32( 1717986918 /* 0.8f in Q31 */, rms_L ), sub( Q16, q_rms_L ) ) ) &&
1326 : LT_32( tdm_lt_rms_R, L_shl( Mpy_32_32( 1717986918 /* 0.8f in Q31 */, rms_R ), sub( Q16, q_rms_R ) ) ) ) &&
1327 : ( GT_32( tdm_lt_rms_L, L_shl( tdm_lt_rms_R, Q1 ) ) ||
1328 : LT_32( tdm_lt_rms_L, L_shr( tdm_lt_rms_R, Q1 ) ) ) ) )
1329 : {
1330 0 : L_tmp = Mpy_32_32( ALP2_FX_Q31, *tdm_lt_corr_LM ); // Q24
1331 0 : L_tmp1 = Mpy_32_32( BET2_FX_Q31, corr_LM ); // q_corr_LM
1332 0 : L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_LM ), &exp_diff ); // (Q31 - exp_diff)
1333 0 : *tdm_lt_corr_LM = L_shl( L_tmp, sub( Q24, sub( Q31, exp_diff ) ) ); // Q24
1334 0 : move32();
1335 0 : L_tmp = Mpy_32_32( ALP2_FX_Q31, *tdm_lt_corr_RM ); // Q24
1336 0 : L_tmp1 = Mpy_32_32( BET2_FX_Q31, corr_RM ); // q_corr_RM
1337 0 : L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_RM ), &exp_diff ); // (Q31 - exp_diff)
1338 0 : *tdm_lt_corr_RM = L_shl( L_tmp, sub( Q24, sub( Q31, exp_diff ) ) ); // Q24
1339 0 : move32();
1340 :
1341 0 : *tdm_lt_corr_LM = L_shl( Mpy_32_32( *tdm_lt_corr_LM, 1342177280 /* 2.5f in Q29 */ ), Q24 - Q22 ); // ((Q24, Q29) -> Q22 << 2) -> Q24
1342 0 : move32();
1343 0 : *tdm_lt_corr_RM = L_shl( Mpy_32_32( *tdm_lt_corr_RM, 1342177280 /* 2.5f in Q29 */ ), Q24 - Q22 ); // ((Q24, Q29) -> Q22 << 2) -> Q24
1344 0 : move32();
1345 : }
1346 3827 : ELSE IF( ( !( ( GT_32( ener_R_dt, DT_ENER_THR_FX_Q16 ) && LT_32( ener_L_dt, DT_ENER_THR_FX_Q16 ) ) ||
1347 : ( LT_32( ener_R_dt, DT_ENER_THR_FX_Q16 ) && GT_32( ener_L_dt, DT_ENER_THR_FX_Q16 ) ) ) /* Energy are going in the same direction */
1348 : && ( LT_32( L_abs( L_shl( d_lt_corr_fx, d_lt_corr_shift ) ), L_shl( 665719931 /* 0.31f in Q31 */, shift ) ) /* small difference regarding the difference gain evolution */
1349 : || GT_32( tdm_lt_rms_L, L_shl( RMS_MIN2_FX_Q21, Q16 - Q21 + Q1 ) ) || GT_32( tdm_lt_rms_R, L_shl( RMS_MIN2_FX_Q21, Q16 - Q21 + Q1 ) ) ) ) /* Energy of at least one of the channel is not low */
1350 : )
1351 : {
1352 : /* Use estimated results */
1353 2976 : *tdm_lt_corr_LM = L_shl( diff_lt_corr_LM_tmp_fx, sub( Q24, q_diff_lt_corr_LM_tmp ) ); /* Q24 */
1354 2976 : move32();
1355 2976 : *tdm_lt_corr_RM = L_shl( diff_lt_corr_RM_tmp_fx, sub( Q24, q_diff_lt_corr_RM_tmp ) ); /* Q24 */
1356 2976 : move32();
1357 : }
1358 : ELSE
1359 : {
1360 851 : L_tmp = Mpy_32_32( ALP1_FX_Q31, *tdm_lt_corr_LM ); // Q24
1361 851 : L_tmp1 = Mpy_32_32( BET1_FX_Q31, corr_LM ); // q_corr_LM
1362 851 : L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_LM ), &exp_diff ); // (Q31 - exp_diff)
1363 851 : *tdm_lt_corr_LM = L_shl( L_tmp, sub( Q24, sub( Q31, exp_diff ) ) ); // Q24
1364 851 : move32();
1365 851 : L_tmp = Mpy_32_32( ALP1_FX_Q31, *tdm_lt_corr_RM ); // Q24
1366 851 : L_tmp1 = Mpy_32_32( BET1_FX_Q31, corr_RM ); // q_corr_RM
1367 851 : L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_RM ), &exp_diff ); // (Q31 - exp_diff)
1368 851 : *tdm_lt_corr_RM = L_shl( L_tmp, sub( Q24, sub( Q31, exp_diff ) ) ); // Q24
1369 851 : move32();
1370 : }
1371 :
1372 3827 : *diff_lt_corr = L_sub( *tdm_lt_corr_LM, *tdm_lt_corr_RM ); /* update the difference */ // Q24
1373 3827 : move32();
1374 :
1375 3827 : return d_lt_corr_raw_fx;
1376 : }
1377 :
1378 :
1379 : /*-------------------------------------------------------------------*
1380 : * Function limit_idx_Dnwmix_fx()
1381 : *
1382 : *
1383 : *-------------------------------------------------------------------*/
1384 :
1385 129 : static Word16 limit_idx_Dwnmix_fx(
1386 : const Word16 idx_in, /* Q0 */
1387 : const Word16 unclr_decision, /* Q0 */
1388 : const Word16 inst_idx, /* Q0 */
1389 : const Word16 previous_idx, /* Q0 */
1390 : const Word16 tdm_last_LRTD_PriCh_cnt, /* Q0 */
1391 : const Word16 tdm_last_LRTD_frame_cnt /* Q0 */ )
1392 : {
1393 : Word16 idx;
1394 :
1395 129 : idx = idx_in;
1396 129 : move16();
1397 129 : idx = check_bounds_s_fx( idx, 1, 29 ); /* Q0 */
1398 :
1399 129 : test();
1400 129 : IF( EQ_16( unclr_decision, 1 ) && GT_16( tdm_last_LRTD_frame_cnt, 1 ) )
1401 : {
1402 60 : IF( tdm_last_LRTD_PriCh_cnt > 0 )
1403 : {
1404 59 : test();
1405 59 : test();
1406 59 : IF( LE_16( idx, LRTD_STEREO_MID_IS_PRIM ) && LT_16( inst_idx, LRTD_STEREO_MID_IS_PRIM + 2 ) )
1407 : {
1408 17 : idx = s_min( 1, idx );
1409 : }
1410 42 : ELSE IF( GE_16( idx, LRTD_STEREO_MID_IS_PRIM ) && GT_16( inst_idx, LRTD_STEREO_MID_IS_PRIM - 2 ) )
1411 : {
1412 37 : idx = s_max( 29, idx );
1413 : }
1414 5 : ELSE IF( LT_16( inst_idx, LRTD_STEREO_MID_IS_PRIM - 4 ) )
1415 : {
1416 1 : idx = s_min( 1, idx );
1417 : }
1418 4 : ELSE IF( GT_16( inst_idx, LRTD_STEREO_MID_IS_PRIM + 4 ) )
1419 : {
1420 1 : idx = s_max( 29, idx );
1421 : }
1422 : ELSE
1423 : {
1424 3 : idx = previous_idx;
1425 3 : move16();
1426 : }
1427 : }
1428 : ELSE
1429 : {
1430 1 : idx = previous_idx;
1431 1 : move16();
1432 : }
1433 : }
1434 :
1435 129 : return idx; /* Q0 */
1436 : }
1437 :
1438 :
1439 : /*-------------------------------------------------------------------*
1440 : * Function limit_idx_NoDwnmix_fx()
1441 : *
1442 : *-------------------------------------------------------------------*/
1443 :
1444 3598 : static Word16 limit_idx_NoDwnmix_fx(
1445 : const Word16 idx_in, /* i : Index Q0*/
1446 : const Word16 side_can_change, /* i : Primary and secondary channel allowed to change ? Q0*/
1447 : const Word32 d_lt_corr_raw, /* i : Raw corrrelation differences q_d_lt_corr_raw*/
1448 : const Word16 q_d_lt_corr_raw /* i : Q-factor of Raw corrrelation differences */
1449 : )
1450 : {
1451 : Word16 idx;
1452 :
1453 3598 : idx = idx_in;
1454 3598 : move16();
1455 :
1456 3598 : test();
1457 3598 : test();
1458 3598 : IF( side_can_change == 0 && GT_16( idx_in, 10 ) && LT_16( idx_in, 20 ) )
1459 : {
1460 0 : idx = 30;
1461 0 : move16();
1462 0 : IF( LT_32( d_lt_corr_raw, L_negate( L_shl( 214748365 /* 0.1f in Q31 */, sub( q_d_lt_corr_raw, Q31 ) ) ) ) )
1463 : {
1464 0 : idx = 0;
1465 0 : move16();
1466 : }
1467 : }
1468 : ELSE
1469 : {
1470 3598 : IF( LE_16( idx, 15 ) )
1471 : {
1472 268 : idx = 0;
1473 268 : move16();
1474 : }
1475 : ELSE
1476 : {
1477 3330 : idx = 30;
1478 3330 : move16();
1479 : }
1480 : }
1481 :
1482 3598 : return idx; /* Q0 */
1483 : }
1484 :
1485 :
1486 : /*-------------------------------------------------------------------*
1487 : * Function stereo_tdm_ener_analysis_SM_fx()
1488 : *
1489 : *
1490 : *-------------------------------------------------------------------*/
1491 :
1492 0 : static Word16 stereo_tdm_ener_analysis_SM_fx(
1493 : CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */
1494 : Encoder_State **sts, /* i/o: Encoder static variables structure */
1495 : const Word16 input_frame, /* i : Number of samples Q0*/
1496 : Word16 *tdm_SM_flag /* i/o: channel combination scheme flag Q0*/
1497 : )
1498 : {
1499 : Word32 rms_R_fx, rms_L_fx;
1500 : Word16 q_rms_R, q_rms_L;
1501 : Word32 corr_RM_fx, corr_LM_fx;
1502 : Word16 q_corr_LM, q_corr_RM;
1503 : Word32 diff_lt_corr_fx;
1504 : Word32 ratio_L_fx;
1505 : Word32 dist_fx;
1506 : Word16 i, side_can_change;
1507 : Word16 idx, tdm_SM_flag_loc;
1508 : Word32 es_em_fx;
1509 : Word32 ener_R_dt_fx, ener_L_dt_fx;
1510 : Word16 desired_idx;
1511 : STEREO_TD_ENC_DATA_HANDLE hStereoTD;
1512 : Word16 angle;
1513 :
1514 0 : hStereoTD = hCPE->hStereoTD;
1515 0 : desired_idx = 0;
1516 0 : move16();
1517 0 : es_em_fx = 20972; /* 0.01f in Q21 */
1518 0 : move32();
1519 :
1520 : /*----------------------------------------------------------------*
1521 : * set SM flag
1522 : *----------------------------------------------------------------*/
1523 :
1524 : /* Simple logic to set SM flag, should be done in the frequency domain for low SM correlation signal, especially for music item such as Music_1_org_s */
1525 0 : tdm_SM_flag_loc = hStereoTD->tdm_last_SM_flag_noop; /* Q0 */
1526 0 : move16();
1527 :
1528 : /*----------------------------------------------------------------*
1529 : * Compute L and R energy and Long term RMS of each channel
1530 : *----------------------------------------------------------------*/
1531 :
1532 0 : Get_LR_rms_fx( sts[0]->input_fx, sts[1]->input_fx, input_frame, &rms_L_fx, &q_rms_L, &rms_R_fx, &q_rms_R );
1533 :
1534 : /*----------------------------------------------------------------*
1535 : * Compute the 1st order energy difference difference
1536 : * Compute the gain of L&R channel compared to mono
1537 : * - estimate the long term evolution of the L to Mono gain
1538 : * - estimate the long term evolution of the R to Mono gain
1539 : * - estimate the long term difference between the long term
1540 : * - evolution of the L and R to Mono gain
1541 : *----------------------------------------------------------------*/
1542 :
1543 0 : Get_dt_lt_ener_fx( hCPE, 1, input_frame, hStereoTD->tdm_last_SM_flag_noop, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R,
1544 : &hStereoTD->tdm_lt_rms_L_SM_fx, &hStereoTD->tdm_lt_rms_R_SM_fx, &hStereoTD->tdm_last_ener_lt_L_SM_fx, &hStereoTD->tdm_last_ener_lt_R_SM_fx, &hStereoTD->tdm_LT_es_em_SM_fx, &hStereoTD->tdm_hyst_cnt_SM, &tdm_SM_flag_loc,
1545 : &ener_R_dt_fx, &ener_L_dt_fx, &corr_LM_fx, &q_corr_LM, &corr_RM_fx, &q_corr_RM );
1546 :
1547 0 : hStereoTD->tdm_SM_reset_flag = 0;
1548 0 : move16();
1549 :
1550 : /*----------------------------------------------------------------*
1551 : * Adjust stereo downmixing adaptation rate factor
1552 : * in function of the signal energy. If signal energy is low,
1553 : * adaptation rate factor is lower. This prevent stereo image
1554 : * move on speech offset
1555 : *----------------------------------------------------------------*/
1556 :
1557 0 : Comp_diff_lt_corr_fx( hCPE, 1, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R, ener_L_dt_fx, ener_R_dt_fx, corr_LM_fx, q_corr_LM, corr_RM_fx, q_corr_RM, hStereoTD->tdm_lt_rms_L_SM_fx, hStereoTD->tdm_lt_rms_R_SM_fx, &hStereoTD->tdm_lt_corr_LM_SM_fx,
1558 : &hStereoTD->tdm_lt_corr_RM_SM_fx, &hStereoTD->tdm_last_diff_lt_corr_SM_fx, &hStereoTD->q_tdm_last_diff_lt_corr_SM, NULL, &diff_lt_corr_fx, NULL );
1559 :
1560 0 : side_can_change = 0;
1561 0 : move16();
1562 :
1563 : /*----------------------------------------------------------------*
1564 : * When the energies of channels are low enough, compute the ratio
1565 : * of L and R needed to create new mono/side signals
1566 : *----------------------------------------------------------------*/
1567 0 : test();
1568 0 : test();
1569 0 : test();
1570 0 : IF( ( LE_32( L_shl( hStereoTD->tdm_lt_rms_L_SM_fx, Q20 - Q24 ), RMS_MIN_FX_Q20 ) && LE_32( L_shl( hStereoTD->tdm_lt_rms_R_SM_fx, Q19 /* adjusted for 2 in RHS */ - Q24 ), RMS_MIN_FX_Q20 ) ) ||
1571 : ( LE_32( L_shl( hStereoTD->tdm_lt_rms_R_SM_fx, Q20 - Q24 ), RMS_MIN_FX_Q20 ) && LE_32( L_shl( hStereoTD->tdm_lt_rms_L_SM_fx, Q19 /* adjusted for 2 in RHS */ - Q24 ), RMS_MIN_FX_Q20 ) ) ) /* Q20 */
1572 : {
1573 0 : test();
1574 0 : test();
1575 0 : test();
1576 0 : IF( ( LT_16( sts[0]->old_corr_fx, CORR_THRES_FX_Q15 ) && LT_16( sts[1]->old_corr_fx, CORR_THRES_FX_Q15 ) ) ||
1577 : ( LE_32( L_shl( hStereoTD->tdm_lt_rms_L_SM_fx, Q21 - Q24 ), RMS_MIN2_FX_Q21 ) && LE_32( L_shl( hStereoTD->tdm_lt_rms_R_SM_fx, Q21 - Q24 ), RMS_MIN2_FX_Q21 ) ) )
1578 : {
1579 0 : side_can_change = 1;
1580 0 : move16();
1581 : }
1582 : }
1583 :
1584 0 : test();
1585 0 : test();
1586 0 : test();
1587 0 : IF( ( LE_32( L_shl( hStereoTD->tdm_lt_rms_L_SM_fx, Q21 - Q24 ), RMS_MIN2_FX_Q21 ) && LE_32( L_shl( hStereoTD->tdm_lt_rms_R_SM_fx, Q20 /* adjusted for 2 in RHS */ - Q24 ), RMS_MIN2_FX_Q21 ) ) ||
1588 : ( LE_32( L_shl( hStereoTD->tdm_lt_rms_R_SM_fx, Q21 - Q24 ), RMS_MIN2_FX_Q21 ) && LE_32( L_shl( hStereoTD->tdm_lt_rms_L_SM_fx, Q20 /* adjusted for 2 in RHS */ - Q24 ), RMS_MIN2_FX_Q21 ) ) ) /* Q21 */
1589 : {
1590 0 : test();
1591 0 : test();
1592 0 : test();
1593 0 : IF( ( ( NE_16( hStereoTD->tdm_last_SM_flag_noop, tdm_SM_flag_loc ) ) && hStereoTD->tdm_noop_cnt == 0 ) ||
1594 : EQ_16( hStereoTD->tdm_noop_mov_flag, 1 ) || NE_16( hStereoTD->tdm_prev_desired_idx_SM, hStereoTD->tdm_prev_stable_idx_SM ) )
1595 : {
1596 0 : hStereoTD->tdm_noop_mov_flag = 1;
1597 0 : move16();
1598 0 : IF( hStereoTD->tdm_last_ratio_idx_SM != 0 && NE_16( hStereoTD->tdm_last_ratio_idx_SM, ( TDM_NQ - 1 ) ) )
1599 : {
1600 0 : side_can_change = 1;
1601 0 : move16();
1602 : }
1603 : }
1604 : }
1605 :
1606 0 : test();
1607 0 : IF( side_can_change == 0 && EQ_16( tdm_SM_flag_loc, 1 ) && GT_32( es_em_fx, 31457280 /* 15.0f in Q21 */ ) )
1608 : {
1609 0 : side_can_change = 1;
1610 0 : move16();
1611 : }
1612 :
1613 0 : IF( side_can_change )
1614 : {
1615 0 : ratio_L_fx = L_max( diff_lt_corr_fx, -RATIO_MAX_FX_Q24 ); // Q24
1616 0 : ratio_L_fx = L_min( ratio_L_fx, RATIO_MAX_FX_Q24 ); // Q24
1617 :
1618 0 : IF( GT_32( ratio_L_fx, RATIO_MAX_FX_Q23 ) )
1619 : {
1620 0 : ratio_L_fx = L_add( Mpy_32_32( 1159641170 /* 1.08f in Q30 */, ratio_L_fx ), 3187671 /* 0.38f in Q23 */ ); // (Q30, Q24) -> Q23
1621 : }
1622 0 : ELSE IF( LT_32( ratio_L_fx, -RATIO_MAX_FX_Q23 ) )
1623 : {
1624 0 : ratio_L_fx = L_add( Mpy_32_32( 687194767 /* 0.64f in Q30 */, ratio_L_fx ), 10737418 /* 1.28f in Q23 */ ); // (Q30, Q24) -> Q23
1625 : }
1626 : ELSE
1627 : {
1628 0 : ratio_L_fx = L_add( Mpy_32_32( 279172874 /* 0.26f in Q30 */, ratio_L_fx ), 8346665 /* 0.995f in Q23 */ ); // (Q30, Q24) -> Q23
1629 : }
1630 :
1631 0 : angle = extract_l( L_shl( Mpy_32_16_1( ratio_L_fx, EVS_PI_FX ), Q13 - Q21 - Q1 ) ); // (Q23, Q13) -> Q21 >> Q1 -> Q22 -> Q13
1632 0 : ratio_L_fx = L_shl( L_shr( L_sub( ONE_IN_Q14, L_deposit_l( getCosWord16( angle ) ) ), Q1 ), Q24 - Q14 ); // Q14 << Q10 -> Q24
1633 :
1634 0 : dist_fx = L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx_Q24[0] ) ); // Q24
1635 :
1636 0 : desired_idx = 0;
1637 0 : move16();
1638 0 : FOR( i = 1; i < TDM_NQ; i++ )
1639 : {
1640 0 : IF( LE_32( L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx_Q24[i] ) ), dist_fx ) )
1641 : {
1642 0 : dist_fx = L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx_Q24[i] ) ); // Q24
1643 0 : desired_idx = i;
1644 0 : move16();
1645 : }
1646 : }
1647 :
1648 0 : idx = stereo_smooth_LR_transition_fx( &hStereoTD->tdm_prev_stable_idx_SM, &hStereoTD->tdm_noop_mov_flag, hStereoTD->tdm_last_ratio_idx_SM, &hStereoTD->tdm_prev_desired_idx_SM, &hStereoTD->tdm_noop_cnt, tdm_SM_flag_loc, desired_idx ); /* Q0 */
1649 :
1650 0 : idx = extract_l( L_add( Mpy_32_32( 1717986918 /* 0.8f in Q31 */, idx ), Mpy_32_32( 429496729 /* 0.2f in Q31 */, hStereoTD->tdm_last_ratio_idx_SM ) ) ); // (Q31, Q0) -> Q0
1651 :
1652 0 : ratio_L_fx = tdm_ratio_tabl_fx_Q24[idx];
1653 0 : move32();
1654 : }
1655 : ELSE
1656 : {
1657 0 : ratio_L_fx = L_shl( hStereoTD->tdm_last_ratio_SM_fx, Q24 - Q31 ); // Q31 -> Q24
1658 0 : idx = hStereoTD->tdm_last_ratio_idx_SM;
1659 0 : move16();
1660 : }
1661 :
1662 0 : test();
1663 0 : test();
1664 0 : test();
1665 0 : IF( ( EQ_16( hStereoTD->tdm_noop_mov_flag, 1 ) && GE_16( hStereoTD->tdm_noop_cnt, 31 ) ) || ( ( EQ_16( hStereoTD->tdm_last_SM_flag_noop, tdm_SM_flag_loc ) ) && ( EQ_16( idx, hStereoTD->tdm_prev_stable_idx_SM ) ) ) )
1666 : {
1667 0 : hStereoTD->tdm_noop_cnt = 0;
1668 0 : move16();
1669 0 : hStereoTD->tdm_noop_mov_flag = 0;
1670 0 : move16();
1671 : }
1672 :
1673 0 : test();
1674 0 : if ( hStereoTD->tdm_noop_mov_flag == 0 || tdm_SM_flag_loc == 0 )
1675 : {
1676 0 : hStereoTD->tdm_prev_stable_idx_SM = idx;
1677 0 : move16();
1678 : }
1679 :
1680 0 : hStereoTD->tdm_last_SM_flag_noop = tdm_SM_flag_loc;
1681 0 : move16();
1682 0 : *tdm_SM_flag = tdm_SM_flag_loc;
1683 0 : move16();
1684 :
1685 0 : return ( idx );
1686 : }
1687 :
1688 :
1689 : /*-------------------------------------------------------------------*
1690 : * tdm_lp_comparison()
1691 : *
1692 : * Perform the comparison of the 2 sets of LP coefficients
1693 : *-------------------------------------------------------------------*/
1694 : /*! r: replication decision; 1 = Use old LP */
1695 3827 : Word16 tdm_lp_comparison_fx(
1696 : STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i/o: TD stereo encoder handle */
1697 : STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */
1698 : Encoder_State *st, /* i/o: Encoder structure */
1699 : Word32 *speech_buff, /* i : Current speech frame Q_speech */
1700 : const Word16 *A_PCh_fx, /* i : primary channel LP coefficients Q12*/
1701 : const Word16 *A_SCh_fx, /* i : secondary channel LP coeff. Q12*/
1702 : const Word16 m, /* i : filter length Q0*/
1703 : const Word16 *isp_PCh_fx, /* i : primary channel LSPs Q15 */
1704 : const Word16 *isp_SCh_fx, /* i : secondary channel LSPs Q15 */
1705 : const Word16 L_frame, /* i : frame length Q0*/
1706 : const Word32 element_brate_wo_meta, /* i : element bitrate without metadata Q0*/
1707 : Word16 Q_speech )
1708 : {
1709 : Word32 ener_sig_fx, pred_gain_reuse_PCh_fx, log10_fx, predgain_SCh_fx;
1710 : Word16 LP_mode;
1711 : Word32 dist_fx, ftmp_fx;
1712 : Word16 i;
1713 : Word32 res_fx[L_FRAME16k];
1714 :
1715 : Word16 Q_A_SCh;
1716 3827 : Word32 *speech_fx = &speech_buff[M];
1717 3827 : Q_A_SCh = sub( 14, norm_s( A_SCh_fx[0] ) );
1718 3827 : residu_ivas_fx( A_SCh_fx, Q_A_SCh, m, speech_fx, res_fx, L_frame );
1719 :
1720 : /* Find prediction gain for current LP filter */
1721 : // residu( A_SCh, m, speech, res, L_frame );
1722 :
1723 3827 : Word16 gb = find_guarded_bits_fx( L_frame );
1724 3827 : scale_sig32( speech_buff, L_FRAME + M, Q4 ); /* Q_speech + 4 */
1725 3827 : Word16 exp = sub( Q27, Q_speech );
1726 3827 : Word32 sum2_value = sum2_32_exp_fx( speech_fx, L_frame, &exp, gb ); // 2*Q_speech -31-gb
1727 3827 : IF( LT_16( exp, -5 ) ) /*maximum q to prevent 0.01 from saturating is 37, since we are adding it headroom of 1 is required*/
1728 : {
1729 0 : sum2_value = L_shl( sum2_value, add( 5, exp ) ); // sum2_value>>(-5-exp)=>sum2_value<<(5+exp)
1730 0 : exp = -5;
1731 0 : move16();
1732 : }
1733 3827 : sum2_value = BASOP_Util_Add_Mant32Exp( sum2_value, exp, 328, Q16, &exp ); /* Q31-exp */
1734 3827 : Word32 temp32_log = L_add( BASOP_Util_Log2( sum2_value ), L_shl( sub( Q31, sub( 31, exp ) ), Q25 ) ); /* Q25 */
1735 3827 : ener_sig_fx = Mpy_32_32( temp32_log, 646456623 ); // Q25
1736 : // ener_sig = log10f( sum2_f( speech, L_frame ) + 0.01f );
1737 3827 : exp = sub( Q31, Q_speech );
1738 3827 : sum2_value = sum2_32_exp_fx( res_fx, L_frame, &exp, gb ); // 2*Q_speech -31-gb
1739 3827 : sum2_value = BASOP_Util_Add_Mant32Exp( sum2_value, exp, 328, Q16, &exp ); /* Q31-exp */
1740 3827 : temp32_log = L_add( BASOP_Util_Log2( sum2_value ), L_shl( sub( Q31, sub( 31, exp ) ), Q25 ) ); /* Q25 */
1741 3827 : log10_fx = Mpy_32_32( temp32_log, 646456623 ); // Q25
1742 3827 : predgain_SCh_fx = Mpy_32_32( L_sub( ener_sig_fx, log10_fx ), 1342177280 ); // Q27+Q25-31 = Q21
1743 : // pred_gain_reuse_PCh = 10.0f * ( ener_sig - log10f( sum2_f( res, L_frame ) + 0.01f ) );
1744 : // predgain_SCh = 10.0f * ( ener_sig - log10f( sum2_f( res, L_frame ) + 0.01f ) );
1745 :
1746 : /* Find prediction gain when resuing the Primary Channel LP filter */
1747 : // residu( A_PCh, m, speech, res, L_frame );
1748 3827 : scale_sig32( speech_buff, L_FRAME + M, -4 ); /* Q_speech */
1749 3827 : residu_ivas_fx( A_PCh_fx, sub( 14, norm_s( A_PCh_fx[0] ) ), m, speech_fx, res_fx, L_frame );
1750 3827 : exp = sub( Q31, Q_speech );
1751 3827 : sum2_value = sum2_32_exp_fx( res_fx, L_frame, &exp, gb ); // 2*Q_speech -31-gb
1752 3827 : sum2_value = BASOP_Util_Add_Mant32Exp( sum2_value, exp, 328, Q16, &exp );
1753 3827 : temp32_log = L_add( BASOP_Util_Log2( sum2_value ), L_shl( sub( Q31, sub( 31, exp ) ), Q25 ) ); /* Q25 */
1754 3827 : log10_fx = Mpy_32_32( temp32_log, 646456623 ); // Q25
1755 :
1756 3827 : pred_gain_reuse_PCh_fx = Mpy_32_32( L_sub( ener_sig_fx, log10_fx ), 1342177280 ); // Q27+Q25-31 = Q21
1757 : // pred_gain_reuse_PCh = 10.0f * ( ener_sig - log10f( sum2_f( res, L_frame ) + 0.01f ) );
1758 :
1759 : /* Find Euclidian distance between the 2 filters */
1760 3827 : dist_fx = 0;
1761 3827 : move16();
1762 3827 : gb = 4;
1763 3827 : move16();
1764 65059 : FOR( i = 0; i < m; i++ )
1765 : {
1766 : // ftmp = isp_SCh[i] - isp_PCh[i];
1767 61232 : ftmp_fx = L_deposit_h( sub( isp_SCh_fx[i], isp_PCh_fx[i] ) ); /* Q31 */
1768 : // dist += ftmp * ftmp;
1769 61232 : dist_fx = L_add( dist_fx, L_shr( Mpy_32_32( ftmp_fx, ftmp_fx ), gb ) ); // Q31-gb
1770 : }
1771 : // ener_sig *= 10.0f;
1772 3827 : ener_sig_fx = Mpy_32_32( ener_sig_fx, 1342177280 ); // Q27+Q25-31 = Q21
1773 :
1774 : /* Verification of the filters similartiies and prediction gain obtained for each channel */
1775 : /* Threshold are more relax if alpha is close to 0.5 (Valid if ICA is used ) */
1776 3827 : test();
1777 3827 : test();
1778 3827 : test();
1779 3827 : test();
1780 3827 : test();
1781 3827 : test();
1782 3827 : test();
1783 3827 : test();
1784 3827 : test();
1785 3827 : IF( ( ( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST_FX, gb ) ) ) /* Prediction gain are close & Euclidian dist is small */
1786 : || ( LT_32( predgain_SCh_fx, PG2ND_FX ) && LT_32( dist_fx, L_shr( EUCLDST2_FX, gb ) ) ) ) /* Prediction gain if the secondary channel is low & Euclidian dist is not too large */
1787 : || ( GE_16( hStereoTD->tdm_last_ratio_idx, ( LRTD_STEREO_MID_IS_PRIM - 2 ) ) && LE_16( hStereoTD->tdm_last_ratio_idx, ( LRTD_STEREO_MID_IS_PRIM + 2 ) ) && /* ratio between 0.4 and 0.6 */
1788 : ( ( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG2_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST2_FX, gb ) ) ) || LT_32( predgain_SCh_fx, PG2ND2_FX ) ) ) /* Prediction gain are not far & Euclidian dist is not too large or Prediction gain if the secondary channel is low */
1789 : || LE_32( ener_sig_fx, 62914560 ) // 30.0f in Q21
1790 : /* secondary channel has low energy */
1791 : )
1792 : {
1793 1119 : LP_mode = 1;
1794 1119 : move16();
1795 1119 : test();
1796 1119 : test();
1797 1119 : test();
1798 1119 : test();
1799 1119 : test();
1800 1119 : test();
1801 1119 : test();
1802 1119 : test();
1803 1119 : test();
1804 1119 : test();
1805 :
1806 1119 : IF( ( GE_32( element_brate_wo_meta, IVAS_48k ) && !( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG_HR_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST_FX, gb ) ) ) ) ||
1807 : ( EQ_16( hStereoClassif->lrtd_mode, 1 ) && LT_32( element_brate_wo_meta, IVAS_16k4 ) && !( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG_HR_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST_FX, add( gb, 1 ) ) ) ) ) ||
1808 : ( EQ_16( hStereoClassif->lrtd_mode, 1 ) && GE_32( element_brate_wo_meta, IVAS_16k4 ) && !( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG_LRTD_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST_FX, gb + 2 ) ) ) ) || st->tc_cnt > 0 )
1809 : {
1810 988 : LP_mode = 0;
1811 988 : move16();
1812 : }
1813 : }
1814 : ELSE
1815 : {
1816 : /* Prediction or and filters are too different -> quantize the difference*/
1817 2708 : LP_mode = 0;
1818 2708 : move16();
1819 : }
1820 :
1821 3827 : return LP_mode;
1822 : }
1823 : /*-------------------------------------------------------------------*
1824 : * tdm_ol_pitch_comparison()
1825 : *
1826 : * Perform the comparison of the 2 sets of OL pitch
1827 : *-------------------------------------------------------------------*/
1828 :
1829 : /*! r: replication decision; 1 = Use old LP */
1830 3827 : void tdm_ol_pitch_comparison_fx(
1831 : CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */
1832 : Word16 pitch_fr[CPE_CHANNELS][NB_SUBFR], /* i/o: fractional pitch values, Q6 */
1833 : Word16 voicing_fr[CPE_CHANNELS][NB_SUBFR] /* i/o: fractional pitch gains, Q15 */
1834 : )
1835 : {
1836 : Word16 tmp_diff;
1837 3827 : Word16 diff_thr = 6;
1838 : Encoder_State *st0, *st1;
1839 3827 : move16();
1840 :
1841 3827 : st0 = hCPE->hCoreCoder[0]; /* Encoder structure - primary channel */
1842 3827 : st1 = hCPE->hCoreCoder[1]; /* Encoder structure - secondary channel */
1843 :
1844 3827 : IF( GT_32( hCPE->element_brate, IVAS_13k2 ) )
1845 : {
1846 3827 : diff_thr = 3;
1847 3827 : move16();
1848 : }
1849 :
1850 3827 : test();
1851 3827 : IF( GE_32( hCPE->element_brate, IVAS_48k ) || EQ_16( hCPE->hStereoTD->tdm_LRTD_flag, 1 ) )
1852 : {
1853 3698 : diff_thr = 1;
1854 3698 : move16();
1855 : }
1856 :
1857 3827 : hCPE->hStereoTD->tdm_Pitch_reuse_flag = 0;
1858 3827 : move16();
1859 :
1860 3827 : test();
1861 3827 : test();
1862 3827 : test();
1863 3827 : test();
1864 3827 : test();
1865 3827 : test();
1866 3827 : IF( ( ( st0->sp_aud_decision1 == 0 && st0->sp_aud_decision2 == 0 ) && /* Pitch is not recycled in case of music coding*/
1867 : ( LE_32( hCPE->element_brate, IVAS_16k4 ) || ( LE_32( hCPE->element_brate, IVAS_24k4 ) && EQ_16( st0->coder_type, VOICED ) && EQ_16( st1->coder_type, VOICED ) ) ) ) ||
1868 : LT_32( hCPE->element_brate, IVAS_13k2 ) )
1869 : {
1870 719 : IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) )
1871 : {
1872 : Word16 voicmin[4];
1873 :
1874 719 : minimum_fx( st0->voicing_fx, 3, voicmin );
1875 719 : minimum_fx( st1->voicing_fx, 3, voicmin + 1 );
1876 719 : minimum_fx( voicing_fr[0], 4, voicmin + 2 );
1877 719 : minimum_fx( voicing_fr[1], 4, voicmin + 3 );
1878 :
1879 719 : tmp_diff = 10;
1880 719 : move16();
1881 :
1882 719 : test();
1883 719 : test();
1884 719 : test();
1885 719 : IF( GE_16( voicmin[0], 29491 /* 0.9f in Q15 */ ) && GE_16( voicmin[1], 29491 /* 0.9f in Q15 */ ) && GE_16( voicmin[2], 27853 /* 0.85f in Q15 */ ) && GE_16( voicmin[3], 27853 /* 0.85f in Q15 */ ) )
1886 : {
1887 44 : tmp_diff = add( abs_s( sub( st0->pitch[0], st1->pitch[0] ) ), add( abs_s( sub( st0->pitch[1], st1->pitch[1] ) ), abs_s( sub( st0->pitch[2], st1->pitch[2] ) ) ) ); /* Q0 */
1888 : }
1889 : }
1890 : ELSE
1891 : {
1892 0 : tmp_diff = abs_s( sub( add( st0->pitch[0], add( st0->pitch[1], st0->pitch[2] ) ), add( st1->pitch[0], add( st1->pitch[1], st1->pitch[2] ) ) ) ); /* Q0 */
1893 : }
1894 :
1895 719 : IF( LE_16( tmp_diff, diff_thr ) )
1896 : {
1897 35 : hCPE->hStereoTD->tdm_Pitch_reuse_flag = 1;
1898 35 : move16();
1899 :
1900 : /* 1/4 pitch precision update*/
1901 35 : Copy( st0->pitch, st1->pitch, 3 ); /* Q0 */
1902 35 : Copy( st0->voicing_fx, st1->voicing_fx, 3 ); /* Q15 */
1903 :
1904 : /* Update some parameters accordingly */
1905 35 : st1->old_corr_fx = st0->old_corr_fx; /* Q15 */
1906 35 : st1->old_thres_fx = st0->old_thres_fx; /* Q15 */
1907 35 : st1->delta_pit = st0->delta_pit; /* Q0 */
1908 35 : move16();
1909 35 : move16();
1910 35 : move16();
1911 :
1912 : /* Updates for adaptive lag window memory */
1913 35 : st1->old_pitch_la = st0->old_pitch_la; /* Q0 */
1914 35 : move16();
1915 : /* 1/4 pitch precision update*/
1916 35 : Copy( pitch_fr[0], pitch_fr[1], NB_SUBFR ); /* Q6 */
1917 35 : Copy( voicing_fr[0], voicing_fr[1], NB_SUBFR ); /* Q15 */
1918 : }
1919 : }
1920 :
1921 3827 : return;
1922 : }
1923 :
1924 : /*-------------------------------------------------------------------*
1925 : * Function Get_corr_n_fx()
1926 : *
1927 : *
1928 : *-------------------------------------------------------------------*/
1929 :
1930 3827 : static void Get_corr_n_fx(
1931 : const Word16 L[], /* i : Left signal q_in*/
1932 : const Word16 R[], /* i : Right signal q_in*/
1933 : Word32 *ic_Lm, /* o : Left signal q_ic_Lm*/
1934 : Word16 *q_ic_Lm, /* o : Q factor of Left signal */
1935 : Word32 *ic_Rm, /* o : Right signal q_ic_Rm*/
1936 : Word16 *q_ic_Rm, /* o : Q factor of Right signal */
1937 : const Word16 len, /* i : segment length Q0*/
1938 : Word32 *es_em, /* o : return the difference between the side and mono energy */
1939 : const Word16 tdm_SM_calc_flag /* i : Flag that indicates that it is for SM mode Q0*/
1940 : )
1941 : {
1942 : Word32 corrL, corrR, ener;
1943 : Word16 mono_i;
1944 : Word16 i;
1945 : Word32 ener_side;
1946 : Word16 side_i;
1947 : Word16 exp_diff;
1948 : Word32 L_tmp;
1949 : Word16 guard_bits;
1950 : Word64 W_corrL, W_corrR, W_ener, W_ener_side;
1951 :
1952 3827 : W_corrL = 0;
1953 3827 : move64();
1954 3827 : W_corrR = 0;
1955 3827 : move64();
1956 3827 : W_ener = EPSILON_FX;
1957 3827 : move64();
1958 3827 : W_ener_side = EPSILON_FX;
1959 3827 : move64();
1960 3827 : guard_bits = sub( 32, find_guarded_bits_fx( len ) ); /* Q0 */
1961 :
1962 : /*----------------------------------------------------------------*
1963 : * Find the normalized correlation between: left/mono and right/mono based
1964 : *----------------------------------------------------------------*/
1965 :
1966 3827 : IF( tdm_SM_calc_flag )
1967 : {
1968 0 : FOR( i = 0; i < len; i++ )
1969 : {
1970 0 : mono_i = extract_h( L_msu( L_mult( L[i], ONE_IN_Q14 ), R[i], ONE_IN_Q14 ) ); // q_in
1971 0 : W_corrL = W_mac0_16_16( W_corrL, abs_s( L[i] ), abs_s( mono_i ) ); // (q_in + q_in )
1972 0 : W_corrR = W_mac0_16_16( W_corrR, abs_s( R[i] ), abs_s( mono_i ) ); // (q_in + q_in )
1973 0 : W_ener = W_mac0_16_16( W_ener, mono_i, mono_i ); // (q_in + q_in )
1974 0 : side_i = extract_h( L_mac( L_mult( L[i], ONE_IN_Q14 ), R[i], ONE_IN_Q14 ) ); // q_in
1975 0 : W_ener_side = W_mac0_16_16( W_ener_side, side_i, side_i ); // (q_in + q_in )
1976 : }
1977 : /* Scaling back to the original proposal */
1978 0 : corrL = W_extract_h( W_shl( W_corrL, guard_bits ) ); /* 2*q_in + guard_bits - 32 */
1979 0 : corrR = W_extract_h( W_shl( W_corrR, guard_bits ) ); /* 2*q_in + guard_bits - 32 */
1980 0 : ener = W_extract_h( W_shl( W_ener, guard_bits ) );
1981 0 : ener_side = W_extract_h( W_shl( W_ener_side, guard_bits ) );
1982 : }
1983 : ELSE
1984 : {
1985 2507827 : FOR( i = 0; i < len; i++ )
1986 : {
1987 2504000 : mono_i = extract_h( L_mac( L_mult( L[i], ONE_IN_Q14 ), R[i], ONE_IN_Q14 ) ); // q_in
1988 2504000 : W_corrL = W_mac0_16_16( W_corrL, L[i], mono_i ); // (q_in + q_in )
1989 2504000 : W_corrR = W_mac0_16_16( W_corrR, R[i], mono_i ); // (q_in + q_in )
1990 2504000 : W_ener = W_mac0_16_16( W_ener, mono_i, mono_i ); // (q_in + q_in )
1991 2504000 : side_i = extract_h( L_msu( L_mult( L[i], ONE_IN_Q14 ), R[i], ONE_IN_Q14 ) ); // q_in
1992 2504000 : W_ener_side = W_mac0_16_16( W_ener_side, side_i, side_i ); // (q_in + q_in )
1993 : }
1994 : /* Scaling back to the original proposal */
1995 3827 : corrL = W_extract_h( W_shl( W_corrL, guard_bits ) ); /* 2*q_in + guard_bits - 32 */
1996 3827 : corrR = W_extract_h( W_shl( W_corrR, guard_bits ) ); /* 2*q_in + guard_bits - 32 */
1997 3827 : ener = W_extract_h( W_shl( W_ener, guard_bits ) );
1998 3827 : ener_side = W_extract_h( W_shl( W_ener_side, guard_bits ) );
1999 : }
2000 :
2001 3827 : IF( ener == 0 )
2002 : {
2003 0 : *ic_Lm = 0;
2004 0 : move32();
2005 0 : *q_ic_Lm = Q31;
2006 0 : move16();
2007 0 : *ic_Rm = 0;
2008 0 : move32();
2009 0 : *q_ic_Rm = Q31;
2010 0 : move16();
2011 0 : *es_em = 0;
2012 0 : move32();
2013 : }
2014 : ELSE
2015 : {
2016 3827 : *ic_Lm = BASOP_Util_Divide3232_Scale_newton( corrL, ener, &exp_diff ); // (Q31 - exp_diff)
2017 3827 : move32();
2018 3827 : IF( *ic_Lm == 0 )
2019 : {
2020 0 : *q_ic_Lm = Q31;
2021 0 : move16();
2022 : }
2023 : ELSE
2024 : {
2025 3827 : *q_ic_Lm = sub( Q31, exp_diff );
2026 3827 : move16();
2027 : }
2028 3827 : *ic_Rm = BASOP_Util_Divide3232_Scale_newton( corrR, ener, &exp_diff ); // (Q31 - exp_diff)
2029 3827 : move16();
2030 3827 : IF( *ic_Rm == 0 )
2031 : {
2032 0 : *q_ic_Rm = Q31;
2033 0 : move16();
2034 : }
2035 : ELSE
2036 : {
2037 3827 : *q_ic_Rm = sub( Q31, exp_diff );
2038 3827 : move16();
2039 : }
2040 :
2041 : /* *es_em = 10 * ( log10f( sqrtf( ener_side / len ) ) - log10f( sqrtf( ener / len ) ) );
2042 : is simplified to
2043 : *es_em = 10 * ( log10f( sqrtf( ener_side / ener ) ) ); */
2044 3827 : L_tmp = BASOP_Util_Divide3232_Scale_newton( ener_side, ener, &exp_diff ); // (Q31 - exp_diff)
2045 3827 : L_tmp = Sqrt32( L_tmp, &exp_diff ); /* (Q31 - exp_diff) */
2046 3827 : L_tmp = BASOP_Util_Log2( L_tmp ); /* Q25 */
2047 3827 : *es_em = Mpy_32_32( Mpy_32_32( L_add( L_tmp, L_shl( exp_diff, Q25 ) ), LOG10_2_Q31 ), TEN_IN_Q27 ); // (Q25, Q27) -> Q21
2048 3827 : move32();
2049 : }
2050 :
2051 3827 : return;
2052 : }
2053 :
2054 :
2055 : /*-------------------------------------------------------------------*
2056 : * Function stereo_smooth_LR_transition_fx()
2057 : *
2058 : *-------------------------------------------------------------------*/
2059 :
2060 : /*! r: smoothed position */
2061 121 : static Word16 stereo_smooth_LR_transition_fx(
2062 : Word16 *tdm_prev_stable_idx, /* i/o: Previous Transmitted ratio index Q0*/
2063 : Word16 *tdm_ratio_transition_mov_flag, /* i/o: Flag that indicates that L-R energy is changing Q0*/
2064 : Word16 tdm_last_ratio_idx, /* i : last TDM ratio index Q0*/
2065 : Word16 *tdm_prev_desired_idx, /* i/o: Previous Transmitted ratio index Q0*/
2066 : Word16 *tdm_ratio_transition_cnt, /* i/o: Counter Q0*/
2067 : const Word16 tdm_SM_flag, /* i : channel combination scheme flag for current frame Q0*/
2068 : Word16 desired_idx /* i : desired final position Q0*/
2069 : )
2070 : {
2071 : Word16 idx;
2072 :
2073 121 : IF( EQ_16( tdm_SM_flag, 1 ) )
2074 : {
2075 0 : desired_idx = 15;
2076 0 : move16();
2077 : }
2078 :
2079 121 : IF( NE_16( desired_idx, *tdm_prev_stable_idx ) )
2080 : {
2081 121 : *tdm_ratio_transition_mov_flag = 1;
2082 121 : move16();
2083 : }
2084 :
2085 121 : IF( EQ_16( *tdm_ratio_transition_mov_flag, 1 ) )
2086 : {
2087 121 : IF( NE_16( desired_idx, *tdm_prev_desired_idx ) )
2088 : {
2089 121 : *tdm_prev_stable_idx = tdm_last_ratio_idx;
2090 121 : move16();
2091 121 : *tdm_ratio_transition_cnt = 0;
2092 121 : move16();
2093 : }
2094 :
2095 121 : *tdm_ratio_transition_cnt = add( *tdm_ratio_transition_cnt, 4 );
2096 121 : move16();
2097 121 : IF( LT_16( desired_idx, sub( *tdm_prev_stable_idx, 2 ) ) )
2098 : {
2099 52 : idx = sub( *tdm_prev_stable_idx, *tdm_ratio_transition_cnt );
2100 52 : idx = s_max( desired_idx, idx );
2101 : }
2102 69 : ELSE IF( GT_16( desired_idx, add( *tdm_prev_stable_idx, 2 ) ) )
2103 : {
2104 69 : idx = add( *tdm_prev_stable_idx, *tdm_ratio_transition_cnt );
2105 69 : idx = s_min( desired_idx, idx );
2106 : }
2107 : ELSE
2108 : {
2109 0 : idx = desired_idx;
2110 0 : move16();
2111 : }
2112 : }
2113 : ELSE
2114 : {
2115 0 : idx = desired_idx;
2116 0 : move16();
2117 : }
2118 :
2119 121 : *tdm_prev_desired_idx = desired_idx;
2120 121 : move16();
2121 :
2122 121 : return idx;
2123 : }
|