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.h"
39 : #include "ivas_prot.h"
40 : #include "ivas_rom_com.h"
41 : #include "ivas_cnst.h"
42 : #include "rom_enc.h"
43 : #ifdef DEBUGGING
44 : #include "debug.h"
45 : #endif
46 : #include "wmc_auto.h"
47 :
48 :
49 : /*-------------------------------------------------------------------*
50 : * Local constants
51 : *-------------------------------------------------------------------*/
52 :
53 : #define RMS_MIN 1500 /* Minimum energy for ratio index*/
54 : #define RMS_MIN2 1000 /* Minimum energy for LR encoding*/
55 : #define CORR_THRES 0.95f /* Maximal open loop correlation */
56 : #define DT_ENER_THR 200 /* Energy variation threshold */
57 :
58 : #define ALP_REF 0.8f /* smoothing factor */
59 : #define BET_REF ( 1.0f - ALP_REF )
60 :
61 : #define ALP1 0.5f /* smoothing factor in case of correlation are going in different directions */
62 : #define BET1 ( 1.0f - ALP1 ) /* increase the update rate */
63 :
64 : #define ALP2 0.2f /* smoothing factor in case of correlation are going in different directions in SM mode*/
65 : #define BET2 ( 1.0f - ALP2 ) /* increase the update rate in SM mode*/
66 : #define RATIO_MAX 1.5f /* Maximum correlation ratio */
67 :
68 : #define LIMIT_ADAP_FAC 0.15f
69 : #define MIN_ADAP_FAC 0.1f
70 : #define M_ADAP 0.0009f
71 : #define B_ADAP 0.16f
72 :
73 : #define PC_LIMIT 64
74 : #define RATIO_PG_HR 0.94f
75 : #define RATIO_PG 0.92f
76 : #define PG2ND 3.0f
77 : #define EUCLDST 0.04f
78 : #define RATIO_PG2 0.86f
79 : #define PG2ND2 3.0f
80 : #define EUCLDST2 0.08f
81 :
82 : #define RMS_THR 100
83 : #define RATIO_PG_LRTD 0.96f
84 :
85 : #define IVAS_BRATE_OMASA_STEREO_SW_THR 15000
86 :
87 :
88 : /*-------------------------------------------------------------------*
89 : * Local function prototypes
90 : *-------------------------------------------------------------------*/
91 :
92 : static int16_t stereo_tdm_ener_analysis_SM( CPE_ENC_HANDLE hCPE, Encoder_State **sts, const int16_t input_frame, int16_t *tdm_SM_flag );
93 :
94 : static void Get_corr_n( const float L[], const float R[], float *ic_Lm, float *ic_Rm, const int16_t len, float *es_em, const int16_t tdm_SM_calc_flag );
95 :
96 : static int16_t stereo_smooth_LR_transition( int16_t *tdm_prev_stable_idx, int16_t *tdm_ratio_transition_mov_flag, int16_t tdm_last_ratio_idx, int16_t *tdm_prev_desired_idx, int16_t *tdm_ratio_transition_cnt, const int16_t tdm_SM_flag, int16_t desired_idx );
97 :
98 : static int16_t limit_idx_Dwnmix( const int16_t idx_in, const int16_t unclr_decision, const int16_t inst_idx, const int16_t previous_idx, const int16_t tdm_last_LRTD_PriCh_cnt, const int16_t tdm_last_LRTD_frame_cnt );
99 :
100 : static int16_t limit_idx_NoDwnmix( const int16_t idx_in, const int16_t side_can_change, const float d_lt_corr_raw );
101 :
102 : static void Get_LR_rms( const float *Left_in, const float *Right_in, const int16_t input_frame, float *rms_L, float *rms_R );
103 :
104 : static int16_t Get_dt_lt_ener( CPE_ENC_HANDLE hCPE, const int16_t IsSideMono, const int16_t input_frame, const int16_t tdm_last_SM_flag, const float rms_L, const float rms_R, float *tdm_lt_rms_L, float *tdm_lt_rms_R, float *tdm_last_ener_lt_L, float *tdm_last_ener_lt_R, float *tdm_LT_es_em, int16_t *tdm_hyst_cnt, int16_t *tdm_NOOP_SM_flag_loc, float *ener_R_dt, float *ener_L_dt, float *corr_LM, float *corr_RM );
105 :
106 : static void NOOP_decision( CPE_ENC_HANDLE hCPE, const int16_t tdm_NOOP_flag_loc, const int16_t tmp_SM_flag, const float rms_L, const float rms_R, int16_t *tdm_SM_flag_loc );
107 :
108 : static float Comp_diff_lt_corr( CPE_ENC_HANDLE hCPE, const int16_t IsSideMono, const float rms_L, const float rms_R, const float ener_L_dt, const float ener_R_dt, float corr_LM, float corr_RM, const float tdm_lt_rms_L, const float tdm_lt_rms_R, float *tdm_lt_corr_LM, float *tdm_lt_corr_RM, float *tdm_last_diff_lt_corr, float *inst_ratio_L_out, float *diff_lt_corr );
109 :
110 : /*-------------------------------------------------------------------*
111 : * Function stereo_tdm_ener_analysis()
112 : *
113 : *-------------------------------------------------------------------*/
114 :
115 3791 : int16_t stereo_tdm_ener_analysis(
116 : const int16_t ivas_format, /* i : IVAS format */
117 : CPE_ENC_HANDLE hCPE, /* i : CPE structure */
118 : const int16_t input_frame, /* i : Number of samples */
119 : int16_t *tdm_SM_or_LRTD_Pri, /* o : channel combination scheme flag in TD stereo OR LRTD primary channel */
120 : int16_t *tdm_ratio_idx_SM /* o : TDM ratio index for SM mode */
121 : )
122 : {
123 : float rms_R, rms_L;
124 3791 : float corr_RM, corr_LM, diff_lt_corr = 0, ratio_L, dist;
125 : int16_t i, side_can_change;
126 : int16_t idx, tdm_SM_flag_loc;
127 : int16_t tmp_SM_flag;
128 : float ener_R_dt, ener_L_dt;
129 : int16_t desired_idx;
130 : float rms_thd;
131 : int16_t tdm_NOOP_flag_loc, tdm_NOOP_flag;
132 : STEREO_TD_ENC_DATA_HANDLE hStereoTD;
133 : Encoder_State **sts;
134 : const float *Left_in, *Right_in;
135 : float d_lt_corr_raw;
136 3791 : float inst_ratio_L = 0;
137 : int16_t tdm_LRTD_pri_side;
138 :
139 3791 : hStereoTD = hCPE->hStereoTD;
140 3791 : sts = hCPE->hCoreCoder;
141 3791 : Left_in = sts[0]->input; /* Left channel */
142 3791 : Right_in = sts[1]->input; /* Right channel */
143 :
144 3791 : desired_idx = 0;
145 :
146 : /*----------------------------------------------------------------*
147 : * Compute L and R energy and Long term RMS of each channel
148 : *----------------------------------------------------------------*/
149 :
150 3791 : Get_LR_rms( Left_in, Right_in, input_frame, &rms_L, &rms_R );
151 :
152 : /*----------------------------------------------------------------*
153 : * Compute the 1st order energy difference difference
154 : * Compute the gain of L&R channel compared to mono
155 : * - estimate the long term evolution of the L to Mono gain
156 : * - estimate the long term evolution of the R to Mono gain
157 : * - estimate the long term difference between the long term
158 : * - evolution of the L and R to Mono gain
159 : *----------------------------------------------------------------*/
160 :
161 3791 : tdm_SM_flag_loc = hStereoTD->tdm_last_SM_flag;
162 :
163 3791 : tmp_SM_flag = Get_dt_lt_ener( hCPE, 0, input_frame, hStereoTD->tdm_last_SM_flag, rms_L, rms_R, &hStereoTD->tdm_lt_rms_L, &hStereoTD->tdm_lt_rms_R, &hStereoTD->tdm_last_ener_lt_L, &hStereoTD->tdm_last_ener_lt_R,
164 : &hStereoTD->tdm_LT_es_em, &hStereoTD->tdm_hyst_cnt, &tdm_NOOP_flag_loc, &ener_R_dt, &ener_L_dt, &corr_LM, &corr_RM );
165 :
166 3791 : hStereoTD->tdm_SM_reset_flag = 0;
167 :
168 : /*----------------------------------------------------------------*
169 : * Check if the signal has Near Out Of Phase characteristics
170 : * and trigger side/mono configuration if needed
171 : *----------------------------------------------------------------*/
172 :
173 3791 : NOOP_decision( hCPE, tdm_NOOP_flag_loc, tmp_SM_flag, rms_L, rms_R, &tdm_SM_flag_loc );
174 :
175 : /*----------------------------------------------------------------*
176 : * Adjust stereo downmixing adaptation rate factor
177 : * in function of the signal energy. If signal energy is low,
178 : * adaptation rate factor is lower. This prevent stereo image
179 : * move on speech offset
180 : *----------------------------------------------------------------*/
181 :
182 3791 : d_lt_corr_raw = Comp_diff_lt_corr( hCPE, 0, rms_L, rms_R, ener_L_dt, ener_R_dt, corr_LM, corr_RM, hStereoTD->tdm_lt_rms_L, hStereoTD->tdm_lt_rms_R, &hStereoTD->tdm_lt_corr_LM,
183 : &hStereoTD->tdm_lt_corr_RM, &hStereoTD->tdm_last_diff_lt_corr, &inst_ratio_L, &diff_lt_corr );
184 :
185 : /*----------------------------------------------------------------*
186 : * UNCLR classifier (detection of uncorrelated L and R channels)
187 : * Xtalk classifier (detection of cross-talk L and R channels)
188 : *----------------------------------------------------------------*/
189 :
190 3791 : unclr_classifier_td( hCPE );
191 3791 : xtalk_classifier_td( hCPE );
192 :
193 : /* switch to LRTD on cross-talk segments where two speakers are weakly correlated */
194 3791 : hStereoTD->prev_fr_LRTD_TD_dec = hCPE->hStereoClassif->lrtd_mode;
195 :
196 : /*----------------------------------------------------------------*
197 : * When the energies of channels are low enough, compute the ratio
198 : * of L and R needed to create new mono/side signals
199 : *----------------------------------------------------------------*/
200 :
201 3791 : if ( ivas_format == MASA_ISM_FORMAT )
202 : {
203 :
204 0 : if ( ( hCPE->hStereoClassif->lrtd_mode == 1 || hCPE->hStereoTD->prev_fr_LRTD_TD_dec == 1 ) && ( hCPE->element_brate - 50 * FRAMES_PER_SEC + hCPE->brate_surplus + hCPE->brate_surplus < IVAS_BRATE_OMASA_STEREO_SW_THR ) )
205 : {
206 0 : hStereoTD->prev_fr_LRTD_TD_dec = 0;
207 : }
208 : }
209 :
210 3791 : rms_thd = RMS_MIN;
211 3791 : if ( hCPE->hStereoClassif->lrtd_mode == 1 )
212 : {
213 3791 : rms_thd *= .25f;
214 3791 : if ( hStereoTD->tdm_lt_rms_L <= 75 || hStereoTD->tdm_lt_rms_R <= 75 /*|| sts[0]->last_coder_type == TRANSITION */ )
215 : {
216 435 : rms_thd *= .03125f;
217 : }
218 3356 : else if ( sts[0]->hVAD->hangover_cnt >= 8 && sts[1]->hVAD->hangover_cnt >= 8 )
219 : {
220 0 : rms_thd /= .2f;
221 : }
222 :
223 : /* 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 */
224 3791 : if ( tdm_SM_flag_loc == 1 )
225 : {
226 13 : hStereoTD->prev_fr_LRTD_TD_dec = 0;
227 : }
228 3778 : else if ( hStereoTD->tdm_LRTD_flag == 1 && hStereoTD->tdm_FD2LRTD_SW_cnt > 10 &&
229 3121 : ( hCPE->hStereoClassif->vad_flag_glob == 0 || ( hCPE->hStereoClassif->unclr_decision == 0 && ( hCPE->hStereoClassif->xtalk_score < -0.8f || hCPE->hStereoClassif->xtalk_wscore < -0.13f ) ) ||
230 3088 : ( hCPE->hStereoClassif->unclr_decision == 1 && sts[0]->last_clas == UNVOICED_CLAS && sts[1]->last_clas == UNVOICED_CLAS && fabsf( hCPE->hStereoClassif->unclr_wscore ) < 0.005f ) ) )
231 : {
232 : /* This forces the LRTD to switch to TD when inactive content happens on both channel */
233 33 : hStereoTD->prev_fr_LRTD_TD_dec = 0;
234 : }
235 3745 : else if ( hStereoTD->tdm_LRTD_flag == 0 &&
236 113 : ( hCPE->hStereoClassif->vad_flag_glob == 0 || ( hCPE->hStereoClassif->unclr_decision == 0 && ( hCPE->hStereoClassif->xtalk_score <= 0.0f || hCPE->hStereoClassif->xtalk_wscore <= 0.1f ) ) ||
237 0 : ( hCPE->hStereoClassif->unclr_decision == 1 && ( sts[0]->last_clas == UNVOICED_CLAS && sts[1]->last_clas == UNVOICED_CLAS ) && fabsf( hCPE->hStereoClassif->unclr_wscore ) < 0.025f )
238 : /* (sts[0]->last_clas == UNVOICED_CLAS && sts[1]->last_clas == UNVOICED_CLAS && hCPE->hStereoClassif->xtalk_wscore <= 0.0f)*/ ) )
239 : {
240 : /* This forces the LRTD to switch to TD when inactive content happens on both channel */
241 113 : hStereoTD->prev_fr_LRTD_TD_dec = 0;
242 : }
243 : }
244 :
245 3791 : side_can_change = 0;
246 :
247 : /* update LRTD->DFT stereo hangover counters */
248 3791 : if ( hStereoTD->prev_fr_LRTD_TD_dec == 1 )
249 : {
250 3632 : hStereoTD->tdm_last_LRTD_frame_cnt = 0;
251 : }
252 : else
253 : {
254 159 : hStereoTD->tdm_last_LRTD_frame_cnt++;
255 159 : hStereoTD->tdm_last_LRTD_frame_cnt = min( hStereoTD->tdm_last_LRTD_frame_cnt, 100 );
256 : }
257 :
258 3791 : if ( hCPE->last_element_mode != IVAS_CPE_TD )
259 : {
260 59 : side_can_change = 1;
261 : }
262 :
263 3791 : if ( hStereoTD->prev_fr_LRTD_TD_dec == 1 && side_can_change == 0 )
264 : {
265 3573 : if ( ( hStereoTD->tdm_lt_rms_L <= rms_thd && hStereoTD->tdm_lt_rms_R <= 2 * rms_thd ) ||
266 3383 : ( hStereoTD->tdm_lt_rms_R <= rms_thd && hStereoTD->tdm_lt_rms_L <= 2 * rms_thd ) ||
267 3330 : ( sts[0]->hVAD->hangover_cnt != 0 && sts[1]->hNoiseEst->Etot_last < 12 ) ||
268 3281 : ( sts[1]->hVAD->hangover_cnt != 0 && sts[0]->hNoiseEst->Etot_last < 12 ) ||
269 3281 : ( sts[0]->hSpMusClas->past_dec[0] != sts[1]->hSpMusClas->past_dec[0] ) )
270 : {
271 2096 : if ( ( ( rms_L < RMS_THR && rms_R < RMS_THR && fabsf( rms_R - rms_L ) < RMS_THR / 2.0f && fabsf( d_lt_corr_raw ) > 0.3f ) ||
272 2050 : ( fabsf( sts[0]->old_corr - sts[1]->old_corr ) < 0.15f && sts[0]->old_corr > 0.7f && sts[0]->old_corr < 0.85f && fabsf( rms_L - rms_R ) < rms_thd && fabsf( d_lt_corr_raw ) > 0.3f ) ) /* Both channels are low energy, clean background switching is allowed */
273 : )
274 : {
275 154 : side_can_change = 1;
276 : }
277 : }
278 : }
279 218 : else if ( side_can_change == 0 ) /*if( hStereoTD->prev_fr_LRTD_TD_dec == 0 )*/
280 : {
281 159 : if ( ( ( sts[0]->old_corr < CORR_THRES && sts[1]->old_corr < CORR_THRES ) || ( hStereoTD->tdm_lt_rms_L <= RMS_MIN2 && hStereoTD->tdm_lt_rms_R <= RMS_MIN2 ) ) &&
282 159 : ( ( ( hStereoTD->tdm_lt_rms_L <= rms_thd && hStereoTD->tdm_lt_rms_R <= 2 * rms_thd ) || ( hStereoTD->tdm_lt_rms_R <= rms_thd && hStereoTD->tdm_lt_rms_L <= 2 * rms_thd ) ) ||
283 81 : ( hCPE->hStereoClassif->lrtd_mode == 1 && ( sts[0]->tdm_LRTD_flag == 0 || ( sts[0]->tdm_LRTD_flag == 1 && ( ( rms_L < 2 * rms_thd && rms_R < 2 * rms_thd ) || ( 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 */
284 : ) )
285 : {
286 159 : side_can_change = 1;
287 : }
288 : }
289 :
290 3791 : if ( hCPE->hStereoClassif->xtalk_wscore >= 0.05f && hStereoTD->prev_fr_LRTD_TD_dec == 0 && hCPE->hStereoClassif->lrtd_mode == 1 )
291 : {
292 0 : side_can_change = 0;
293 : }
294 3791 : if ( hCPE->last_element_mode == IVAS_CPE_MDCT || hStereoTD->flag_skip_DMX == 1 )
295 : {
296 100 : desired_idx = LRTD_STEREO_LEFT_IS_PRIM;
297 100 : hStereoTD->tdm_prev_desired_idx = LRTD_STEREO_LEFT_IS_PRIM;
298 100 : ratio_L = 1.0f;
299 100 : hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_LEFT_IS_PRIM;
300 100 : hStereoTD->tdm_ratio_transition_mov_flag = 0;
301 100 : hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_LEFT_IS_PRIM;
302 100 : hStereoTD->tdm_ratio_transition_cnt = 0;
303 100 : idx = TDM_NQ; /* Reserved quantizer index for special case */
304 : }
305 3691 : else if ( side_can_change || sts[1]->ini_frame <= 1 )
306 : {
307 392 : ratio_L = max( diff_lt_corr, -RATIO_MAX );
308 392 : ratio_L = min( ratio_L, RATIO_MAX );
309 392 : ratio_L = 0.667f * ratio_L + 1.0f;
310 :
311 392 : if ( hCPE->hStereoClassif->lrtd_mode == 1 && ( hCPE->last_element_mode != IVAS_CPE_TD || hStereoTD->tdm_FD2LRTD_SW_cnt < 4 ) )
312 : {
313 89 : ratio_L = hCPE->hStereoTD->tdm_last_ratio; /* note: the last_ratio is set in before in stereo_set_tdm() */
314 : }
315 : else
316 : {
317 303 : ratio_L = ( 1.0f - cosf( EVS_PI * ratio_L / 2.0f ) ) / 2.0f;
318 : }
319 :
320 392 : if ( hStereoTD->tdm_LRTD_flag == 1 || ( hCPE->hStereoClassif->lrtd_mode == 1 && ( hCPE->hStereoClassif->prev_lrtd_mode == 0 || abs( hCPE->hStereoTCA->indx_ica_gD - 20 ) > 2 ) ) )
321 : {
322 266 : if ( ratio_L >= 0.53f ) /* small hysteresis is used to prevent undesired switching during inactive segment */
323 : {
324 132 : desired_idx = LRTD_STEREO_LEFT_IS_PRIM - 1;
325 : }
326 134 : else if ( ratio_L < 0.47f )
327 : {
328 105 : desired_idx = LRTD_STEREO_RIGHT_IS_PRIM + 1;
329 : }
330 29 : else if ( rms_L - rms_R > 10 )
331 : {
332 0 : desired_idx = LRTD_STEREO_LEFT_IS_PRIM - 1;
333 : }
334 : else
335 : {
336 29 : desired_idx = LRTD_STEREO_RIGHT_IS_PRIM + 1;
337 : }
338 :
339 266 : if ( desired_idx != hStereoTD->tdm_prev_desired_idx && hStereoTD->tdm_last_LRTD_frame_cnt == 1 && sts[0]->last_coder_type <= UNVOICED ) /* TD transtionning to FD, we don't want an inversion of channels on the first transition frame */
340 : {
341 0 : desired_idx = hStereoTD->tdm_prev_desired_idx;
342 : }
343 : else
344 : {
345 266 : hStereoTD->tdm_prev_desired_idx = desired_idx;
346 : }
347 266 : idx = desired_idx;
348 : }
349 : else
350 : {
351 126 : if ( hCPE->element_brate >= IVAS_48k && sts[0]->hVAD->hangover_cnt != 0 && max( hStereoTD->tdm_lt_rms_L, hStereoTD->tdm_lt_rms_R ) < 512.0f )
352 : {
353 0 : ratio_L = check_bounds( ratio_L, 0.3f, 0.7f );
354 : }
355 :
356 126 : if ( ( hCPE->hStereoTCA->instTargetGain > 1.2f || hCPE->hStereoTCA->targetGain > 1.0f ) && ratio_L < 0.4f )
357 : {
358 0 : ratio_L = 0.4f;
359 : }
360 126 : else if ( ( hCPE->hStereoTCA->instTargetGain < 0.8f || hCPE->hStereoTCA->targetGain < 1.0f ) && ratio_L > 0.6f )
361 : {
362 0 : ratio_L = 0.6f;
363 : }
364 :
365 126 : dist = fabsf( ratio_L - tdm_ratio_tabl[0] );
366 :
367 126 : desired_idx = 0;
368 3906 : for ( i = 1; i < TDM_NQ; i++ )
369 : {
370 3780 : if ( fabsf( ratio_L - tdm_ratio_tabl[i] ) <= dist )
371 : {
372 1614 : dist = fabsf( ratio_L - tdm_ratio_tabl[i] );
373 1614 : desired_idx = i;
374 : }
375 : }
376 :
377 126 : idx = stereo_smooth_LR_transition( &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 );
378 :
379 : /* Change the switching level in case of dual mono (in case the scenario still accept left right switching */
380 : /* 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 */
381 126 : if ( hCPE->hStereoClassif->lrtd_mode == 1 )
382 : {
383 126 : if ( idx <= LRTD_STEREO_MID_IS_PRIM )
384 : {
385 90 : idx = min( idx, LRTD_STEREO_MID_IS_PRIM - 1 );
386 : }
387 : else
388 : {
389 36 : idx = max( idx, LRTD_STEREO_MID_IS_PRIM + 1 );
390 : }
391 :
392 126 : hStereoTD->tdm_prev_desired_idx = idx;
393 : }
394 : /* 0 and 30 are reserved to signal L-R only coding */
395 : }
396 : }
397 : else
398 : {
399 3299 : idx = hStereoTD->tdm_last_ratio_idx;
400 : }
401 :
402 3791 : hStereoTD->tdm_inst_ratio_idx = LRTD_STEREO_RIGHT_IS_PRIM;
403 3791 : tdm_LRTD_pri_side = -1;
404 3791 : if ( hStereoTD->tdm_FD2LRTD_SW_cnt < 5 )
405 : {
406 236 : desired_idx = 15;
407 : }
408 : else
409 : {
410 3555 : desired_idx = 0;
411 3555 : dist = fabsf( inst_ratio_L - tdm_ratio_tabl[0] );
412 :
413 110205 : for ( i = 1; i < TDM_NQ; i++ )
414 : {
415 106650 : if ( fabsf( inst_ratio_L - tdm_ratio_tabl[i] ) <= dist )
416 : {
417 51997 : dist = fabsf( inst_ratio_L - tdm_ratio_tabl[i] );
418 51997 : desired_idx = i;
419 : }
420 : }
421 : }
422 :
423 3791 : if ( ( sts[1]->lp_speech - sts[1]->lp_noise ) < 50.0f ) /* likely presence of noisy content */
424 : {
425 : /* pointing in the right direction, inverse it else do nothing */
426 33 : if ( ( idx > LRTD_STEREO_MID_IS_PRIM && desired_idx > LRTD_STEREO_MID_IS_PRIM ) || ( idx < LRTD_STEREO_MID_IS_PRIM && desired_idx < LRTD_STEREO_MID_IS_PRIM ) )
427 : {
428 : int16_t idx_offet;
429 0 : idx_offet = 5;
430 0 : if ( desired_idx > LRTD_STEREO_MID_IS_PRIM ) /* slightly Favor the 2nd channel */
431 : {
432 0 : idx_offet *= -1;
433 : }
434 0 : desired_idx += idx_offet;
435 0 : desired_idx = check_bounds_s( desired_idx, 0, 30 );
436 : }
437 : }
438 :
439 3791 : if ( sts[1]->clas != UNVOICED_CLAS || sts[0]->clas != UNVOICED_CLAS )
440 : {
441 2896 : desired_idx = check_bounds_s( desired_idx, 5, 25 );
442 : }
443 :
444 3791 : hStereoTD->tdm_inst_ratio_idx = desired_idx;
445 3791 : if ( /*hCPE->last_element_mode == IVAS_CPE_MDCT ||*/ hStereoTD->flag_skip_DMX == 1 )
446 : {
447 : /*force tdm_inst_ratio_idx to the reserved index */
448 100 : hStereoTD->tdm_inst_ratio_idx = idx;
449 100 : tdm_LRTD_pri_side = 1; /* left channel */
450 : }
451 3691 : else if ( hStereoTD->tdm_LRTD_flag == 1 )
452 : {
453 3565 : idx = limit_idx_NoDwnmix( idx, side_can_change, d_lt_corr_raw );
454 3565 : hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_LEFT_IS_PRIM;
455 3565 : tdm_LRTD_pri_side = 0; /* right channel */
456 3565 : if ( idx != LRTD_STEREO_RIGHT_IS_PRIM )
457 : {
458 3297 : tdm_LRTD_pri_side = 1; /* left channel */
459 3297 : hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_RIGHT_IS_PRIM;
460 : }
461 : }
462 : else
463 : {
464 126 : idx = limit_idx_Dwnmix( idx, ( hCPE->hStereoClassif->unclr_decision || ( sts[0]->flag_noisy_speech_snr == 1 && hCPE->hStereoClassif->xtalk_wscore > 0.1f ) ), desired_idx, hStereoTD->tdm_last_ratio_idx, hStereoTD->tdm_last_LRTD_PriCh_cnt, hStereoTD->tdm_last_LRTD_frame_cnt );
465 : }
466 :
467 3791 : if ( abs( hStereoTD->tdm_last_ratio_idx - idx ) > LRTD_STEREO_MID_IS_PRIM )
468 : {
469 37 : hStereoTD->tdm_last_LRTD_PriCh_cnt = 0;
470 : }
471 : else
472 : {
473 3754 : hStereoTD->tdm_last_LRTD_PriCh_cnt++;
474 : }
475 3791 : ratio_L = tdm_ratio_tabl[idx];
476 :
477 3791 : if ( hStereoTD->tdm_SM_modi_flag == 1 && hStereoTD->tdm_LRTD_flag == 0 )
478 : {
479 0 : idx = (int16_t) ( ( hStereoTD->tdm_last_ratio_idx + ( LRTD_STEREO_MID_IS_PRIM + 1 ) ) * 0.5 );
480 0 : ratio_L = tdm_ratio_tabl[idx];
481 : }
482 :
483 3791 : if ( ( hStereoTD->tdm_ratio_transition_mov_flag == 1 && hStereoTD->tdm_ratio_transition_cnt >= 31 ) || ( ( hStereoTD->tdm_last_SM_flag == tdm_SM_flag_loc ) && ( idx == hStereoTD->tdm_prev_stable_idx ) ) )
484 : {
485 55 : hStereoTD->tdm_ratio_transition_cnt = 0;
486 55 : hStereoTD->tdm_ratio_transition_mov_flag = 0;
487 : }
488 :
489 3791 : if ( hStereoTD->tdm_ratio_transition_mov_flag == 0 || tdm_SM_flag_loc == 0 )
490 : {
491 3789 : hStereoTD->tdm_prev_stable_idx = idx;
492 : }
493 :
494 : /* NOOP ratio calculation */
495 3791 : if ( tdm_SM_flag_loc )
496 : {
497 13 : if ( hStereoTD->tdm_SM_reset_flag )
498 : {
499 1 : hStereoTD->tdm_lt_corr_RM_SM = 0.01f;
500 1 : hStereoTD->tdm_lt_corr_LM_SM = 0.01f;
501 1 : hStereoTD->tdm_last_ratio_SM = hStereoTD->tdm_last_ratio;
502 1 : hStereoTD->tdm_last_ratio_idx_SM = hStereoTD->tdm_last_ratio_idx;
503 1 : hStereoTD->tdm_lt_rms_L_SM = 40.0f;
504 1 : hStereoTD->tdm_lt_rms_R_SM = 40.0f;
505 1 : hStereoTD->tdm_last_diff_lt_corr_SM = 0;
506 1 : hStereoTD->tdm_last_ener_lt_R_SM = 0;
507 1 : hStereoTD->tdm_last_ener_lt_L_SM = 0;
508 :
509 1 : hStereoTD->tdm_noop_mov_flag = 0;
510 1 : hStereoTD->tdm_noop_cnt = 0;
511 1 : hStereoTD->tdm_last_SM_flag_noop = 0;
512 1 : hStereoTD->tdm_prev_stable_idx_SM = 0;
513 1 : hStereoTD->tdm_prev_desired_idx_SM = 0;
514 1 : hStereoTD->tdm_LT_es_em_SM = 0.1f;
515 1 : hStereoTD->tdm_hyst_cnt_SM = 0;
516 : }
517 :
518 13 : *tdm_ratio_idx_SM = stereo_tdm_ener_analysis_SM( hCPE, sts, input_frame, &tdm_NOOP_flag );
519 : }
520 : else
521 : {
522 3778 : *tdm_ratio_idx_SM = LRTD_STEREO_MID_IS_PRIM;
523 3778 : tdm_NOOP_flag = 1;
524 : }
525 :
526 3791 : sts[0]->tdm_LRTD_flag = hStereoTD->tdm_LRTD_flag;
527 3791 : sts[1]->tdm_LRTD_flag = hStereoTD->tdm_LRTD_flag;
528 :
529 : /* set channel combination scheme flag */
530 3791 : *tdm_SM_or_LRTD_Pri = tdm_SM_flag_loc;
531 3791 : if ( hCPE->hStereoTD->tdm_LRTD_flag == 1 )
532 : {
533 3665 : *tdm_SM_or_LRTD_Pri = tdm_LRTD_pri_side;
534 : }
535 :
536 3791 : hCPE->hStereoClassif->ratio_L = ratio_L;
537 :
538 : #ifdef DEBUG_MODE_TD
539 : dbgwrite( &ratio_L, 4, 1, 320, "res/ratio_L" );
540 : dbgwrite( &hStereoTD->prev_fr_LRTD_TD_dec, 2, 1, 320, "res/prev_fr_LRTD_TD_dec" );
541 : dbgwrite( &hStereoTD->tdm_inst_ratio_idx, 2, 1, 320, "res/inst_ratio_L" );
542 : #endif
543 :
544 3791 : return ( idx );
545 : }
546 :
547 : /*-------------------------------------------------------------------*
548 : * Function Get_LR_rms()
549 : *
550 : * Get current frame left and right rms values
551 : *-------------------------------------------------------------------*/
552 :
553 3804 : static void Get_LR_rms(
554 : const float *Left_in,
555 : const float *Right_in,
556 : const int16_t input_frame,
557 : float *rms_L,
558 : float *rms_R )
559 : {
560 : float ener_l, ener_r;
561 : int16_t i;
562 :
563 3804 : ener_l = 0.01f;
564 3804 : ener_r = 0.01f;
565 :
566 2528924 : for ( i = 0; i < input_frame; i++ )
567 : {
568 2525120 : ener_l += Left_in[i] * Left_in[i];
569 2525120 : ener_r += Right_in[i] * Right_in[i];
570 : }
571 3804 : *rms_L = sqrtf( ener_l / input_frame );
572 3804 : *rms_R = sqrtf( ener_r / input_frame );
573 :
574 3804 : return;
575 : }
576 :
577 :
578 : /*-------------------------------------------------------------------*
579 : * Function Get_dt_lt_ener()
580 : *
581 : * Compute the gain of L&R channel compared to mono
582 : * - estimate the long term evolution of the L to Mono gain
583 : * - estimate the long term evolution of the R to Mono gain
584 : * - estimate the long term difference between the long term
585 : * - evolution of the L and R to Mono gain
586 : *-------------------------------------------------------------------*/
587 :
588 3804 : static int16_t Get_dt_lt_ener(
589 : CPE_ENC_HANDLE hCPE,
590 : const int16_t IsSideMono,
591 : const int16_t input_frame,
592 : const int16_t tdm_last_SM_flag,
593 : const float rms_L,
594 : const float rms_R,
595 : float *tdm_lt_rms_L,
596 : float *tdm_lt_rms_R,
597 : float *tdm_last_ener_lt_L,
598 : float *tdm_last_ener_lt_R,
599 : float *tdm_LT_es_em,
600 : int16_t *tdm_hyst_cnt,
601 : int16_t *tdm_NOOP_SM_flag_loc,
602 : float *ener_R_dt,
603 : float *ener_L_dt,
604 : float *corr_LM,
605 : float *corr_RM )
606 : {
607 : Encoder_State **sts;
608 : const float *Left_in, *Right_in;
609 : float es_em;
610 : int16_t tmp_SM_flag, tdm_SM_flag_loc;
611 :
612 3804 : sts = hCPE->hCoreCoder;
613 3804 : Left_in = sts[0]->input; /* Left channel */
614 3804 : Right_in = sts[1]->input; /* Right channel */
615 :
616 3804 : tdm_SM_flag_loc = tdm_last_SM_flag;
617 :
618 3804 : if ( hCPE->last_element_mode != IVAS_CPE_TD && IsSideMono == 0 ) /* last coding mode not TD and normal mono/side case, quick update of lt energy */
619 : {
620 59 : *tdm_lt_rms_L = .9f * rms_L;
621 59 : *tdm_lt_rms_R = .9f * rms_R;
622 59 : sts[1]->hNoiseEst->Etot_last = 0.9f * ( sts[0]->hNoiseEst->Etot_last );
623 59 : sts[1]->hVAD->hangover_cnt = 0;
624 : }
625 : else
626 : {
627 3745 : *tdm_lt_rms_L = 0.6f * *tdm_lt_rms_L + 0.4f * rms_L;
628 3745 : *tdm_lt_rms_R = 0.6f * *tdm_lt_rms_R + 0.4f * rms_R;
629 : }
630 :
631 : /*----------------------------------------------------------------*
632 : * Compute the 1st order energy difference difference
633 : *----------------------------------------------------------------*/
634 :
635 3804 : *ener_R_dt = *tdm_lt_rms_R - *tdm_last_ener_lt_R;
636 3804 : *tdm_last_ener_lt_R = *tdm_lt_rms_R;
637 :
638 3804 : *ener_L_dt = *tdm_lt_rms_L - *tdm_last_ener_lt_L;
639 3804 : *tdm_last_ener_lt_L = *tdm_lt_rms_L;
640 :
641 : /*----------------------------------------------------------------*
642 : * Compute the gain of L&R channel compared to mono
643 : * - estimate the long term evolution of the L to Mono gain
644 : * - estimate the long term evolution of the R to Mono gain
645 : * - estimate the long term difference between the long term
646 : * - evolution of the L and R to Mono gain
647 : *----------------------------------------------------------------*/
648 :
649 3804 : Get_corr_n( Left_in, Right_in, corr_LM, corr_RM, input_frame, &es_em, IsSideMono );
650 :
651 3804 : hCPE->hStereoClassif->xtalk_fv[E_diff_corrLM_corrRM] = *corr_LM - *corr_RM;
652 :
653 3804 : if ( sts[0]->hVAD->hangover_cnt != 0 )
654 : {
655 398 : *tdm_LT_es_em = 0.9f * *tdm_LT_es_em;
656 : }
657 : else
658 : {
659 3406 : *tdm_LT_es_em = 0.9f * *tdm_LT_es_em + 0.1f * es_em;
660 : }
661 :
662 3804 : hCPE->hStereoClassif->xtalk_fv[E_tdm_LT_es_em] = *tdm_LT_es_em;
663 :
664 3804 : tmp_SM_flag = 0;
665 3804 : if ( min( sts[0]->old_corr, sts[1]->old_corr ) < 0.85f && max( sts[0]->old_corr, sts[1]->old_corr < 0.92f ) &&
666 3284 : ( *tdm_LT_es_em > 2.0f || es_em > 2.5f ) && ( sts[0]->hVAD->hangover_cnt <= 1 && sts[1]->hVAD->hangover_cnt <= 3 && sts[0]->tdm_LRTD_flag == 0 ) )
667 : {
668 3 : tmp_SM_flag = 1;
669 : }
670 3804 : if ( IsSideMono == 0 )
671 : {
672 3791 : *tdm_NOOP_SM_flag_loc = tdm_SM_flag_loc;
673 : }
674 :
675 3804 : if ( tmp_SM_flag != tdm_SM_flag_loc )
676 : {
677 15 : if ( ( *tdm_hyst_cnt )++ >= 2 && tmp_SM_flag == 1 && ( sts[0]->tdm_pc > PC_LIMIT || sts[1]->tdm_pc > PC_LIMIT ) )
678 : {
679 1 : *tdm_NOOP_SM_flag_loc = tmp_SM_flag;
680 1 : *tdm_hyst_cnt = 0;
681 : }
682 14 : else if ( ( *tdm_hyst_cnt )++ >= 20 && tmp_SM_flag == 0 &&
683 3 : ( sts[0]->tdm_pc > PC_LIMIT || sts[1]->tdm_pc > PC_LIMIT ) && ( *tdm_LT_es_em <= 0.5f || es_em < -10.0f ) )
684 : {
685 0 : *tdm_NOOP_SM_flag_loc = tmp_SM_flag;
686 0 : *tdm_hyst_cnt = 0;
687 : }
688 : }
689 : else
690 : {
691 3789 : *tdm_hyst_cnt = 0;
692 : }
693 :
694 3804 : return tmp_SM_flag;
695 : }
696 :
697 :
698 : /*-------------------------------------------------------------------*
699 : * Function NOOP_decision()
700 : *
701 : * Set Near Out Of Phase decision
702 : *-------------------------------------------------------------------*/
703 :
704 3791 : static void NOOP_decision(
705 : CPE_ENC_HANDLE hCPE,
706 : const int16_t tdm_NOOP_flag_loc,
707 : const int16_t tmp_SM_flag,
708 : const float rms_L,
709 : const float rms_R,
710 : int16_t *tdm_SM_flag_loc )
711 : {
712 : int16_t tdm_NOOP_switch_flag;
713 : STEREO_TD_ENC_DATA_HANDLE hStereoTD;
714 : Encoder_State **sts;
715 :
716 3791 : hStereoTD = hCPE->hStereoTD;
717 3791 : sts = hCPE->hCoreCoder;
718 :
719 3791 : tdm_NOOP_switch_flag = 0;
720 3791 : hStereoTD->tdm_NOOP_cnt++;
721 3791 : if ( hCPE->hCoreCoder[0]->sp_aud_decision0 == 0 )
722 : {
723 3791 : if ( ( ( hStereoTD->tdm_SM_last2_clas[0] > VOICED_TRANSITION && ( hStereoTD->tdm_SM_last_clas[0] == UNVOICED_CLAS || hStereoTD->tdm_SM_last_clas[0] == VOICED_TRANSITION ) ) ||
724 3791 : ( hStereoTD->tdm_SM_last2_clas[1] > VOICED_TRANSITION && ( hStereoTD->tdm_SM_last_clas[1] == UNVOICED_CLAS || hStereoTD->tdm_SM_last_clas[1] == VOICED_TRANSITION ) ) ) &&
725 351 : ( !( sts[0]->last_coder_type_raw == VOICED || sts[1]->last_coder_type_raw == VOICED ) && hStereoTD->tdm_NOOP_cnt > 5 ) )
726 : {
727 134 : tdm_NOOP_switch_flag = 1;
728 134 : hStereoTD->tdm_NOOP_cnt = 0;
729 : }
730 3657 : else if ( ( hStereoTD->tdm_SM_last_clas[0] == UNVOICED_CLAS || hStereoTD->tdm_SM_last_clas[1] == UNVOICED_CLAS ) &&
731 1817 : ( !( sts[0]->last_coder_type_raw == VOICED || sts[1]->last_coder_type_raw == VOICED ) ) && ( rms_L < 400.0f && rms_R < 400.0f ) && ( hStereoTD->tdm_NOOP_cnt > 5 ) )
732 : {
733 67 : tdm_NOOP_switch_flag = 1;
734 67 : hStereoTD->tdm_NOOP_cnt = 0;
735 : }
736 : }
737 : else
738 : {
739 0 : if ( sts[0]->ee_old < 5000.f && sts[1]->ee_old < 5000.f )
740 : {
741 0 : tdm_NOOP_switch_flag = 1;
742 : }
743 : }
744 :
745 3791 : if ( *tdm_SM_flag_loc != tdm_NOOP_flag_loc )
746 : {
747 1 : hStereoTD->tdm_SM_flag = 1;
748 1 : if ( hCPE->hCoreCoder[0]->sp_aud_decision0 == 0 )
749 : {
750 1 : if ( tdm_NOOP_switch_flag == 1 )
751 : {
752 0 : *tdm_SM_flag_loc = tdm_NOOP_flag_loc;
753 0 : if ( *tdm_SM_flag_loc )
754 : {
755 0 : hStereoTD->tdm_SM_reset_flag = 1;
756 : }
757 0 : hStereoTD->tdm_SM_flag = 0;
758 : }
759 : }
760 : else
761 : {
762 0 : if ( tdm_NOOP_switch_flag == 1 )
763 : {
764 0 : *tdm_SM_flag_loc = tdm_NOOP_flag_loc;
765 0 : if ( *tdm_SM_flag_loc )
766 : {
767 0 : hStereoTD->tdm_SM_reset_flag = 1;
768 : }
769 0 : hStereoTD->tdm_SM_flag = 0;
770 : }
771 : }
772 :
773 1 : if ( tdm_NOOP_flag_loc == 1 )
774 : {
775 1 : hStereoTD->tdm_hyst_cnt = 2;
776 : }
777 : else
778 : {
779 0 : hStereoTD->tdm_hyst_cnt = 20;
780 : }
781 : }
782 :
783 3791 : if ( hStereoTD->tdm_SM_flag > 0 && tdm_NOOP_switch_flag == 1 && *tdm_SM_flag_loc != tmp_SM_flag )
784 : {
785 1 : *tdm_SM_flag_loc = !( *tdm_SM_flag_loc );
786 1 : hStereoTD->tdm_SM_flag = 0;
787 1 : if ( *tdm_SM_flag_loc )
788 : {
789 1 : hStereoTD->tdm_SM_reset_flag = 1;
790 : }
791 : }
792 :
793 3791 : if ( hStereoTD->tdm_SM_modi_flag == 1 )
794 : {
795 0 : *tdm_SM_flag_loc = 1;
796 0 : hStereoTD->tdm_SM_modi_flag = 0;
797 0 : hStereoTD->tdm_SM_reset_flag = 1;
798 : }
799 : else
800 : {
801 3791 : if ( *tdm_SM_flag_loc == 1 && hStereoTD->tdm_SM_reset_flag == 1 && hStereoTD->tdm_last_ratio < 0.5 )
802 : {
803 0 : hStereoTD->tdm_SM_reset_flag = 0;
804 0 : *tdm_SM_flag_loc = 0;
805 0 : hStereoTD->tdm_SM_modi_flag = 1;
806 : }
807 : }
808 :
809 3791 : return;
810 : }
811 :
812 :
813 : /*-------------------------------------------------------------------*
814 : * Function Comp_diff_lt_corr()
815 : *
816 : * Adjust stereo downmixing adaptation rate factor
817 : * in function of the signal energy.
818 : *-------------------------------------------------------------------*/
819 :
820 3804 : static float Comp_diff_lt_corr(
821 : CPE_ENC_HANDLE hCPE,
822 : const int16_t IsSideMono,
823 : const float rms_L,
824 : const float rms_R,
825 : const float ener_L_dt,
826 : const float ener_R_dt,
827 : float corr_LM,
828 : float corr_RM,
829 : const float tdm_lt_rms_L,
830 : const float tdm_lt_rms_R,
831 : float *tdm_lt_corr_LM,
832 : float *tdm_lt_corr_RM,
833 : float *tdm_last_diff_lt_corr,
834 : float *inst_ratio_L_out,
835 : float *diff_lt_corr )
836 : {
837 : float adaprate, adaprate_tmp, madaprate, d_lt_corr_raw, diff_lt_corr_tmp;
838 : float d_lt_corr, inst_ratio_L, diff_lt_corr_LM_tmp, diff_lt_corr_RM_tmp;
839 : Encoder_State **sts;
840 :
841 3804 : sts = hCPE->hCoreCoder;
842 :
843 : /*----------------------------------------------------------------*
844 : * Adjust stereo downmixing adaptation rate factor
845 : * in function of the signal energy. If signal energy is low,
846 : * adaptation rate factor is lower. This prevent stereo image
847 : * move on speech offset
848 : *----------------------------------------------------------------*/
849 :
850 3804 : if ( IsSideMono == 0 && hCPE->hStereoClassif->lrtd_mode == 1 && ( ( tdm_lt_rms_R > 2.0f * tdm_lt_rms_L ) || ( tdm_lt_rms_L > 2.0f * tdm_lt_rms_R ) ) )
851 : {
852 1489 : adaprate = M_ADAP * max( tdm_lt_rms_R, tdm_lt_rms_L ) + B_ADAP;
853 : }
854 : else
855 : {
856 2315 : adaprate = M_ADAP * min( tdm_lt_rms_R, tdm_lt_rms_L ) + B_ADAP;
857 : }
858 :
859 3804 : adaprate = check_bounds( adaprate, MIN_ADAP_FAC, 1.0f );
860 :
861 : /*----------------------------------------------------------------*
862 : * In case of unvoiced content (expect when it is part of an onset),
863 : * the adaptation rate is minimal.
864 : *----------------------------------------------------------------*/
865 :
866 3804 : if ( sts[0]->ini_frame > 2 &&
867 3546 : ( ( sts[0]->last_clas <= VOICED_TRANSITION && sts[0]->hVAD->hangover_cnt == 0 ) ||
868 2104 : ( sts[1]->last_clas <= VOICED_TRANSITION && sts[1]->hVAD->hangover_cnt == 0 ) ) )
869 : {
870 1995 : adaprate = min( adaprate, LIMIT_ADAP_FAC );
871 : }
872 :
873 3804 : d_lt_corr_raw = 0.0f;
874 3804 : if ( IsSideMono == 0 )
875 : {
876 3791 : if ( hCPE->last_element_mode != IVAS_CPE_TD || ( ( tdm_lt_rms_R < 1.0f || tdm_lt_rms_L < 1.0f ) && hCPE->hStereoClassif->lrtd_mode == 1 && max( tdm_lt_rms_R, tdm_lt_rms_L ) < 10.0f ) )
877 : {
878 71 : adaprate = 0.98f; /* speed up the adaptation of the long term values to the current values after coming from DFT */
879 : }
880 3791 : adaprate_tmp = max( adaprate, 0.8f );
881 3791 : madaprate = 1.0f - adaprate_tmp; /* madaprate has temporary value, will updated few lines below */
882 :
883 3791 : d_lt_corr_raw = ( adaprate_tmp * corr_LM + madaprate * *tdm_lt_corr_LM ) -
884 3791 : ( adaprate_tmp * corr_RM + madaprate * *tdm_lt_corr_RM ); /* Short term smooth correlation differences to mono */
885 3791 : inst_ratio_L = 0.0f;
886 : /*inst_ratio_L = max(diff_lt_corr,-RATIO_MAX);*/
887 3791 : inst_ratio_L = max( d_lt_corr_raw, -RATIO_MAX );
888 3791 : inst_ratio_L = min( inst_ratio_L, RATIO_MAX );
889 3791 : inst_ratio_L = 0.667f * inst_ratio_L + 1.0f;
890 3791 : *inst_ratio_L_out = ( 1.0f - cosf( EVS_PI * inst_ratio_L / 2.0f ) ) / 2.0f;
891 : }
892 3804 : madaprate = 1.0f - adaprate;
893 3804 : corr_RM = adaprate * corr_RM + madaprate * *tdm_lt_corr_RM;
894 3804 : corr_LM = adaprate * corr_LM + madaprate * *tdm_lt_corr_LM;
895 3804 : diff_lt_corr_LM_tmp = ( ALP_REF * *tdm_lt_corr_LM + BET_REF * corr_LM );
896 3804 : diff_lt_corr_RM_tmp = ( ALP_REF * *tdm_lt_corr_RM + BET_REF * corr_RM );
897 3804 : diff_lt_corr_tmp = diff_lt_corr_LM_tmp - diff_lt_corr_RM_tmp;
898 :
899 3804 : d_lt_corr = diff_lt_corr_tmp - *tdm_last_diff_lt_corr;
900 3804 : *tdm_last_diff_lt_corr = diff_lt_corr_tmp;
901 :
902 : /*----------------------------------------------------------------*
903 : * Correct the estimation depending of channels energies evolution
904 : *----------------------------------------------------------------*/
905 :
906 3804 : if ( IsSideMono == 1 && ( ( rms_L < RMS_MIN2 && rms_R < RMS_MIN2 ) && ( ( tdm_lt_rms_L < 0.8f * rms_L ) && ( tdm_lt_rms_R < 0.8f * rms_R ) ) &&
907 0 : ( ( tdm_lt_rms_L > 2.0f * tdm_lt_rms_R ) || ( tdm_lt_rms_L < 0.5f * tdm_lt_rms_R ) ) ) )
908 : {
909 0 : *tdm_lt_corr_LM = ALP2 * *tdm_lt_corr_LM + BET2 * corr_LM;
910 0 : *tdm_lt_corr_RM = ALP2 * *tdm_lt_corr_RM + BET2 * corr_RM;
911 :
912 0 : *tdm_lt_corr_LM *= 2.5f;
913 0 : *tdm_lt_corr_RM *= 2.5f;
914 : }
915 3804 : else if ( ( !( ( ener_R_dt > DT_ENER_THR && ener_L_dt < DT_ENER_THR ) || ( ener_R_dt < DT_ENER_THR && ener_L_dt > DT_ENER_THR ) ) /* Energy are going in the same direction */
916 3100 : && ( fabsf( d_lt_corr ) < 0.31f /* small difference regarding the difference gain evolution */
917 188 : || tdm_lt_rms_L > 2 * RMS_MIN2 || tdm_lt_rms_R > 2 * RMS_MIN2 ) ) /* Energy of at least one of the channel is not low */
918 : )
919 : {
920 : /* Use estimated results */
921 2975 : *tdm_lt_corr_LM = diff_lt_corr_LM_tmp;
922 2975 : *tdm_lt_corr_RM = diff_lt_corr_RM_tmp;
923 : }
924 : else
925 : {
926 829 : *tdm_lt_corr_LM = ALP1 * *tdm_lt_corr_LM + BET1 * corr_LM;
927 829 : *tdm_lt_corr_RM = ALP1 * *tdm_lt_corr_RM + BET1 * corr_RM;
928 : }
929 :
930 3804 : *diff_lt_corr = *tdm_lt_corr_LM - *tdm_lt_corr_RM; /* update the difference */
931 :
932 3804 : return d_lt_corr_raw;
933 : }
934 :
935 :
936 : /*-------------------------------------------------------------------*
937 : * Function limit_idx_Dnwmix()
938 : *
939 : *
940 : *-------------------------------------------------------------------*/
941 :
942 126 : static int16_t limit_idx_Dwnmix(
943 : const int16_t idx_in,
944 : const int16_t unclr_decision,
945 : const int16_t inst_idx,
946 : const int16_t previous_idx,
947 : const int16_t tdm_last_LRTD_PriCh_cnt,
948 : const int16_t tdm_last_LRTD_frame_cnt )
949 : {
950 : int16_t idx;
951 :
952 126 : idx = idx_in;
953 126 : idx = check_bounds_s( idx, 1, 29 );
954 :
955 126 : if ( unclr_decision == 1 && tdm_last_LRTD_frame_cnt > 1 )
956 : {
957 75 : if ( tdm_last_LRTD_PriCh_cnt > 0 )
958 : {
959 71 : if ( idx <= LRTD_STEREO_MID_IS_PRIM && ( inst_idx < LRTD_STEREO_MID_IS_PRIM + 2 ) )
960 : {
961 35 : idx = min( 1, idx );
962 : }
963 36 : else if ( idx >= LRTD_STEREO_MID_IS_PRIM && ( inst_idx > LRTD_STEREO_MID_IS_PRIM - 2 ) )
964 : {
965 29 : idx = max( 29, idx );
966 : }
967 7 : else if ( inst_idx < LRTD_STEREO_MID_IS_PRIM - 4 )
968 : {
969 2 : idx = min( 1, idx );
970 : }
971 5 : else if ( inst_idx > LRTD_STEREO_MID_IS_PRIM + 4 )
972 : {
973 2 : idx = max( 29, idx );
974 : }
975 : else
976 : {
977 3 : idx = previous_idx;
978 : }
979 : }
980 : else
981 : {
982 4 : idx = previous_idx;
983 : }
984 : }
985 :
986 126 : return idx;
987 : }
988 :
989 :
990 : /*-------------------------------------------------------------------*
991 : * Function limit_idx_NoDwnmix()
992 : *
993 : *-------------------------------------------------------------------*/
994 :
995 3565 : static int16_t limit_idx_NoDwnmix(
996 : const int16_t idx_in, /* i : Index */
997 : const int16_t side_can_change, /* i : Primary and secondary channel allowed to change ? */
998 : const float d_lt_corr_raw /* i : Raw corrrelation differences */
999 : )
1000 : {
1001 : int16_t idx;
1002 :
1003 3565 : idx = idx_in;
1004 3565 : if ( side_can_change == 0 && idx_in > 10 && idx_in < 20 )
1005 : {
1006 0 : idx = 30;
1007 0 : if ( d_lt_corr_raw < -0.1f )
1008 : {
1009 0 : idx = 0;
1010 : }
1011 : }
1012 : else
1013 : {
1014 3565 : if ( idx <= 15 )
1015 : {
1016 268 : idx = 0;
1017 : }
1018 : else
1019 : {
1020 3297 : idx = 30;
1021 : }
1022 : }
1023 :
1024 3565 : return idx;
1025 : }
1026 :
1027 :
1028 : /*-------------------------------------------------------------------*
1029 : * Function stereo_tdm_ener_analysis_SM()
1030 : *
1031 : *
1032 : *-------------------------------------------------------------------*/
1033 :
1034 13 : static int16_t stereo_tdm_ener_analysis_SM(
1035 : CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */
1036 : Encoder_State **sts, /* i/o: Encoder static variables structure */
1037 : const int16_t input_frame, /* i : Number of samples */
1038 : int16_t *tdm_SM_flag /* i/o: channel combination scheme flag */
1039 : )
1040 : {
1041 : float rms_R, rms_L;
1042 : float corr_RM, corr_LM, diff_lt_corr, ratio_L, dist;
1043 : int16_t i, side_can_change;
1044 : int16_t idx, tdm_SM_flag_loc;
1045 13 : float es_em = 0.01f;
1046 : float ener_R_dt, ener_L_dt;
1047 13 : int16_t desired_idx = 0;
1048 : STEREO_TD_ENC_DATA_HANDLE hStereoTD;
1049 :
1050 13 : hStereoTD = hCPE->hStereoTD;
1051 :
1052 : /*----------------------------------------------------------------*
1053 : * set SM flag
1054 : *----------------------------------------------------------------*/
1055 :
1056 : /* 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 */
1057 13 : tdm_SM_flag_loc = hStereoTD->tdm_last_SM_flag_noop;
1058 :
1059 : /*----------------------------------------------------------------*
1060 : * Compute L and R energy and Long term RMS of each channel
1061 : *----------------------------------------------------------------*/
1062 :
1063 13 : Get_LR_rms( sts[0]->input, sts[1]->input, input_frame, &rms_L, &rms_R );
1064 :
1065 : /*----------------------------------------------------------------*
1066 : * Compute the 1st order energy difference difference
1067 : * Compute the gain of L&R channel compared to mono
1068 : * - estimate the long term evolution of the L to Mono gain
1069 : * - estimate the long term evolution of the R to Mono gain
1070 : * - estimate the long term difference between the long term
1071 : * - evolution of the L and R to Mono gain
1072 : *----------------------------------------------------------------*/
1073 :
1074 13 : Get_dt_lt_ener( hCPE, 1, input_frame, hStereoTD->tdm_last_SM_flag_noop, rms_L, rms_R,
1075 : &hStereoTD->tdm_lt_rms_L_SM, &hStereoTD->tdm_lt_rms_R_SM, &hStereoTD->tdm_last_ener_lt_L_SM, &hStereoTD->tdm_last_ener_lt_R_SM, &hStereoTD->tdm_LT_es_em_SM, &hStereoTD->tdm_hyst_cnt_SM, &tdm_SM_flag_loc,
1076 : &ener_R_dt, &ener_L_dt, &corr_LM, &corr_RM );
1077 :
1078 13 : hStereoTD->tdm_SM_reset_flag = 0;
1079 :
1080 : /*----------------------------------------------------------------*
1081 : * Adjust stereo downmixing adaptation rate factor
1082 : * in function of the signal energy. If signal energy is low,
1083 : * adaptation rate factor is lower. This prevent stereo image
1084 : * move on speech offset
1085 : *----------------------------------------------------------------*/
1086 :
1087 13 : Comp_diff_lt_corr( hCPE, 1, rms_L, rms_R, ener_L_dt, ener_R_dt, corr_LM, corr_RM, hStereoTD->tdm_lt_rms_L_SM, hStereoTD->tdm_lt_rms_R_SM, &hStereoTD->tdm_lt_corr_LM_SM,
1088 : &hStereoTD->tdm_lt_corr_RM_SM, &( hStereoTD->tdm_last_diff_lt_corr_SM ), NULL, &diff_lt_corr );
1089 :
1090 13 : side_can_change = 0;
1091 :
1092 : /*----------------------------------------------------------------*
1093 : * When the energies of channels are low enough, compute the ratio
1094 : * of L and R needed to create new mono/side signals
1095 : *----------------------------------------------------------------*/
1096 :
1097 13 : if ( ( hStereoTD->tdm_lt_rms_L_SM <= RMS_MIN && hStereoTD->tdm_lt_rms_R_SM <= 2 * RMS_MIN ) || ( hStereoTD->tdm_lt_rms_R_SM <= RMS_MIN && hStereoTD->tdm_lt_rms_L_SM <= 2 * RMS_MIN ) )
1098 : {
1099 13 : if ( ( sts[0]->old_corr < CORR_THRES && sts[1]->old_corr < CORR_THRES ) || ( hStereoTD->tdm_lt_rms_L_SM <= RMS_MIN2 && hStereoTD->tdm_lt_rms_R_SM <= RMS_MIN2 ) )
1100 : {
1101 13 : side_can_change = 1;
1102 : }
1103 : }
1104 :
1105 13 : if ( ( hStereoTD->tdm_lt_rms_L_SM <= RMS_MIN2 && hStereoTD->tdm_lt_rms_R_SM <= 2 * RMS_MIN2 ) || ( hStereoTD->tdm_lt_rms_R_SM <= RMS_MIN2 && hStereoTD->tdm_lt_rms_L_SM <= 2 * RMS_MIN2 ) )
1106 : {
1107 13 : if ( ( ( hStereoTD->tdm_last_SM_flag_noop != tdm_SM_flag_loc ) && hStereoTD->tdm_noop_cnt == 0 ) ||
1108 13 : hStereoTD->tdm_noop_mov_flag == 1 || hStereoTD->tdm_prev_desired_idx_SM != hStereoTD->tdm_prev_stable_idx_SM )
1109 : {
1110 3 : hStereoTD->tdm_noop_mov_flag = 1;
1111 3 : if ( hStereoTD->tdm_last_ratio_idx_SM != 0 && hStereoTD->tdm_last_ratio_idx_SM != ( TDM_NQ - 1 ) )
1112 : {
1113 3 : side_can_change = 1;
1114 : }
1115 : }
1116 : }
1117 :
1118 13 : if ( side_can_change == 0 && tdm_SM_flag_loc == 1 && es_em > 15.0f )
1119 : {
1120 0 : side_can_change = 1;
1121 : }
1122 :
1123 13 : if ( side_can_change )
1124 : {
1125 13 : ratio_L = max( diff_lt_corr, -RATIO_MAX );
1126 13 : ratio_L = min( ratio_L, RATIO_MAX );
1127 :
1128 13 : if ( ratio_L > 0.5f * RATIO_MAX )
1129 : {
1130 0 : ratio_L = 1.08f * ratio_L + 0.38f;
1131 : }
1132 13 : else if ( ratio_L < -0.5f * RATIO_MAX )
1133 : {
1134 0 : ratio_L = 0.64f * ratio_L + 1.28f;
1135 : }
1136 : else
1137 : {
1138 13 : ratio_L = 0.26f * ratio_L + 0.995f;
1139 : }
1140 :
1141 13 : ratio_L = ( 1.0f - cosf( EVS_PI * ratio_L / 2.0f ) ) / 2.0f;
1142 :
1143 13 : dist = fabsf( ratio_L - tdm_ratio_tabl[0] );
1144 :
1145 13 : desired_idx = 0;
1146 403 : for ( i = 1; i < TDM_NQ; i++ )
1147 : {
1148 390 : if ( fabsf( ratio_L - tdm_ratio_tabl[i] ) <= dist )
1149 : {
1150 195 : dist = fabsf( ratio_L - tdm_ratio_tabl[i] );
1151 195 : desired_idx = i;
1152 : }
1153 : }
1154 :
1155 13 : idx = stereo_smooth_LR_transition( &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 );
1156 :
1157 13 : idx = (int16_t) ( idx * 0.8f + hStereoTD->tdm_last_ratio_idx_SM * 0.2f );
1158 :
1159 13 : ratio_L = tdm_ratio_tabl[idx];
1160 : }
1161 : else
1162 : {
1163 0 : ratio_L = hStereoTD->tdm_last_ratio_SM;
1164 0 : idx = hStereoTD->tdm_last_ratio_idx_SM;
1165 : }
1166 :
1167 13 : if ( ( hStereoTD->tdm_noop_mov_flag == 1 && hStereoTD->tdm_noop_cnt >= 31 ) || ( ( hStereoTD->tdm_last_SM_flag_noop == tdm_SM_flag_loc ) && ( idx == hStereoTD->tdm_prev_stable_idx_SM ) ) )
1168 : {
1169 10 : hStereoTD->tdm_noop_cnt = 0;
1170 10 : hStereoTD->tdm_noop_mov_flag = 0;
1171 : }
1172 :
1173 13 : if ( hStereoTD->tdm_noop_mov_flag == 0 || tdm_SM_flag_loc == 0 )
1174 : {
1175 13 : hStereoTD->tdm_prev_stable_idx_SM = idx;
1176 : }
1177 :
1178 13 : hStereoTD->tdm_last_SM_flag_noop = tdm_SM_flag_loc;
1179 13 : *tdm_SM_flag = tdm_SM_flag_loc;
1180 :
1181 13 : return ( idx );
1182 : }
1183 :
1184 :
1185 : /*-------------------------------------------------------------------*
1186 : * tdm_lp_comparison()
1187 : *
1188 : * Perform the comparison of the 2 sets of LP coefficients
1189 : *-------------------------------------------------------------------*/
1190 :
1191 : /*! r: replication decision; 1 = Use old LP */
1192 3791 : int16_t tdm_lp_comparison(
1193 : STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i/o: TD stereo encoder handle */
1194 : STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */
1195 : Encoder_State *st, /* i/o: Encoder structure */
1196 : const float *speech, /* i : Current speech frame */
1197 : const float *A_PCh, /* i : primary channel LP coefficients */
1198 : const float *A_SCh, /* i : secondary channel LP coeff. */
1199 : const int16_t m, /* i : filter length */
1200 : const float *isp_PCh, /* i : primary channel LSPs */
1201 : const float *isp_SCh, /* i : secondary channel LSPs */
1202 : const int16_t L_frame, /* i : frame length */
1203 : const int32_t element_brate_wo_meta /* i : element bitrate without metadata*/
1204 : )
1205 : {
1206 : float predgain_SCh, pred_gain_reuse_PCh, ener_sig;
1207 : float res[L_FRAME16k];
1208 : int16_t LP_mode;
1209 : float dist, ftmp;
1210 : int16_t i;
1211 :
1212 : /* Find prediction gain for current LP filter */
1213 3791 : residu( A_SCh, m, speech, res, L_frame );
1214 3791 : ener_sig = log10f( sum2_f( speech, L_frame ) + 0.01f );
1215 3791 : predgain_SCh = 10.0f * ( ener_sig - log10f( sum2_f( res, L_frame ) + 0.01f ) );
1216 :
1217 : /* Find prediction gain when resuing the Primary Channel LP filter */
1218 3791 : residu( A_PCh, m, speech, res, L_frame );
1219 3791 : pred_gain_reuse_PCh = 10.0f * ( ener_sig - log10f( sum2_f( res, L_frame ) + 0.01f ) );
1220 :
1221 : /* Find Euclidian distance between the 2 filters */
1222 3791 : dist = 0;
1223 64447 : for ( i = 0; i < m; i++ )
1224 : {
1225 60656 : ftmp = isp_SCh[i] - isp_PCh[i];
1226 60656 : dist += ftmp * ftmp;
1227 : }
1228 3791 : ener_sig *= 10.0f;
1229 :
1230 : /* Verification of the filters similartiies and prediction gain obtained for each channel */
1231 : /* Threshold are more relax if alpha is close to 0.5 (Valid if ICA is used ) */
1232 3791 : if ( ( ( pred_gain_reuse_PCh >= RATIO_PG * predgain_SCh && dist < EUCLDST ) /* Prediction gain are close & Euclidian dist is small */
1233 2890 : || ( predgain_SCh < PG2ND && dist < EUCLDST2 ) ) /* Prediction gain if the secondary channel is low & Euclidian dist is not too large */
1234 2716 : || ( hStereoTD->tdm_last_ratio_idx >= ( LRTD_STEREO_MID_IS_PRIM - 2 ) && hStereoTD->tdm_last_ratio_idx <= ( LRTD_STEREO_MID_IS_PRIM + 2 ) && /* ratio between 0.4 and 0.6 */
1235 0 : ( ( pred_gain_reuse_PCh >= RATIO_PG2 * predgain_SCh && dist < EUCLDST2 ) || predgain_SCh < PG2ND2 ) ) /* Prediction gain are not far & Euclidian dist is not too large or Prediction gain if the secondary channel is low */
1236 2716 : || ener_sig <= 30.0f /* secondary channel has low energy */
1237 : )
1238 : {
1239 1075 : LP_mode = 1;
1240 :
1241 1075 : if ( ( element_brate_wo_meta >= IVAS_48k && !( pred_gain_reuse_PCh >= RATIO_PG_HR * predgain_SCh && dist < EUCLDST ) ) ||
1242 1075 : ( hStereoClassif->lrtd_mode == 1 && element_brate_wo_meta < IVAS_16k4 && !( pred_gain_reuse_PCh >= RATIO_PG_HR * predgain_SCh && dist < EUCLDST / 2.0f ) ) ||
1243 1075 : ( hStereoClassif->lrtd_mode == 1 && element_brate_wo_meta >= IVAS_16k4 && !( pred_gain_reuse_PCh >= RATIO_PG_LRTD * predgain_SCh && dist < EUCLDST / 4.0f ) ) || st->tc_cnt > 0 )
1244 : {
1245 925 : LP_mode = 0;
1246 : }
1247 : }
1248 : else
1249 : {
1250 : /* Prediction or and filters are too different -> quantize the difference*/
1251 2716 : LP_mode = 0;
1252 : }
1253 :
1254 3791 : return LP_mode;
1255 : }
1256 :
1257 :
1258 : /*-------------------------------------------------------------------*
1259 : * tdm_ol_pitch_comparison()
1260 : *
1261 : * Perform the comparison of the 2 sets of OL pitch
1262 : *-------------------------------------------------------------------*/
1263 :
1264 : /*! r: replication decision; 1 = Use old LP */
1265 3791 : void tdm_ol_pitch_comparison(
1266 : CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */
1267 : float pitch_fr[CPE_CHANNELS][NB_SUBFR], /* i/o: fractional pitch values */
1268 : float voicing_fr[CPE_CHANNELS][NB_SUBFR] /* i/o: fractional pitch gains */
1269 : )
1270 : {
1271 : int16_t tmp_diff;
1272 3791 : int16_t diff_thr = 6;
1273 : Encoder_State *st0, *st1;
1274 :
1275 3791 : st0 = hCPE->hCoreCoder[0]; /* Encoder structure - primary channel */
1276 3791 : st1 = hCPE->hCoreCoder[1]; /* Encoder structure - secondary channel */
1277 :
1278 3791 : if ( hCPE->element_brate > IVAS_13k2 )
1279 : {
1280 3791 : diff_thr = 3;
1281 : }
1282 :
1283 3791 : if ( hCPE->element_brate >= IVAS_48k || hCPE->hStereoTD->tdm_LRTD_flag == 1 )
1284 : {
1285 3665 : diff_thr = 1;
1286 : }
1287 :
1288 3791 : hCPE->hStereoTD->tdm_Pitch_reuse_flag = 0;
1289 :
1290 3791 : if ( ( ( st0->sp_aud_decision1 == 0 && st0->sp_aud_decision2 == 0 ) && /* Pitch is not recycled in case of music coding*/
1291 3249 : ( hCPE->element_brate <= IVAS_16k4 || ( hCPE->element_brate <= IVAS_24k4 && st0->coder_type == VOICED && st1->coder_type == VOICED ) ) ) ||
1292 3089 : hCPE->element_brate < IVAS_13k2 )
1293 : {
1294 702 : if ( hCPE->hStereoClassif->lrtd_mode == 1 )
1295 : {
1296 : float voicmin[4];
1297 :
1298 702 : minimum( st0->voicing, 3, voicmin );
1299 702 : minimum( st1->voicing, 3, voicmin + 1 );
1300 702 : minimum( voicing_fr[0], 4, voicmin + 2 );
1301 702 : minimum( voicing_fr[1], 4, voicmin + 3 );
1302 :
1303 702 : tmp_diff = 10;
1304 702 : if ( voicmin[0] >= .9f && voicmin[1] >= .9f && voicmin[2] >= .85f && voicmin[3] >= .85f )
1305 : {
1306 41 : tmp_diff = (int16_t) ( abs( ( st0->pitch[0] - st1->pitch[0] ) ) + abs( ( st0->pitch[1] - st1->pitch[1] ) ) + abs( ( st0->pitch[2] - st1->pitch[2] ) ) );
1307 : }
1308 : }
1309 : else
1310 : {
1311 0 : tmp_diff = (int16_t) abs( ( st0->pitch[0] + st0->pitch[1] + st0->pitch[2] ) - ( st1->pitch[0] + st1->pitch[1] + st1->pitch[2] ) );
1312 : }
1313 :
1314 702 : if ( tmp_diff <= diff_thr )
1315 : {
1316 33 : hCPE->hStereoTD->tdm_Pitch_reuse_flag = 1;
1317 :
1318 : /* 1/4 pitch precision update*/
1319 33 : mvs2s( st0->pitch, st1->pitch, 3 );
1320 33 : mvr2r( st0->voicing, st1->voicing, 3 );
1321 :
1322 : /* Update some parameters accordingly */
1323 33 : st1->old_corr = st0->old_corr;
1324 33 : st1->old_thres = st0->old_thres;
1325 33 : st1->delta_pit = st0->delta_pit;
1326 :
1327 : /* Updates for adaptive lag window memory */
1328 33 : st1->old_pitch_la = st0->old_pitch_la;
1329 : /* 1/4 pitch precision update*/
1330 33 : mvr2r( pitch_fr[0], pitch_fr[1], NB_SUBFR );
1331 33 : mvr2r( voicing_fr[0], voicing_fr[1], NB_SUBFR );
1332 : }
1333 : }
1334 :
1335 3791 : return;
1336 : }
1337 :
1338 :
1339 : /*-------------------------------------------------------------------*
1340 : * Function Get_corr_n()
1341 : *
1342 : *
1343 : *-------------------------------------------------------------------*/
1344 :
1345 3804 : static void Get_corr_n(
1346 : const float L[], /* i : Left signal */
1347 : const float R[], /* i : Right signal */
1348 : float *ic_Lm, /* o : Right signal */
1349 : float *ic_Rm, /* o : Right signal */
1350 : const int16_t len, /* i : segment length */
1351 : float *es_em, /* o : return the difference between the side and mono energy */
1352 : const int16_t tdm_SM_calc_flag /* i : Flag that indicates that it is for SM mode */
1353 : )
1354 : {
1355 : float corrL, corrR, ener, mono_i;
1356 : int16_t i;
1357 : float ener_side, side_i;
1358 :
1359 3804 : corrL = 0;
1360 3804 : corrR = 0;
1361 3804 : ener = 1e-6f;
1362 3804 : ener_side = 1e-6f;
1363 :
1364 : /*----------------------------------------------------------------*
1365 : * Find the normalized correlation between: left/mono and right/mono based
1366 : *----------------------------------------------------------------*/
1367 :
1368 3804 : if ( tdm_SM_calc_flag )
1369 : {
1370 8333 : for ( i = 0; i < len; i++ )
1371 : {
1372 8320 : mono_i = ( L[i] - R[i] ) / 2.0f;
1373 8320 : corrL += fabsf( L[i] ) * fabsf( mono_i );
1374 8320 : corrR += fabsf( R[i] ) * fabsf( mono_i );
1375 8320 : ener += mono_i * mono_i;
1376 8320 : side_i = ( L[i] + R[i] ) / 2.0f;
1377 8320 : ener_side += side_i * side_i;
1378 : }
1379 : }
1380 : else
1381 : {
1382 2520591 : for ( i = 0; i < len; i++ )
1383 : {
1384 2516800 : mono_i = ( L[i] + R[i] ) / 2.0f;
1385 2516800 : corrL += L[i] * mono_i;
1386 2516800 : corrR += R[i] * mono_i;
1387 2516800 : ener += mono_i * mono_i;
1388 2516800 : side_i = ( L[i] - R[i] ) / 2.0f;
1389 2516800 : ener_side += side_i * side_i;
1390 : }
1391 : }
1392 :
1393 3804 : *ic_Lm = corrL / ener;
1394 3804 : *ic_Rm = corrR / ener;
1395 :
1396 3804 : *es_em = 10 * ( log10f( sqrtf( ener_side / len ) ) - log10f( sqrtf( ener / len ) ) );
1397 :
1398 3804 : return;
1399 : }
1400 :
1401 :
1402 : /*-------------------------------------------------------------------*
1403 : * Function stereo_smooth_LR_transition()
1404 : *
1405 : *-------------------------------------------------------------------*/
1406 :
1407 : /*! r: smoothed position */
1408 139 : static int16_t stereo_smooth_LR_transition(
1409 : int16_t *tdm_prev_stable_idx, /* i/o: Previous Transmitted ratio index */
1410 : int16_t *tdm_ratio_transition_mov_flag, /* i/o: Flag that indicates that L-R energy is changing */
1411 : int16_t tdm_last_ratio_idx, /* i : last TDM ratio index */
1412 : int16_t *tdm_prev_desired_idx, /* i/o: Previous Transmitted ratio index */
1413 : int16_t *tdm_ratio_transition_cnt, /* i/o: Counter */
1414 : const int16_t tdm_SM_flag, /* i : channel combination scheme flag for current frame */
1415 : int16_t desired_idx /* i : desired final position */
1416 : )
1417 : {
1418 : int16_t idx;
1419 :
1420 139 : if ( tdm_SM_flag == 1 )
1421 : {
1422 13 : desired_idx = 15;
1423 : }
1424 :
1425 139 : if ( desired_idx != *tdm_prev_stable_idx )
1426 : {
1427 128 : *tdm_ratio_transition_mov_flag = 1;
1428 : }
1429 :
1430 139 : if ( *tdm_ratio_transition_mov_flag == 1 )
1431 : {
1432 130 : if ( desired_idx != *tdm_prev_desired_idx )
1433 : {
1434 126 : *tdm_prev_stable_idx = tdm_last_ratio_idx;
1435 126 : *tdm_ratio_transition_cnt = 0;
1436 : }
1437 :
1438 130 : *tdm_ratio_transition_cnt += 4;
1439 130 : if ( desired_idx < *tdm_prev_stable_idx - 2 )
1440 : {
1441 39 : idx = *tdm_prev_stable_idx - *tdm_ratio_transition_cnt;
1442 39 : idx = max( desired_idx, idx );
1443 : }
1444 91 : else if ( desired_idx > *tdm_prev_stable_idx + 2 )
1445 : {
1446 73 : idx = *tdm_prev_stable_idx + *tdm_ratio_transition_cnt;
1447 73 : idx = min( desired_idx, idx );
1448 : }
1449 : else
1450 : {
1451 18 : idx = desired_idx;
1452 : }
1453 : }
1454 : else
1455 : {
1456 9 : idx = desired_idx;
1457 : }
1458 :
1459 139 : *tdm_prev_desired_idx = desired_idx;
1460 :
1461 139 : return idx;
1462 : }
|