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