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 <assert.h>
34 : #include <stdint.h>
35 : #include "options.h"
36 : #include <math.h>
37 : #include "cnst.h"
38 : #include "ivas_cnst.h"
39 : #include "prot_fx.h"
40 : #include "wmc_auto.h"
41 : #include "rom_com.h"
42 : #include "ivas_rom_com.h"
43 :
44 : #include "ivas_prot_fx.h"
45 : #include "ivas_rom_com_fx.h"
46 :
47 : /*---------------------------------------------------------------
48 : * Local function prototypes
49 : * ---------------------------------------------------------------*/
50 : static void unclr_calc_corr_features_fx(
51 : STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier handle */
52 : STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */
53 : Word32 buf1[], /* i : left channel q_com*/
54 : Word32 buf2[], /* i : right channel q_com*/
55 : Word16 q_com,
56 : const Word16 length, /* i : length of input signal buffers Q0*/
57 : Word32 corrEst[], /* i : buffer containing inter-channel correlation values Q31-corrEst_exp*/
58 : Word16 corrEst_exp,
59 : const Word16 lagSearchRange[], /* i : minimum and maximum lags for corrEst[] Q0*/
60 : Word32 *corrEst_ncorr, /* o : norm. x-correlation btw. current and previous correlation buffers Q31-corrEst_ncorr_exp*/
61 : Word16 *corrEst_ncorr_exp );
62 :
63 :
64 : #define XL_BIAS_FX_Q15 6554
65 : #define XH_BIAS_FX_Q15 13107
66 : #define XL_WIDTH_FX_Q15 3932
67 : #define XH_WIDTH_FX_Q15 4915
68 : #define SMOOTH_DIST_FACTOR_FX_Q15 13107
69 : #define A_BIAS_FX_Q15 3277
70 : #define B_BIAS_FX_Q15 -16384
71 : #define A_WIDTH_FX_Q31 32212264
72 : #define B_WIDTH_FX_Q31 32212192
73 : #define SMOOTH_ENV_FACTOR_FX_Q15 19661
74 :
75 :
76 : /*---------------------------------------------------------------
77 : * tcaTargetCh_LA()
78 : *
79 : * Temporal channel adjustment of LA samples in target channel
80 : * ---------------------------------------------------------------*/
81 96 : static void tcaTargetCh_LA_fx(
82 : STEREO_TCA_ENC_HANDLE hStereoTCA,
83 : Word32 *ptrChanL, /* q_com */
84 : Word32 *ptrChanR, /* q_com */
85 : Word16 *q_com,
86 : const Word16 currentNCShift, /* Q0 */
87 : const Word16 input_frame /* Q0 */ )
88 : {
89 : Word16 i, j;
90 : Word16 tempS, temp, sine_inp;
91 : Word32 tempF1, tempF2, gAdj;
92 : Word16 tempF1_exp, tempF2_exp, gAdj_exp;
93 :
94 : Word32 *ref, *target;
95 : Word16 ref_exp, target_exp, target_exp_temp[L_FRAME48k + L_FRAME48k];
96 : Word16 win[240]; /* 5 ms at 48 kHz */
97 :
98 96 : ref_exp = sub( 31, *q_com );
99 96 : target_exp = sub( 31, *q_com );
100 96 : set16_fx( target_exp_temp, target_exp, L_FRAME48k + currentNCShift );
101 :
102 96 : IF( EQ_16( hStereoTCA->refChanIndx, L_CH_INDX ) )
103 : {
104 66 : ref = ptrChanL;
105 66 : target = ptrChanR;
106 : }
107 : ELSE
108 : {
109 30 : ref = ptrChanR;
110 30 : target = ptrChanL;
111 : }
112 :
113 96 : tempS = NS2SA_FX2( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS );
114 96 : tempF1 = 0;
115 96 : move32();
116 96 : tempF1_exp = 0;
117 96 : move32();
118 96 : tempF2 = 0;
119 96 : move32();
120 96 : tempF2_exp = 0;
121 96 : move16();
122 52975 : FOR( i = 0; i < ( input_frame - currentNCShift ); i++ )
123 : {
124 52879 : tempF1 = BASOP_Util_Add_Mant32Exp( tempF1, tempF1_exp, L_abs( ref[i] ), ref_exp, &tempF1_exp ); /* Q31-tempF1_exp */
125 52879 : tempF2 = BASOP_Util_Add_Mant32Exp( tempF2, tempF2_exp, L_abs( target[i + currentNCShift] ), target_exp, &tempF2_exp ); /* Q31-tempF2_exp */
126 : }
127 :
128 96 : IF( tempF1 == 0 )
129 : {
130 0 : gAdj = ONE_IN_Q31; /* Q31 */
131 0 : move32();
132 0 : gAdj_exp = 0;
133 0 : move16();
134 : }
135 : ELSE
136 : {
137 96 : Word32 deno = BASOP_Util_Add_Mant32Exp( tempF1, tempF1_exp, -21475 /*0.00001f in Q31*/, 0, &temp ); /* Q31-temp */
138 : Word16 deno_exp;
139 96 : IF( deno > 0 )
140 : {
141 96 : deno = tempF1;
142 96 : move32();
143 96 : deno_exp = tempF1_exp;
144 96 : move16();
145 : }
146 : ELSE
147 : {
148 0 : deno = 21475;
149 0 : move32();
150 0 : deno_exp = 0;
151 0 : move16();
152 : }
153 96 : gAdj = BASOP_Util_Divide3232_Scale_newton( tempF2, deno, &gAdj_exp ); /* Q31-gAdj_exp */
154 96 : gAdj_exp = add( gAdj_exp, sub( tempF2_exp, deno_exp ) );
155 : }
156 :
157 1956 : FOR( i = 0; i < tempS; i++ )
158 : {
159 1860 : sine_inp = BASOP_Util_Divide1616_Scale( add( shl( i, 10 ), 512 /* 0.5 Q10 */ ), shl( tempS, 1 ), &temp ); /* Q15-(temp+(15-10)) */
160 1860 : sine_inp = shl_sat( sine_inp, add( temp, -10 ) ); /*Q0*/
161 1860 : win[i] = getSineWord16R2( shr( sine_inp, 1 ) ); /*Q15*/
162 1860 : move16();
163 : }
164 :
165 96 : j = 0;
166 96 : move16();
167 :
168 96 : Word16 exp_com = target_exp_temp[0];
169 96 : move16();
170 1956 : FOR( i = ( input_frame - ( currentNCShift + tempS ) ); i < ( input_frame - currentNCShift ); ( i++, j++ ) )
171 : {
172 1860 : target[i + currentNCShift] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( Mpy_32_16_1( gAdj, win[j] ), ref[i] ), add( ref_exp, gAdj_exp ), Mpy_32_16_1( target[i + currentNCShift], sub( MAX_16, win[j] ) ), target_exp, &temp ); /* Q31-temp */
173 1860 : move32();
174 1860 : target_exp_temp[i + currentNCShift] = temp;
175 1860 : move16();
176 1860 : exp_com = s_max( exp_com, temp );
177 : }
178 :
179 6737 : FOR( ; i < input_frame; i++ )
180 : {
181 6641 : target[i + currentNCShift] = Mpy_32_32( gAdj, ref[i] ); /* Q31-target_exp_temp */
182 6641 : move32();
183 6641 : target_exp_temp[i + currentNCShift] = add( gAdj_exp, ref_exp );
184 6641 : move16();
185 6641 : exp_com = s_max( exp_com, target_exp_temp[i + currentNCShift] );
186 : }
187 :
188 66257 : FOR( i = 0; i < input_frame + currentNCShift; i++ )
189 : {
190 66161 : target[i] = L_shl( target[i], sub( target_exp_temp[i], exp_com ) ); /* Q31-exp_com */
191 66161 : move32();
192 66161 : ref[i] = L_shl( ref[i], sub( ref_exp, exp_com ) ); /* Q31-exp_com */
193 66161 : move32();
194 : }
195 96 : *q_com = sub( 31, exp_com );
196 96 : move16();
197 :
198 96 : return;
199 : }
200 : /*---------------------------------------------------------------
201 : * spectral_balancer()
202 : *
203 : * Spectral-balancer to take care of the low-freq rumble and
204 : * compensate for the pre-emphasis.
205 : * ---------------------------------------------------------------*/
206 148 : void spectral_balancer_fx16(
207 : Word16 *signal, /* i/o : signal Qx */
208 : Word16 *mem, /* i/o : mem Qx */
209 : const Word16 lg, /* i : input signal length Q0*/
210 : const Word16 coeff_set /* i : coefficient set Q0*/
211 : )
212 : {
213 : Word16 i;
214 : Word16 x0, x1, x2, y0, y1, y2;
215 : Word32 a1, a2, b0, b1, b2;
216 :
217 148 : y1 = mem[0];
218 148 : y2 = mem[1];
219 148 : x0 = mem[2];
220 148 : x1 = mem[3];
221 148 : move16();
222 148 : move16();
223 148 : move16();
224 148 : move16();
225 :
226 : /* hp filter 60Hz at 3dB for 8000KHz sampling rate
227 : 1. [b,a] = butter(1, 60.0/8000.0, 'high');
228 : 2. spectral_balancing_filter
229 : <<gain = 0.97697627795388164 -> maybe not needed>>
230 : b =[1, -1] [1, -0.6]
231 : a =[1, -0.95395255590776329] [1, 0.5] */
232 148 : IF( coeff_set == 0 )
233 : {
234 : // a1 = 0.747789178258504f;
235 : // a2 = -0.272214937925007f;
236 : // b0 = 0.505001029045878f;
237 : // b1 = -1.01000205809176f;
238 : // b2 = 0.505001029045878f;
239 0 : a1 = 401466258; // Q29
240 0 : move32();
241 0 : a2 = -146144282; // Q29
242 0 : move32();
243 0 : b0 = 271120363; // Q29
244 0 : move32();
245 0 : b1 = -542240726; // Q29
246 0 : move32();
247 0 : b2 = 271120363; // Q29
248 0 : move32();
249 : }
250 : ELSE
251 : {
252 : // a1 = -0.13456126833218354f;
253 : // a2 = -0.38813694706072926f;
254 : // b0 = 1.0f;
255 : // b1 = -1.9980666374183167f;
256 : // b2 = 1.0f;
257 148 : a1 = -72242031; // Q29
258 148 : move32();
259 148 : a2 = -208379437; // Q29
260 148 : move32();
261 148 : b0 = 536870912; // Q29
262 148 : move32();
263 148 : b1 = -1072703858; // Q29
264 148 : move32();
265 148 : b2 = 536870912; // Q29
266 148 : move32();
267 : }
268 :
269 96148 : FOR( i = 0; i < lg; i++ )
270 : {
271 96000 : x2 = x1; /*Qx*/
272 96000 : move16();
273 96000 : x1 = x0; /*Qx*/
274 96000 : move16();
275 96000 : x0 = signal[i]; /*Qx*/
276 96000 : move16();
277 : // y0 = (y1 * a1) + (y2 * a2) + (x0 * b0) + (x1 * b1) + (x2 * b2);
278 96000 : y0 = extract_l( W_extract_l( W_shr( W_mac_32_16( W_mac_32_16( W_mac_32_16( W_mac_32_16( W_mult_32_16( a1, y1 ), a2, y2 ), b0, x0 ), b1, x1 ), b2, x2 ), 30 ) ) ); // Qx
279 96000 : signal[i] = y0; /*Qx*/
280 96000 : move16();
281 96000 : y2 = y1; /*Qx*/
282 96000 : move16();
283 96000 : y1 = y0; /*Qx*/
284 96000 : move16();
285 : }
286 :
287 148 : mem[0] = y1; /*Qx*/
288 148 : mem[1] = y2; /*Qx*/
289 148 : mem[2] = x0; /*Qx*/
290 148 : mem[3] = x1; /*Qx*/
291 148 : move16();
292 148 : move16();
293 148 : move16();
294 148 : move16();
295 :
296 148 : return;
297 : }
298 :
299 7654 : void spectral_balancer_fx(
300 : Word32 *signal, /* i/o : signal Qx */
301 : Word32 *mem, /* i/o : mem Qx */
302 : const Word16 lg, /* i : input signal length Q0*/
303 : const Word16 coeff_set /* i : coefficient set Q0*/
304 : )
305 : {
306 : Word16 i;
307 : Word32 x0, x1, x2, y0, y1, y2;
308 : Word32 a1, a2, b0, b1, b2;
309 :
310 7654 : y1 = mem[0]; /*Qx*/
311 7654 : y2 = mem[1]; /*Qx*/
312 7654 : x0 = mem[2]; /*Qx*/
313 7654 : x1 = mem[3]; /*Qx*/
314 7654 : move32();
315 7654 : move32();
316 7654 : move32();
317 7654 : move32();
318 :
319 : /* hp filter 60Hz at 3dB for 8000KHz sampling rate
320 : 1. [b,a] = butter(1, 60.0/8000.0, 'high');
321 : 2. spectral_balancing_filter
322 : <<gain = 0.97697627795388164 -> maybe not needed>>
323 : b =[1, -1] [1, -0.6]
324 : a =[1, -0.95395255590776329] [1, 0.5] */
325 7654 : IF( coeff_set == 0 )
326 : {
327 7654 : a1 = 401466258; // Q29
328 7654 : move32();
329 7654 : a2 = -146144282; // Q29
330 7654 : move32();
331 7654 : b0 = 271120363; // Q29
332 7654 : move32();
333 7654 : b1 = -542240726; // Q29
334 7654 : move32();
335 7654 : b2 = 271120363; // Q29
336 7654 : move32();
337 : }
338 : ELSE
339 : {
340 0 : a1 = -72242031; // Q29
341 0 : move32();
342 0 : a2 = -208379437; // Q29
343 0 : move32();
344 0 : b0 = 536870912; // Q29
345 0 : move32();
346 0 : b1 = -1072703858; // Q29
347 0 : move32();
348 0 : b2 = 536870912; // Q29
349 0 : move32();
350 : }
351 :
352 1232294 : FOR( i = 0; i < lg; i++ )
353 : {
354 1224640 : x2 = x1; /*Qx*/
355 1224640 : move16();
356 1224640 : x1 = x0; /*Qx*/
357 1224640 : move16();
358 1224640 : x0 = signal[i]; /*Qx*/
359 1224640 : move16();
360 1224640 : y0 = W_extract_l( W_shr( W_mac_32_32( W_mac_32_32( W_mac_32_32( W_mac_32_32( W_mult_32_32( a1, y1 ), a2, y2 ), b0, x0 ), b1, x1 ), b2, x2 ), 30 ) ); // Qx
361 1224640 : signal[i] = y0; /*Qx*/
362 1224640 : move16();
363 1224640 : y2 = y1; /*Qx*/
364 1224640 : move16();
365 1224640 : y1 = y0; /*Qx*/
366 1224640 : move16();
367 : }
368 :
369 7654 : mem[0] = y1; /*Qx*/
370 7654 : move32();
371 7654 : mem[1] = y2; /*Qx*/
372 7654 : move32();
373 7654 : mem[2] = x0; /*Qx*/
374 7654 : move32();
375 7654 : mem[3] = x1; /*Qx*/
376 7654 : move32();
377 :
378 7654 : return;
379 : }
380 :
381 :
382 : /*---------------------------------------------------------------
383 : * deEmphResample()
384 : *
385 : * De-emphasize and resample the L and R channels.
386 : * ---------------------------------------------------------------*/
387 3827 : static void deEmphResample_fx(
388 : STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo TCA encoder handle */
389 : const Word32 *tempChan1_fx, /* i : Stereo data Qx*/
390 : const Word32 *tempChan2_fx, /* i : Stereo data Qx*/
391 : Word32 *chan1_fx, /*Qx*/
392 : Word32 *chan2_fx, /*Qx*/
393 : const Word16 input_frame, /*Q0*/
394 : const Word16 dsFactor /*Q0*/ )
395 : {
396 : Word32 buf1_fx[L_FRAME48k], buf2_fx[L_FRAME48k];
397 : Word32 tempBuf1_fx[2 * L_FRAME_DS], tempBuf2_fx[2 * L_FRAME_DS];
398 : Word16 i;
399 : Word16 dsFac1, dsFac2;
400 :
401 : /* Estimate first and second stage downsample factors */
402 3827 : dsFac1 = shr( dsFactor, 1 ); /*Qx*/
403 3827 : dsFac2 = idiv1616( dsFactor, dsFac1 ); /*Qx*/
404 :
405 : /* convert stereo data to two distinct channels, e.g., L, R */
406 3827 : Copy32( tempChan1_fx, buf1_fx, input_frame ); /*Qx*/
407 3827 : Copy32( tempChan2_fx, buf2_fx, input_frame ); /*Qx*/
408 :
409 : /* De-emphasis, 1/(1-mu z^-1), and resample, stage 1 */
410 :
411 3827 : deemph_fx_32( buf1_fx, PREEMPH_FAC_16k, input_frame, &hStereoTCA->memdecim_fx[0] );
412 3827 : deemph_fx_32( buf2_fx, PREEMPH_FAC_16k, input_frame, &hStereoTCA->memdecim_fx[1] );
413 :
414 1228467 : FOR( i = 0; i < ( input_frame / dsFac1 ); i++ )
415 : {
416 1224640 : tempBuf1_fx[i] = buf1_fx[i * dsFac1]; /*Qx*/
417 1224640 : move32();
418 1224640 : tempBuf2_fx[i] = buf2_fx[i * dsFac1]; /*Qx*/
419 1224640 : move32();
420 : }
421 :
422 : /* De-emphasis, 1/(1-mu z^-1), and resample, stage 2 */
423 3827 : deemph_fx_32( tempBuf1_fx, PREEMPH_FAC_16k, idiv1616( input_frame, dsFac1 ), &hStereoTCA->memdecim_fx[2] );
424 3827 : deemph_fx_32( tempBuf2_fx, PREEMPH_FAC_16k, idiv1616( input_frame, dsFac1 ), &hStereoTCA->memdecim_fx[3] );
425 :
426 616147 : FOR( i = 0; i < ( input_frame / dsFactor ); i++ )
427 : {
428 612320 : chan1_fx[i] = tempBuf1_fx[i * dsFac2]; /*Qx*/
429 612320 : move32();
430 612320 : chan2_fx[i] = tempBuf2_fx[i * dsFac2]; /*Qx*/
431 612320 : move32();
432 : }
433 :
434 3827 : spectral_balancer_fx( chan1_fx, &hStereoTCA->memdecim_fx[4], idiv1616( input_frame, dsFactor ), 0 ); /*4 mem */
435 3827 : spectral_balancer_fx( chan2_fx, &hStereoTCA->memdecim_fx[8], idiv1616( input_frame, dsFactor ), 0 ); /*4 mem */
436 :
437 3827 : return;
438 : }
439 : /*---------------------------------------------------------------
440 : * utilCrossCorr_mod()
441 : *
442 : * Biased crossCorr estimation between buf1, buf2 over the
443 : * lag range of (lagSearchRange[0], lagSearchRange[1]).
444 : * ---------------------------------------------------------------*/
445 3827 : static void utilCrossCorr_mod_fx(
446 : STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */
447 : Word32 *buf1, /*q_com*/
448 : Word32 *buf2, /*q_com*/
449 : const Word16 q_com,
450 : Word32 *corrEst, /* o : correlation estimate Q31-corrEst_Exp*/
451 : Word16 *corrEst_Exp, /* o : correlation estimate Q31-corrEst_Exp*/
452 : const Word16 *lagSearchRange, /*Q0*/
453 : const Word16 len /*Q0*/ )
454 : {
455 : Word32 C, E1, E2, C_C_mem;
456 : Word16 i, j, E1_exp, E2_exp, Inv_Tot_E_exp, k, C_exp, exp, gb;
457 : Word16 Inv_Tot_E, corrEst_exp[2 * L_NCSHIFT_DS + 1];
458 : Word64 L64_sum;
459 :
460 3827 : set16_fx( corrEst_exp, -1000, 2 * L_NCSHIFT_DS + 1 );
461 3827 : E1_exp = sub( 31, q_com );
462 3827 : E2_exp = sub( 31, q_com );
463 :
464 3827 : gb = 0;
465 3827 : move16();
466 3827 : IF( LT_16( L_norm_arr( buf1, len ), 2 ) )
467 : {
468 0 : gb = 2;
469 0 : move16();
470 : }
471 3827 : E1 = sum2_32_exp_fx( buf1, len, &E1_exp, gb ); /* Q31-E1_exp */
472 :
473 3827 : gb = 0;
474 3827 : move16();
475 3827 : IF( LT_16( L_norm_arr( buf2, len ), 2 ) )
476 : {
477 0 : gb = 2;
478 0 : move16();
479 : }
480 3827 : E2 = sum2_32_exp_fx( buf2, len, &E2_exp, gb ); /* Q31-E2_exp */
481 :
482 : Word16 temp1, temp2;
483 3827 : Word32 E1_mul = BASOP_Util_Add_Mant32Exp( E1, E1_exp, hStereoTCA->E1_mem_fx, hStereoTCA->E1_mem_exp, &temp1 ); /* Q31-temp1 */
484 3827 : Word32 E2_mul = BASOP_Util_Add_Mant32Exp( E2, E2_exp, hStereoTCA->E2_mem_fx, hStereoTCA->E2_mem_exp, &temp2 ); /* Q31-temp2 */
485 3827 : Word32 sqr_inp = Mpy_32_32( E1_mul, E2_mul );
486 3827 : Word16 sq_exp = add( temp1, temp2 );
487 :
488 3827 : IF( sqr_inp )
489 : {
490 3827 : sqr_inp = Sqrt32( sqr_inp, &sq_exp ); /* Q31-sq_exp */
491 3827 : sqr_inp = Mpy_32_32( sqr_inp, 1342177280 /* 320 in Q22*/ ); /* Q31-sq_exp+22-31 */
492 3827 : sq_exp = add( sq_exp, 9 );
493 3827 : Inv_Tot_E = BASOP_Util_Divide3232_Scale( ONE_IN_Q31, sqr_inp, &Inv_Tot_E_exp ); /* Q15-Inv_Tot_E_exp */
494 3827 : Inv_Tot_E_exp = add( Inv_Tot_E_exp, sub( 0, sq_exp ) );
495 : }
496 : ELSE
497 : {
498 0 : Inv_Tot_E = 25088; /* 98.82 in Q8 */
499 0 : move16();
500 0 : Inv_Tot_E_exp = 7;
501 0 : move16();
502 : }
503 :
504 3827 : hStereoTCA->E1_mem_fx = E1; /* Q31-E1_exp */
505 3827 : move32();
506 3827 : hStereoTCA->E2_mem_fx = E2; /* Q31-E2_exp */
507 3827 : move32();
508 3827 : hStereoTCA->E1_mem_exp = E1_exp;
509 3827 : move16();
510 3827 : hStereoTCA->E2_mem_exp = E2_exp;
511 3827 : move16();
512 3827 : *corrEst_Exp = corrEst_exp[0];
513 3827 : move16();
514 :
515 160734 : FOR( ( i = lagSearchRange[0], j = 0 ); i <= 0; ( i++, j++ ) )
516 : {
517 156907 : L64_sum = 1;
518 156907 : move64();
519 25262027 : FOR( k = 0; k < len; k++ )
520 : {
521 25105120 : L64_sum = W_mac_32_32( L64_sum, buf1[k], buf2[k + i] ); /* 2*q_com+1 */
522 : }
523 156907 : k = W_norm( L64_sum );
524 156907 : L64_sum = W_shl( L64_sum, k ); /* 2*q_com+1+k */
525 156907 : C = W_extract_h( L64_sum ); // ener_side_q
526 156907 : C_exp = sub( 31, sub( add( add( shl( q_com, 1 ), 1 ), k ), 32 ) );
527 156907 : C_C_mem = BASOP_Util_Add_Mant32Exp( C, C_exp, hStereoTCA->C_mem_fx[j], hStereoTCA->C_mem_exp[j], &exp ); /* Q31-exp */
528 156907 : corrEst[j] = Mpy_32_16_1( C_C_mem, Inv_Tot_E ); /* Q31-corrEst_exp */
529 156907 : move32();
530 156907 : corrEst_exp[j] = add( Inv_Tot_E_exp, exp );
531 156907 : move16();
532 156907 : *corrEst_Exp = s_max( *corrEst_Exp, corrEst_exp[j] );
533 156907 : move16();
534 156907 : hStereoTCA->C_mem_fx[j] = C;
535 156907 : move32();
536 156907 : hStereoTCA->C_mem_exp[j] = C_exp;
537 156907 : move16();
538 : }
539 :
540 156907 : FOR( ; i <= lagSearchRange[1]; ( i++, j++ ) )
541 : {
542 153080 : L64_sum = 1;
543 153080 : move64();
544 24645880 : FOR( k = 0; k < len; k++ )
545 : {
546 24492800 : L64_sum = W_mac_32_32( L64_sum, buf1[k - i], buf2[k] ); /* 2*q_com+1 */
547 : }
548 153080 : k = W_norm( L64_sum );
549 153080 : L64_sum = W_shl( L64_sum, k ); /* 2*q_com+1+k */
550 153080 : C = W_extract_h( L64_sum ); // ener_side_q
551 153080 : C_exp = sub( 31, sub( add( add( shl( q_com, 1 ), 1 ), k ), 32 ) );
552 153080 : C_C_mem = BASOP_Util_Add_Mant32Exp( C, C_exp, hStereoTCA->C_mem_fx[j], hStereoTCA->C_mem_exp[j], &exp ); /* Q31-exp */
553 153080 : corrEst[j] = Mpy_32_16_1( C_C_mem, Inv_Tot_E ); /* Q31-corrEst_exp */
554 153080 : move32();
555 153080 : corrEst_exp[j] = add( Inv_Tot_E_exp, exp );
556 153080 : move16();
557 153080 : *corrEst_Exp = s_max( *corrEst_Exp, corrEst_exp[j] );
558 153080 : move16();
559 153080 : hStereoTCA->C_mem_fx[j] = C;
560 153080 : move32();
561 153080 : hStereoTCA->C_mem_exp[j] = C_exp;
562 153080 : move16();
563 : }
564 :
565 : /* Rescaling buffers */
566 :
567 313814 : FOR( i = 0; i < ( 2 * L_NCSHIFT_DS + 1 ); i++ )
568 : {
569 309987 : corrEst[i] = L_shl( corrEst[i], sub( corrEst_exp[i], *corrEst_Exp ) ); /* Q31-corrEst_Exp */
570 309987 : move32();
571 : }
572 :
573 3827 : return;
574 : }
575 : /*---------------------------------------------------------------
576 : * utilCrossCorr()
577 : *
578 : * crossCorr estimation between buf1, buf2 over the
579 : * lag range of (lagSearchRange[0], lagSearchRange[1]).
580 : * ---------------------------------------------------------------*/
581 243 : static void utilCrossCorr_fx(
582 : const Word32 *buf1, // buf1_q
583 : Word16 buf1_q,
584 : const Word32 *buf2, // buf2_q
585 : Word16 buf2_q,
586 : const Word32 *win, /*Qx*/
587 : Word32 *corrEst, /* o : correlation estimate corrEst_e */
588 : Word16 *corrEst_e,
589 : const Word16 *lagSearchRange, /*Q0*/
590 : const Word16 len, /*Q0*/
591 : const Word16 winSymmFlag /*Q0*/ )
592 : {
593 : Word32 tempBuf1[L_FRAME48k];
594 : Word32 tempBuf2[L_FRAME48k];
595 : Word32 temp, scale;
596 : Word16 res_e, tmp_e;
597 : Word64 L64_sum;
598 : Word16 i, j, k;
599 : Word16 corrEstTemp_e[N_MAX_SHIFT_CHANGE + 1];
600 243 : Word16 max_e = MIN16B;
601 243 : move16();
602 :
603 243 : Word16 gb1 = s_max( 0, sub( find_guarded_bits_fx( len ), getScaleFactor32( buf1, len ) ) );
604 243 : Word16 gb2 = s_max( 0, sub( find_guarded_bits_fx( len ), getScaleFactor32( buf2, len ) ) );
605 :
606 : /* Apply windowing */
607 243 : IF( win != NULL )
608 : {
609 0 : IF( EQ_16( winSymmFlag, 0 ) )
610 : {
611 0 : v_mult_fixed( buf1, win, tempBuf1, len );
612 0 : v_mult_fixed( buf2, win, tempBuf2, len );
613 : }
614 : ELSE
615 : {
616 0 : v_mult_fixed( buf1, win, tempBuf1, ( len >> 1 ) );
617 0 : v_mult_fixed( buf2, win, tempBuf2, ( len >> 1 ) );
618 :
619 0 : FOR( i = shr( len, 1 ); i < len; i++ )
620 : {
621 0 : tempBuf1[i] = Mpy_32_32( win[len - 1 - i], buf1[i] ); /* Qx+buf1_q-31 */
622 0 : move32();
623 0 : tempBuf2[i] = Mpy_32_32( win[len - 1 - i], buf2[i] ); /* Qx+buf2_q-31 */
624 0 : move32();
625 : }
626 : }
627 : }
628 : ELSE
629 : {
630 243 : Copy32( buf1, tempBuf1, len ); /* buf1_q */
631 243 : Copy32( buf2, tempBuf2, len ); /* buf2_q */
632 : }
633 :
634 243 : Word16 temp1_e = sub( Q31, buf1_q );
635 243 : Word16 temp2_e = sub( Q31, buf2_q );
636 :
637 243 : temp = sum2_32_exp_fx( tempBuf1, len, &temp1_e, gb1 ); // temp1_e
638 243 : temp = Mpy_32_32( temp, sum2_32_exp_fx( tempBuf2, len, &temp2_e, gb2 ) ); // temp2_e
639 243 : temp2_e = add( temp1_e, temp2_e );
640 :
641 243 : IF( temp == 0 )
642 : {
643 0 : scale = MAXVAL_WORD32;
644 0 : move32();
645 : }
646 : ELSE
647 : {
648 243 : scale = ISqrt32( temp, &temp2_e ); // temp2_e
649 : }
650 :
651 : /* starting point of lag search range should be less than the ending point */
652 243 : assert( lagSearchRange[0] <= lagSearchRange[1] );
653 :
654 : /* first part of noncausal corr est. */
655 413 : FOR( ( i = lagSearchRange[0], j = 0 ); i <= s_min( 0, lagSearchRange[1] ); ( i++, j++ ) )
656 : {
657 170 : L64_sum = 0;
658 170 : move64();
659 109748 : FOR( k = 0; k < ( len + i ); k++ )
660 : {
661 109578 : L64_sum = W_mac_32_32( L64_sum, buf1[k - i], buf2[k] ); /* buf1_q+buf2_q+1 */
662 : }
663 170 : k = W_norm( L64_sum );
664 170 : L64_sum = W_shl( L64_sum, k ); /* buf1_q+buf2_q+1+k */
665 170 : temp = W_extract_h( L64_sum ); /* buf1_q+buf2_q+1+k-32 */
666 170 : res_e = sub( 31, sub( add( add( add( buf1_q, buf2_q ), 1 ), k ), 32 ) );
667 :
668 170 : corrEst[j] = L_deposit_h( BASOP_Util_Divide3216_Scale( temp, ( len + i ), &tmp_e ) ); /* Q31-max_e */
669 170 : move32();
670 170 : corrEstTemp_e[j] = add( tmp_e, sub( res_e, 15 ) );
671 170 : move16();
672 170 : max_e = s_max( max_e, corrEstTemp_e[j] );
673 : }
674 :
675 : /* second part of noncausal corr est. */
676 660 : FOR( ; i <= lagSearchRange[1]; ( i++, j++ ) )
677 : {
678 417 : L64_sum = 1;
679 417 : move64();
680 251229 : FOR( k = 0; k < sub( len, i ); k++ )
681 : {
682 250812 : L64_sum = W_mac_32_32( L64_sum, buf1[k], buf2[k + i] ); /* buf1_q+buf2_q+1 */
683 : }
684 417 : k = W_norm( L64_sum );
685 417 : L64_sum = W_shl( L64_sum, k ); /* buf1_q+buf2_q+1+k */
686 417 : temp = W_extract_h( L64_sum ); /* buf1_q+buf2_q+1+k-32 */
687 417 : res_e = sub( 31, sub( add( add( add( buf1_q, buf2_q ), 1 ), k ), 32 ) );
688 :
689 417 : corrEst[j] = L_deposit_h( BASOP_Util_Divide3216_Scale( temp, ( len - i ), &tmp_e ) ); /* Q31-max_e */
690 417 : move32();
691 417 : corrEstTemp_e[j] = add( tmp_e, sub( res_e, 15 ) );
692 417 : move16();
693 417 : max_e = s_max( max_e, corrEstTemp_e[j] );
694 417 : move16();
695 : }
696 :
697 :
698 830 : FOR( i = 0; i < j; i++ )
699 : {
700 587 : corrEst[i] = L_shr( corrEst[i], sub( max_e, corrEstTemp_e[i] ) ); /* Q31-corrEstTemp_e */
701 587 : move32();
702 : }
703 :
704 243 : *corrEst_e = max_e;
705 243 : move16();
706 243 : v_multc_fixed( corrEst, scale, corrEst, j );
707 243 : *corrEst_e = add( *corrEst_e, temp2_e );
708 243 : move16();
709 :
710 243 : return;
711 : }
712 : /*---------------------------------------------------------------
713 : * corrStatsEst()
714 : *
715 : * Non-causal shift estimation to encode future samples.
716 : * ---------------------------------------------------------------*/
717 :
718 11535 : static Word16 TRUNC_FX( Word32 inp /*Q31-exp*/, Word16 exp )
719 : {
720 : Word16 ouptut;
721 : Word32 temp;
722 :
723 11535 : temp = L_shr( inp, sub( 31, exp ) ); /*Q0*/
724 11535 : test();
725 11535 : IF( GT_32( temp, 32767 ) || LT_32( temp, -32768 ) )
726 : {
727 0 : test();
728 0 : IF( temp < 0 )
729 : {
730 0 : ouptut = -32768; /*Q0*/
731 : }
732 : ELSE
733 : {
734 0 : ouptut = 32767; /*Q0*/
735 : }
736 0 : move16();
737 : }
738 : ELSE
739 : {
740 11535 : IF( NE_32( temp, L_shl_sat( 1, sub( 31, exp ) ) ) )
741 : {
742 11535 : Word32 temp1 = L_add_sat( inp, L_shl_sat( 1, sub( 31, add( exp, 1 ) ) ) ); /* Q31-exp */
743 11535 : ouptut = extract_l( L_shr( temp1, sub( 31, exp ) ) ); /*Q0*/
744 :
745 11535 : IF( temp < 0 )
746 : {
747 6456 : ouptut = add( ouptut, 1 ); /*Q0*/
748 : }
749 : }
750 : ELSE
751 : {
752 0 : ouptut = extract_l( temp ); /*Q0*/
753 0 : move16();
754 : }
755 : }
756 11535 : return ouptut; /*Q0*/
757 : }
758 3827 : static void corrStatsEst_fx(
759 : STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo TCA Encoder handle */
760 : Word32 *buf1_fx, /* i : channel 1 q_com*/
761 : Word32 *buf2_fx, /* i : channel 2 q_com*/
762 : Word16 q_com,
763 : const Word16 bufLenDS, /* i : buffer length Q0*/
764 : const Word16 dsFactor, /* i : buffer length Q0*/
765 : const Word16 vad_flag1, /* i : VAD flag channel 1 Q0*/
766 : const Word16 vad_flag2, /* i : VAD flag channel 2 Q0*/
767 : STEREO_CLASSIF_HANDLE hStereoClassif /* i/o: stereo classifier handle */
768 : )
769 : {
770 : Word16 lagSearchRange[2];
771 : Word32 corrEst_fx[2 * L_NCSHIFT_DS + 1];
772 : Word16 corrLagStats[3];
773 : Word32 *tempRK_fx;
774 : const Word32 *winInterp_fx;
775 : Word32 rInterp_fx[MAX_INTERPOLATE];
776 : Word16 rInterp_exp[MAX_INTERPOLATE];
777 : Word16 interpMin, interpMax, interpLen;
778 : Word16 i, j, k, m;
779 : Word16 win_bias_fx;
780 : Word16 tempLen, win_width;
781 : Word16 loc_weight_win_fx[4 * L_NCSHIFT_DS + 1];
782 : Word32 X_hat_fx, Y_hat_fx, XY_hat_fx, X_SQR_hat_fx;
783 : Word32 alpha_reg_fx, beta_reg_fx, reg_prv_corr_fx, dist_reg_prv_corr_fx, bias_par_fx, width_par_fx;
784 : Word16 alpha_reg_exp, beta_reg_exp, reg_prv_corr_exp, dist_reg_prv_corr_exp, bias_par_exp, width_par_exp;
785 :
786 : Word16 alpha_fx;
787 : Word16 k1_fx, k2_fx;
788 : Word32 temp_A_fx, temp_B_fx, tempF_fx;
789 : Word16 stmp;
790 : Word32 corrEst_ncorr_fx, temp32;
791 : Word16 corrEst_exp, corrEst_ncorr_exp, temp;
792 : Word16 X_hat_exp, Y_hat_exp, XY_hat_exp, X_SQR_hat_exp, exp;
793 :
794 : /* init of regression parameters*/
795 3827 : X_hat_fx = 0;
796 3827 : move32();
797 3827 : X_hat_exp = 0;
798 3827 : move16();
799 3827 : X_SQR_hat_fx = 0;
800 3827 : move32();
801 3827 : X_SQR_hat_exp = 0;
802 3827 : move16();
803 3827 : XY_hat_fx = 0;
804 3827 : move32();
805 3827 : XY_hat_exp = 0;
806 3827 : move16();
807 :
808 : /* Initializations */
809 3827 : alpha_fx = 22938; /* 0.7 in Q15*/
810 3827 : move16();
811 3827 : lagSearchRange[0] = -L_NCSHIFT_DS;
812 3827 : move16();
813 3827 : lagSearchRange[1] = L_NCSHIFT_DS;
814 3827 : move16();
815 3827 : tempLen = ( 2 * L_NCSHIFT_DS + 1 );
816 3827 : move16();
817 :
818 3827 : set16_fx( corrLagStats, 0, 3 );
819 :
820 : /* First iteration of xcorr estimation */
821 3827 : utilCrossCorr_mod_fx( hStereoTCA, buf1_fx, buf2_fx, q_com, corrEst_fx, &corrEst_exp, lagSearchRange, sub( bufLenDS, L_XCORRMEM_DS ) );
822 :
823 : /* calculate features for the UNCLR classifier */
824 3827 : unclr_calc_corr_features_fx( hStereoClassif, hStereoTCA, buf1_fx, buf2_fx, q_com, sub( bufLenDS, L_XCORRMEM_DS ), corrEst_fx, corrEst_exp, lagSearchRange, &corrEst_ncorr_fx, &corrEst_ncorr_exp );
825 :
826 11481 : FOR( i = 1; i < 3; i++ )
827 : {
828 7654 : v_add_32( hStereoTCA->corrEstPrev_fx[i], hStereoTCA->corrEstPrev_fx[0], hStereoTCA->corrEstPrev_fx[0], tempLen );
829 : }
830 :
831 : /* back up the corrEst */
832 11481 : FOR( i = 0; i < 2; i++ )
833 : {
834 7654 : Copy32( hStereoTCA->corrEstPrev_fx[i + 1], hStereoTCA->corrEstPrev_fx[i], tempLen ); /* Q31-hStereoTCA->corrEstPrev_exp */
835 : }
836 :
837 3827 : temp = getScaleFactor32( corrEst_fx, 2 * L_NCSHIFT_DS + 1 );
838 3827 : scale_sig32( corrEst_fx, 2 * L_NCSHIFT_DS + 1, temp ); /* Q31-corrEst_exp */
839 3827 : corrEst_exp = sub( corrEst_exp, temp );
840 :
841 3827 : Copy32( corrEst_fx, hStereoTCA->corrEstPrev_fx[2], tempLen ); /* Q31-corrEst_exp */
842 3827 : hStereoTCA->corrEstPrev_exp = corrEst_exp;
843 3827 : move16();
844 3827 : Word16 gb = find_guarded_bits_fx( 2 * L_NCSHIFT_DS + 1 );
845 :
846 3827 : scale_sig32( hStereoTCA->corrEstPrev_fx[2], 2 * L_NCSHIFT_DS + 1, -gb ); /* Q31-hStereoTCA->corrEstPrev_exp-1 */
847 3827 : hStereoTCA->corrEstPrev_exp = add( hStereoTCA->corrEstPrev_exp, gb );
848 3827 : move16();
849 : Word32 buf1_fx_temp[L_FRAME_DS];
850 : Word32 buf2_fx_temp[L_FRAME_DS];
851 :
852 3827 : Copy32( buf1_fx, buf1_fx_temp, L_FRAME_DS ); /* q_com */
853 3827 : Copy32( buf2_fx, buf2_fx_temp, L_FRAME_DS ); /* q_com */
854 :
855 3827 : scale_sig32( buf1_fx_temp, L_FRAME_DS, -4 ); /* q_com-4 */
856 3827 : scale_sig32( buf2_fx_temp, L_FRAME_DS, -4 ); /* q_com-4 */
857 :
858 3827 : temp_A_fx = L_add( sumAbs_fx( buf1_fx_temp, L_FRAME_DS - L_XCORRMEM_DS ), sumAbs_fx( buf2_fx_temp, L_FRAME_DS - L_XCORRMEM_DS ) );
859 3827 : temp_B_fx = L_add( sumAbs_fx( buf1_fx_temp + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ), sumAbs_fx( buf2_fx_temp + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ) );
860 :
861 3827 : tempF_fx = BASOP_Util_Add_Mant32Exp( L_add( temp_A_fx, temp_B_fx ), sub( 31, sub( q_com, 4 ) ), hStereoTCA->mem_tempF_fx, hStereoTCA->mem_tempF_exp, &temp ); /* Q31-tempF_exp */
862 3827 : Word16 tempF_exp = temp;
863 3827 : hStereoTCA->mem_tempF_fx = temp_B_fx; /* Q31-hStereoTCA->mem_tempF_exp */
864 3827 : move32();
865 3827 : hStereoTCA->mem_tempF_exp = sub( 31, sub( q_com, 4 ) );
866 3827 : move16();
867 :
868 3827 : alpha_fx = 30474 /* 0.93f in Q15*/;
869 3827 : move16();
870 3827 : IF( BASOP_Util_Add_Mant32Exp( tempF_fx, tempF_exp, -hStereoTCA->ica_envVarLT_fx, add( hStereoTCA->ica_envVarLT_exp, 2 ), &temp ) > 0 )
871 : {
872 127 : alpha_fx = 27197 /* 0.83f in Q15*/;
873 : }
874 3700 : ELSE IF( BASOP_Util_Add_Mant32Exp( tempF_fx, tempF_exp, -hStereoTCA->ica_envVarLT_fx, add( hStereoTCA->ica_envVarLT_exp, 1 ), &temp ) > 0 )
875 : {
876 323 : alpha_fx = 27853 /* 0.85f in Q15*/;
877 : }
878 3377 : ELSE IF( BASOP_Util_Add_Mant32Exp( tempF_fx, tempF_exp, -hStereoTCA->ica_envVarLT_fx, hStereoTCA->ica_envVarLT_exp, &temp ) > 0 )
879 : {
880 1088 : alpha_fx = 29491 /* 0.9f in Q15*/;
881 : }
882 3827 : move16();
883 3827 : hStereoTCA->corrStatsSmoothFac_fx = alpha_fx;
884 3827 : move32();
885 :
886 : /* long term corr Stats estimation */
887 3827 : v_multc_fixed_16( hStereoTCA->corrEstLT_fx, alpha_fx, hStereoTCA->corrEstLT_fx, 2 * L_NCSHIFT_DS + 1 ); /* Q31-hStereoTCA->corrEstLT_exp */
888 3827 : v_multc_fixed_16( corrEst_fx, sub( MAX_16, alpha_fx ), corrEst_fx, 2 * L_NCSHIFT_DS + 1 ); /* Q31-corrEst_exp */
889 3827 : v_add_fixed_me( hStereoTCA->corrEstLT_fx, hStereoTCA->corrEstLT_exp, corrEst_fx, corrEst_exp, hStereoTCA->corrEstLT_fx, &hStereoTCA->corrEstLT_exp, 2 * L_NCSHIFT_DS + 1, 0 );
890 :
891 3827 : hStereoTCA->ica_envVarLT_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( hStereoTCA->ica_envVarLT_fx, SMOOTH_ENV_FACTOR_FX_Q15 ), hStereoTCA->ica_envVarLT_exp, Mpy_32_16_1( tempF_fx, ONE_IN_Q15 - SMOOTH_ENV_FACTOR_FX_Q15 ), tempF_exp, &hStereoTCA->ica_envVarLT_exp ); // SMOOTH_ENV_FACTOR_FX_Q15 (Q31-hStereoTCA->ica_envVarLT_exp)
892 3827 : move32();
893 :
894 3827 : Copy32( hStereoTCA->corrEstLT_fx, corrEst_fx, 2 * L_NCSHIFT_DS + 1 ); /* Q31-hStereoTCA->corrEstLT_exp */
895 3827 : corrEst_exp = hStereoTCA->corrEstLT_exp;
896 3827 : move16();
897 :
898 3827 : Y_hat_fx = hStereoTCA->delay_0_mem_fx[0]; /* Q31-hStereoTCA->delay_0_mem_exp */
899 3827 : move32();
900 3827 : Y_hat_exp = hStereoTCA->delay_0_mem_exp;
901 3827 : move16();
902 :
903 : /* Note: keep X_hat and X_SQR_hat calculations inside the loop to allow future tuning of MAX_DELAYREGLEN */
904 45924 : FOR( i = 1; i < MAX_DELAYREGLEN; i++ )
905 : {
906 42097 : X_hat_fx = BASOP_Util_Add_Mant32Exp( X_hat_fx, X_hat_exp, L_shl( i, 27 ), 4, &X_hat_exp ); /* Q31-X_hat_exp */
907 42097 : Y_hat_fx = BASOP_Util_Add_Mant32Exp( Y_hat_fx, Y_hat_exp, hStereoTCA->delay_0_mem_fx[i], hStereoTCA->delay_0_mem_exp, &Y_hat_exp ); /* Q31-Y_hat_exp */
908 42097 : XY_hat_fx = BASOP_Util_Add_Mant32Exp( XY_hat_fx, XY_hat_exp, Mpy_32_32( hStereoTCA->delay_0_mem_fx[i], L_shl( i, 27 ) ), add( 4, hStereoTCA->delay_0_mem_exp ), &XY_hat_exp ); /* Q31-XY_hat_exp */
909 42097 : X_SQR_hat_fx = BASOP_Util_Add_Mant32Exp( X_SQR_hat_fx, X_SQR_hat_exp, Mpy_32_32( L_shl( i, 27 ), L_shl( i, 27 ) ), 8, &X_SQR_hat_exp ); /* Q31-X_SQR_hat_exp */
910 : }
911 :
912 3827 : X_hat_fx = Mpy_32_16_1( X_hat_fx, INV_MAX_DELAYREGLEN_FX_Q15 ); /* Q31-X_hat_exp */
913 3827 : Y_hat_fx = Mpy_32_16_1( Y_hat_fx, INV_MAX_DELAYREGLEN_FX_Q15 ); /* Q31-Y_hat_exp */
914 3827 : XY_hat_fx = Mpy_32_16_1( XY_hat_fx, INV_MAX_DELAYREGLEN_FX_Q15 ); /* Q31-XY_hat_exp */
915 3827 : X_SQR_hat_fx = Mpy_32_16_1( X_SQR_hat_fx, INV_MAX_DELAYREGLEN_FX_Q15 ); /* Q31-X_SQR_hat_exp */
916 :
917 3827 : beta_reg_fx = 0;
918 3827 : move32();
919 3827 : beta_reg_exp = 0;
920 3827 : move16();
921 3827 : tempF_fx = BASOP_Util_Add_Mant32Exp( X_SQR_hat_fx, X_SQR_hat_exp, L_negate( Mpy_32_32( X_hat_fx, X_hat_fx ) ), shl( X_hat_exp, 1 ), &tempF_exp ); /* Q31-tempF_exp */
922 :
923 3827 : IF( tempF_fx != 0 )
924 : {
925 3827 : temp32 = BASOP_Util_Add_Mant32Exp( XY_hat_fx, XY_hat_exp, L_negate( Mpy_32_32( X_hat_fx, Y_hat_fx ) ), add( X_hat_exp, Y_hat_exp ), &exp ); /* Q31-exp */
926 3827 : beta_reg_fx = BASOP_Util_Divide3232_Scale_newton( temp32, tempF_fx, &beta_reg_exp ); /* Q31-beta_reg_exp */
927 3827 : if ( beta_reg_fx )
928 : {
929 3603 : beta_reg_exp = add( beta_reg_exp, sub( exp, tempF_exp ) );
930 : }
931 : }
932 :
933 3827 : alpha_reg_fx = BASOP_Util_Add_Mant32Exp( Y_hat_fx, Y_hat_exp, L_negate( Mpy_32_32( X_hat_fx, beta_reg_fx ) ), add( X_hat_exp, beta_reg_exp ), &alpha_reg_exp ); /* Q31-alpha_reg_exp */
934 3827 : reg_prv_corr_fx = BASOP_Util_Add_Mant32Exp( alpha_reg_fx, alpha_reg_exp, Mpy_32_32( beta_reg_fx, L_shl( MAX_DELAYREGLEN, 27 ) ), add( 4, beta_reg_exp ), ®_prv_corr_exp ); /* Q31-reg_prv_corr_exp */
935 :
936 3827 : reg_prv_corr_fx = L_shr( reg_prv_corr_fx, 1 );
937 3827 : reg_prv_corr_exp = add( reg_prv_corr_exp, 1 );
938 3827 : IF( LE_16( TRUNC_FX( reg_prv_corr_fx, reg_prv_corr_exp ), -L_NCSHIFT_DS ) )
939 : {
940 0 : reg_prv_corr_fx = -L_NCSHIFT_DS + 1;
941 0 : move32();
942 0 : reg_prv_corr_exp = 31;
943 0 : move16();
944 : }
945 :
946 3827 : IF( GE_16( TRUNC_FX( reg_prv_corr_fx, reg_prv_corr_exp ), L_NCSHIFT_DS ) )
947 : {
948 2 : reg_prv_corr_fx = L_NCSHIFT_DS - 1;
949 2 : move32();
950 2 : reg_prv_corr_exp = 31;
951 2 : move16();
952 : }
953 :
954 3827 : bias_par_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( hStereoTCA->smooth_dist_reg_prv_corr_fx, A_BIAS_FX_Q15 ), hStereoTCA->smooth_dist_reg_prv_corr_exp, L_shl( B_BIAS_FX_Q15, Q16 ), 0, &bias_par_exp ); /* Q31-bias_par_exp */
955 :
956 3827 : Word32 XH_BIAS_tmp = L_shl( XH_BIAS_FX_Q15, Q16 ); /* Q31 */
957 3827 : Word32 XL_BIAS_tmp = L_shl( XL_BIAS_FX_Q15, Q16 ); /* Q31 */
958 :
959 3827 : IF( bias_par_exp < 0 )
960 : {
961 3544 : bias_par_fx = L_shl( bias_par_fx, bias_par_exp ); /* Q31 */
962 3544 : bias_par_exp = 0;
963 3544 : move16();
964 : }
965 : ELSE
966 : {
967 283 : XH_BIAS_tmp = L_shr( XH_BIAS_tmp, bias_par_exp ); /* Q31-bias_par_exp */
968 283 : XL_BIAS_tmp = L_shr( XL_BIAS_tmp, bias_par_exp ); /* Q31-bias_par_exp */
969 : }
970 :
971 3827 : bias_par_fx = L_min( bias_par_fx, XH_BIAS_tmp );
972 3827 : bias_par_fx = L_max( bias_par_fx, XL_BIAS_tmp );
973 3827 : bias_par_fx = L_shr( bias_par_fx, bias_par_exp );
974 3827 : bias_par_exp = 0;
975 3827 : move16();
976 :
977 3827 : width_par_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hStereoTCA->smooth_dist_reg_prv_corr_fx, A_WIDTH_FX_Q31 ), hStereoTCA->smooth_dist_reg_prv_corr_exp, B_WIDTH_FX_Q31, 0, &width_par_exp ); /* Q31-width_par_exp */
978 3827 : Word32 XH_WIDTH_tmp = L_shl( XH_WIDTH_FX_Q15, Q16 ); /* Q31 */
979 3827 : Word32 XL_WIDTH_tmp = L_shl( XL_WIDTH_FX_Q15, Q16 ); /* Q31 */
980 :
981 3827 : IF( width_par_exp < 0 )
982 : {
983 3827 : width_par_fx = L_shl( width_par_fx, width_par_exp ); /* Q31 */
984 3827 : width_par_exp = 0;
985 3827 : move16();
986 : }
987 : ELSE
988 : {
989 0 : XH_WIDTH_tmp = L_shr( XH_WIDTH_tmp, width_par_exp );
990 0 : XL_WIDTH_tmp = L_shr( XL_WIDTH_tmp, width_par_exp );
991 : }
992 3827 : width_par_fx = L_min( width_par_fx, XH_WIDTH_tmp );
993 3827 : width_par_fx = L_max( width_par_fx, XL_WIDTH_tmp );
994 3827 : width_par_fx = L_shl( width_par_fx, width_par_exp );
995 3827 : width_par_exp = 0;
996 3827 : move16();
997 :
998 3827 : win_width = (Word16) L_shr( Mpy_32_32( width_par_fx, 1350565888 /* ( 4L_NCSHIFT_DS + 1 ) in Q23 */ ), sub( 31, add( width_par_exp, 8 ) ) ); /* Q23-(31-(width_par_exp-8)) */
999 :
1000 3827 : win_bias_fx = round_fx( bias_par_fx ); // Q15
1001 :
1002 3827 : k1_fx = add( MAX_16 >> 1, shr( win_bias_fx, 1 ) ); // Q15
1003 3827 : k2_fx = sub( MAX_16 >> 1, shr( win_bias_fx, 1 ) ); // Q15
1004 :
1005 160373 : FOR( i = 0; i < ( 2 * L_NCSHIFT_DS - ( win_width * 2 ) ); i++ )
1006 : {
1007 156546 : loc_weight_win_fx[i] = win_bias_fx; // Q15
1008 156546 : move16();
1009 : }
1010 :
1011 306882 : FOR( i = ( 2 * L_NCSHIFT_DS - ( win_width * 2 ) ); i <= ( 2 * L_NCSHIFT_DS + ( win_width * 2 ) ); i++ )
1012 : {
1013 303055 : Word16 cos_inp = BASOP_Util_Divide1616_Scale( sub( i, 2 * L_NCSHIFT_DS ), shl( win_width, 1 ), &exp ); /* Q15-exp */
1014 303055 : cos_inp = shr_sat( cos_inp, sub( 0, exp ) );
1015 303055 : cos_inp = getCosWord16R2( shr( cos_inp, 1 ) ); // Q15
1016 303055 : loc_weight_win_fx[i] = add( k1_fx, mult( k2_fx, cos_inp ) ); // Q15
1017 303055 : move16();
1018 : }
1019 :
1020 164200 : FOR( i = ( 2 * L_NCSHIFT_DS + ( win_width * 2 ) ); i < ( 4 * L_NCSHIFT_DS + 1 ); i++ )
1021 : {
1022 160373 : loc_weight_win_fx[i] = win_bias_fx; // Q15
1023 160373 : move16();
1024 : }
1025 3827 : reg_prv_corr_fx = L_shr( reg_prv_corr_fx, 1 );
1026 3827 : reg_prv_corr_exp = add( reg_prv_corr_exp, 1 );
1027 3827 : Word16 x = TRUNC_FX( reg_prv_corr_fx, reg_prv_corr_exp ); /* Q0 */
1028 3827 : move16();
1029 313814 : for ( i = 0, j = ( L_NCSHIFT_DS - x ); i < 2 * L_NCSHIFT_DS + 1; i++, j++ )
1030 : {
1031 309987 : corrEst_fx[i] = Mpy_32_16_1( corrEst_fx[i], loc_weight_win_fx[j] ); /* Q31-corrEst_exp */
1032 309987 : move32();
1033 : }
1034 3827 : test();
1035 3827 : test();
1036 3827 : IF( LT_32( hStereoTCA->prevTargetGain_fx, 429496730 /*0.8f in Q29*/ ) && vad_flag1 )
1037 : {
1038 : /* ch 2 is prev reference channel */
1039 0 : v_multc_fixed( corrEst_fx, 644245095 /*1.2f in Q29*/, corrEst_fx, L_NCSHIFT_DS + 1 ); /* Q31-corrEst_exp */
1040 0 : v_multc_fixed( corrEst_fx + L_NCSHIFT_DS + 1, 447213470 /* 0.833 in Q29*/, corrEst_fx + L_NCSHIFT_DS + 1, L_NCSHIFT_DS ); /* Q31-corrEst_exp */
1041 0 : corrEst_exp = add( corrEst_exp, 2 );
1042 : }
1043 3827 : ELSE IF( GT_32( hStereoTCA->prevTargetGain_fx, 644245094 /*1.2f in Q29*/ ) && vad_flag1 )
1044 : {
1045 : /* ch 1 is prev reference channel */
1046 0 : v_multc_fixed( corrEst_fx, 447213470 /* 0.833 f in Q29*/, corrEst_fx, L_NCSHIFT_DS ); /* Q31-corrEst_exp */
1047 0 : v_multc_fixed( corrEst_fx + L_NCSHIFT_DS, 644245095 /*1.2f in Q29*/, corrEst_fx + L_NCSHIFT_DS, L_NCSHIFT_DS + 1 ); /* Q31-corrEst_exp */
1048 0 : corrEst_exp = add( corrEst_exp, 2 );
1049 : }
1050 3827 : test();
1051 3827 : IF( BASOP_Util_Add_Mant32Exp( corrEst_ncorr_fx, corrEst_ncorr_exp, -429496730 /*0.8f in Q29*/, 2, &exp ) > 0 && vad_flag1 )
1052 : {
1053 1604 : i = s_max( 0, add( hStereoTCA->prevCorrLagStats[0], -1 + L_NCSHIFT_DS ) );
1054 1604 : j = s_min( 2 * L_NCSHIFT_DS, add( hStereoTCA->prevCorrLagStats[0], 1 + L_NCSHIFT_DS ) );
1055 1604 : k = add( sub( j, i ), 1 );
1056 :
1057 1604 : v_multc_fixed( corrEst_fx, ONE_IN_Q29 /*1.0f in Q29*/, corrEst_fx, i ); // to allign in same exp (Q31-corrEst_exp)
1058 1604 : v_multc_fixed( corrEst_fx + i, 644245095 /*1.2f in Q29*/, corrEst_fx + i, k ); /* Q31-corrEst_exp */
1059 1604 : v_multc_fixed( corrEst_fx + i + k, ONE_IN_Q29 /*1.0f in Q29*/, corrEst_fx + i + k, sub( 2 * L_NCSHIFT_DS + 1, i + k ) ); // to allign in same exp (Q31-corrEst_exp)
1060 1604 : corrEst_exp = add( corrEst_exp, 2 );
1061 : }
1062 :
1063 : /* Initial corr lag estimate */
1064 3827 : corrLagStats[0] = maximum_32_fx( corrEst_fx, add( sub( lagSearchRange[1], lagSearchRange[0] ), 1 ), &tempF_fx );
1065 3827 : move16();
1066 3827 : tempF_exp = corrEst_exp;
1067 3827 : move16();
1068 3827 : corrLagStats[0] = add( corrLagStats[0], lagSearchRange[0] );
1069 3827 : move16();
1070 :
1071 3827 : stmp = i_mult( corrLagStats[0], dsFactor ); /* Q0 */
1072 3827 : hStereoClassif->unclr_fv_fx[E_corrLagStats0] = L_shl( stmp, Q15 ); /* Q15 */
1073 3827 : move32();
1074 3827 : hStereoClassif->xtalk_fv_fx[E_corrLagStats0] = L_shl( stmp, Q15 ); /* Q15 */
1075 3827 : move32();
1076 3827 : hStereoClassif->xtalk_fv_fx[E_ica_corr_value0] = L_shl( tempF_fx, sub( tempF_exp, Q16 ) ); /* Q15 */
1077 3827 : move32();
1078 :
1079 3827 : test();
1080 3827 : IF( vad_flag1 == 0 && GT_16( alpha_fx, 22938 /* 0.7f in Q15 */ ) )
1081 : {
1082 15 : corrLagStats[0] = 0;
1083 15 : move16();
1084 : }
1085 :
1086 3827 : dist_reg_prv_corr_fx = L_abs( BASOP_Util_Add_Mant32Exp( reg_prv_corr_fx, reg_prv_corr_exp, -corrLagStats[0], Q31, &dist_reg_prv_corr_exp ) ); /* Q31-dist_reg_prv_corr_exp */
1087 3827 : test();
1088 3827 : IF( EQ_16( vad_flag1, 1 ) && EQ_16( vad_flag2, 1 ) )
1089 3773 : {
1090 :
1091 3773 : hStereoTCA->smooth_dist_reg_prv_corr_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( hStereoTCA->smooth_dist_reg_prv_corr_fx, SMOOTH_DIST_FACTOR_FX_Q15 ), hStereoTCA->smooth_dist_reg_prv_corr_exp, Mpy_32_16_1( dist_reg_prv_corr_fx, MAX_16 - SMOOTH_DIST_FACTOR_FX_Q15 ), dist_reg_prv_corr_exp, &hStereoTCA->smooth_dist_reg_prv_corr_exp ); /* Q31-hStereoTCA->smooth_dist_reg_prv_corr_exp */
1092 3773 : move32();
1093 3773 : Copy32( &( hStereoTCA->delay_0_mem_fx[1] ), &( hStereoTCA->delay_0_mem_fx[0] ), MAX_DELAYREGLEN - 1 ); /* Q31-hStereoTCA->delay_0_mem_exp */
1094 :
1095 3773 : hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1], 429496730 /* 0.2 in Q31*/ ), hStereoTCA->delay_0_mem_exp, L_mult0( 26214 /* 0.8 in Q15*/, corrLagStats[0] ), Q16, &temp ); /* Q31-temp */
1096 3773 : move32();
1097 3773 : Word32 inpp = L_abs( BASOP_Util_Add_Mant32Exp( reg_prv_corr_fx, reg_prv_corr_exp, L_negate( hStereoTCA->delay_0_mem_fx[0] ), hStereoTCA->delay_0_mem_exp, &exp ) ); /* Q31-exp */
1098 3773 : inpp = L_shl_sat( inpp, sub( exp, 5 ) ); /* Q26 */
1099 3773 : IF( GT_32( inpp, 1677721600 ) ) // 25 in Q26
1100 : {
1101 79 : set32_fx( &( hStereoTCA->delay_0_mem_fx[0] ), hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1], MAX_DELAYREGLEN - 1 );
1102 79 : hStereoTCA->delay_0_mem_exp = temp;
1103 79 : move16();
1104 : }
1105 : ELSE
1106 : {
1107 3694 : IF( GT_16( temp, hStereoTCA->delay_0_mem_exp ) )
1108 : {
1109 160 : scale_sig32( hStereoTCA->delay_0_mem_fx, MAX_DELAYREGLEN - 1, sub( hStereoTCA->delay_0_mem_exp, temp ) ); /* Q31-hStereoTCA->delay_0_mem_exp */
1110 160 : hStereoTCA->delay_0_mem_exp = temp;
1111 160 : move16();
1112 : }
1113 : ELSE
1114 : {
1115 3534 : hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1] = L_shl( hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1], sub( temp, hStereoTCA->delay_0_mem_exp ) ); /* Q31-temp */
1116 3534 : move32();
1117 : }
1118 : }
1119 : }
1120 : ELSE
1121 : {
1122 54 : hStereoTCA->smooth_dist_reg_prv_corr_fx = 0;
1123 54 : move32();
1124 54 : hStereoTCA->smooth_dist_reg_prv_corr_exp = 0;
1125 54 : move16();
1126 : }
1127 3827 : test();
1128 3827 : IF( vad_flag1 == 0 || vad_flag2 == 0 )
1129 : {
1130 54 : Word32 tmp_delay = L_shr( hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1], 1 );
1131 54 : Word16 tmp_delay_e = add( hStereoTCA->delay_0_mem_exp, 1 );
1132 54 : corrLagStats[0] = TRUNC_FX( tmp_delay, tmp_delay_e ); /* Q0 */
1133 54 : move32();
1134 : }
1135 :
1136 : /* second iteration of xcorr update @ inputFs with interp*/
1137 3827 : tempRK_fx = hStereoTCA->corrEstLT_fx + add( -lagSearchRange[0], corrLagStats[0] );
1138 3827 : set32_fx( rInterp_fx, 0, MAX_INTERPOLATE );
1139 3827 : set16_fx( rInterp_exp, 0, MAX_INTERPOLATE );
1140 :
1141 : /* select the Rk interp sinc window */
1142 3827 : winInterp_fx = ica_sincInterp4_fx + SINC_ORDER1;
1143 :
1144 3827 : IF( EQ_16( dsFactor, 2 ) )
1145 : {
1146 814 : winInterp_fx = ica_sincInterp2_fx + SINC_ORDER1;
1147 : }
1148 3013 : ELSE IF( EQ_16( dsFactor, 6 ) )
1149 : {
1150 985 : winInterp_fx = ica_sincInterp6_fx + SINC_ORDER1;
1151 : }
1152 :
1153 3827 : corrLagStats[1] = i_mult( corrLagStats[0], dsFactor ); /* Q0 */
1154 3827 : move16();
1155 3827 : interpMin = s_max( -sub( dsFactor, 1 ), -add( corrLagStats[1], i_mult( L_NCSHIFT_DS, dsFactor ) ) );
1156 3827 : interpMax = s_min( sub( dsFactor, 1 ), sub( i_mult( L_NCSHIFT_DS, dsFactor ), corrLagStats[1] ) );
1157 3827 : interpLen = add( sub( interpMax, interpMin ), 1 );
1158 :
1159 31300 : for ( i = interpMin, k = 0; i <= interpMax; i++, k++ )
1160 : {
1161 27473 : rInterp_fx[k] = 0;
1162 27473 : move32();
1163 370586 : FOR( j = -( SINC_ORDER1 / dsFactor ); j <= ( SINC_ORDER1 / dsFactor ); j++ )
1164 : {
1165 343113 : m = i_mult( j, dsFactor ); /* Q0 */
1166 343113 : test();
1167 343113 : IF( GE_16( sub( m, i ), -SINC_ORDER1 ) && LE_16( sub( m, i ), SINC_ORDER1 ) )
1168 : {
1169 319467 : IF( GT_16( j, sub( lagSearchRange[1], corrLagStats[0] ) ) )
1170 : {
1171 67 : rInterp_fx[k] = BASOP_Util_Add_Mant32Exp( rInterp_fx[k], rInterp_exp[k], Mpy_32_32( tempRK_fx[lagSearchRange[1] - corrLagStats[0]], winInterp_fx[m - i] ), hStereoTCA->corrEstLT_exp, &temp ); /* Q31-temp */
1172 67 : move32();
1173 67 : rInterp_exp[k] = temp;
1174 67 : move16();
1175 : }
1176 319400 : ELSE IF( LT_16( j, sub( lagSearchRange[0], corrLagStats[0] ) ) )
1177 : {
1178 176 : rInterp_fx[k] = BASOP_Util_Add_Mant32Exp( rInterp_fx[k], rInterp_exp[k], Mpy_32_32( tempRK_fx[lagSearchRange[0] - corrLagStats[0]], winInterp_fx[m - i] ), hStereoTCA->corrEstLT_exp, &temp ); /* Q31-temp */
1179 176 : move32();
1180 176 : rInterp_exp[k] = temp;
1181 176 : move16();
1182 : }
1183 : ELSE
1184 : {
1185 319224 : rInterp_fx[k] = BASOP_Util_Add_Mant32Exp( rInterp_fx[k], rInterp_exp[k], Mpy_32_32( tempRK_fx[j], winInterp_fx[m - i] ), hStereoTCA->corrEstLT_exp, &temp ); /* Q31-temp */
1186 319224 : move32();
1187 319224 : rInterp_exp[k] = temp;
1188 319224 : move16();
1189 : }
1190 : }
1191 : }
1192 : }
1193 3827 : temp = rInterp_exp[0];
1194 3827 : move16();
1195 45924 : FOR( i = 0; i < MAX_INTERPOLATE; i++ )
1196 : {
1197 42097 : temp = s_max( temp, rInterp_exp[i] );
1198 : }
1199 :
1200 45924 : FOR( i = 0; i < MAX_INTERPOLATE; i++ )
1201 : {
1202 42097 : rInterp_fx[i] = L_shl( rInterp_fx[i], sub( rInterp_exp[i], temp ) ); /* Q31-rInterp_exp[i] */
1203 42097 : move32();
1204 : }
1205 :
1206 3827 : corrLagStats[1] = add( corrLagStats[1], add( maximum_32_fx( rInterp_fx, interpLen, &tempF_fx ), interpMin ) ); /* Q0 */
1207 3827 : move16();
1208 :
1209 : /* save corr lag stats for the current frame */
1210 3827 : Copy( corrLagStats, hStereoTCA->corrLagStats, 3 ); /* Q0 */
1211 :
1212 3827 : return;
1213 : }
1214 :
1215 : /*---------------------------------------------------------------
1216 : * Function estDownmixGain_fx()
1217 : *
1218 : * Down mix gain estimation module; convert L/R to M/S.
1219 : * ---------------------------------------------------------------*/
1220 :
1221 63470 : static void estDownmixGain_fx(
1222 : STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo TCA Encoder handle */
1223 : const Word32 *chan1, /* i : reference signal q_chan */
1224 : const Word32 *chan2, /* i/o: target signal to be scaled q_chan */
1225 : const Word16 q_chan, /* i : Q of the channel signal Q0*/
1226 : const Word16 ncShift, /* i : shift Q0*/
1227 : const Word16 length, /* i : input frame length Q0*/
1228 : const Word16 element_mode, /* i : element mode Q0*/
1229 : STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier handle */
1230 : const Word16 tdm_LRTD_flag /* i : LRTD stereo mode flag Q0*/
1231 : )
1232 : {
1233 : Word16 i, i1, i2;
1234 : Word32 tempN, tempD;
1235 : Word16 alpha, temp;
1236 : Word16 currentGain, currentGain_e;
1237 : Word32 currentGain_log10;
1238 : Word32 unclr_instTargetGain;
1239 : Word32 prevTargetGain_log10;
1240 63470 : Word16 exp = 0;
1241 63470 : Word16 shift = 0;
1242 63470 : move16(); // exp
1243 63470 : move16(); // shift
1244 :
1245 63470 : IF( hStereoTCA->refChanIndx == L_CH_INDX )
1246 : {
1247 63440 : i1 = 0;
1248 63440 : move16();
1249 63440 : i2 = ncShift; /* Q0 */
1250 63440 : move16();
1251 : }
1252 : ELSE
1253 : {
1254 30 : i1 = ncShift; /* Q0 */
1255 30 : move16();
1256 30 : i2 = 0;
1257 30 : move16();
1258 : }
1259 :
1260 : /* abs sample sum estimation */
1261 63470 : tempN = 0;
1262 63470 : move32();
1263 63470 : tempD = 0;
1264 63470 : move32();
1265 43752829 : FOR( i = 0; i < length; i++ )
1266 : {
1267 43689359 : tempN = L_add( tempN, L_abs( chan1[i1 + i] ) ); /* q_chan */
1268 43689359 : tempD = L_add( tempD, L_abs( chan2[i2 + i] ) ); /* q_chan */
1269 : }
1270 :
1271 63470 : alpha = hStereoTCA->corrStatsSmoothFac_fx; /* Q15 */
1272 63470 : move16();
1273 63470 : IF( tempD == 0 )
1274 : {
1275 0 : currentGain_e = norm_l( hStereoTCA->prevTargetGain_fx );
1276 0 : currentGain = extract_h( L_shl( hStereoTCA->prevTargetGain_fx, currentGain_e ) );
1277 0 : currentGain_e = add( currentGain_e, 2 );
1278 : }
1279 : ELSE
1280 : {
1281 63470 : currentGain = BASOP_Util_Divide3232_Scale( tempN, tempD, &exp ); /* Q31-exp */
1282 63470 : currentGain_e = exp;
1283 63470 : move16();
1284 63470 : if ( currentGain == 0 )
1285 : {
1286 0 : currentGain_e = 0;
1287 0 : move16();
1288 : }
1289 : }
1290 :
1291 63470 : IF( GT_32( EPSILON_FX, currentGain ) )
1292 : {
1293 0 : currentGain = EPSILON_FX;
1294 0 : move16();
1295 0 : currentGain_e = 0;
1296 0 : move16();
1297 : }
1298 63470 : hStereoTCA->instTargetGain_fx = L_shl_sat( L_deposit_h( currentGain ), sub( currentGain_e, 2 ) );
1299 63470 : move32();
1300 63470 : prevTargetGain_log10 = BASOP_Util_Log10( hStereoTCA->prevTargetGain_fx, 2 ); // Output in Q25
1301 63470 : currentGain_log10 = BASOP_Util_Log10( L_deposit_h( currentGain ), currentGain_e ); // Output in Q25
1302 : // multiplication result will be Q25 should be fit to Q15 hence right shift by 10.
1303 : // Q25 - Q10 = Q15
1304 63470 : currentGain = extract_l( L_shr( Madd_32_16( Mpy_32_16_1( prevTargetGain_log10, alpha ), currentGain_log10, sub( MAX_16, alpha ) ), Q10 ) ); /* Q15 */
1305 63470 : currentGain_e = 0;
1306 63470 : move16();
1307 :
1308 63470 : test();
1309 63470 : IF( EQ_16( element_mode, IVAS_CPE_TD ) && hStereoClassif != NULL )
1310 : {
1311 3827 : Word16 exp_chan = sub( Q31, q_chan );
1312 : Word16 exp_div;
1313 : // tempD = powf( 10, currentGain );
1314 : // 10 ^ currentGain = 2 ^ (3.32192809488 * currentGain)
1315 : // 3.32192809488 in Q13 27213
1316 3827 : tempD = BASOP_util_Pow2( L_mult( currentGain, 27213 ), add( currentGain_e, Q2 ), &exp ); /* Q31-exp */
1317 3827 : unclr_instTargetGain = L_deposit_h( BASOP_Util_Divide3232_Scale( tempN, L_add( tempD, EPSILON_FX ), &exp_div ) ); /* Q31-exp */
1318 3827 : exp = add( sub( exp_chan, exp ), exp_div );
1319 3827 : if ( unclr_instTargetGain == 0 )
1320 : {
1321 0 : exp = 0;
1322 0 : move16();
1323 : }
1324 3827 : unclr_instTargetGain = BASOP_Util_Log10( L_add( unclr_instTargetGain, L_shr( MAX_32, sub( Q31, exp ) ) ), exp );
1325 : // unclr_fv_fx is expected in Q15 - log result will be in Q25 - hence rightshift by 10.
1326 3827 : hStereoClassif->unclr_fv_fx[E_ica_instTargetGain] = L_shr( unclr_instTargetGain, Q10 ); /* Q15 */
1327 3827 : move32();
1328 : }
1329 :
1330 63470 : test();
1331 63470 : IF( EQ_16( tdm_LRTD_flag, 1 ) )
1332 : {
1333 3698 : currentGain = 0;
1334 3698 : move32();
1335 : }
1336 59772 : ELSE IF( GT_16( hStereoTCA->LRTD_G_ATT_cnt, 1 ) ) /* lrtd_mode == 1 but tdm_LRTD_flag still 0 */
1337 : {
1338 219 : currentGain = BASOP_Util_Divide1616_Scale( currentGain, hStereoTCA->LRTD_G_ATT_cnt, &exp );
1339 219 : currentGain_e = add( exp, sub( currentGain_e, 15 ) );
1340 : }
1341 :
1342 63470 : IF( GE_16( norm_s( currentGain ), sub( currentGain_e, 1 ) ) )
1343 : {
1344 : /* convert currentGain into Q14 */
1345 63470 : currentGain = shl( currentGain, sub( currentGain_e, 1 ) ); /* Q14 */
1346 63470 : currentGain_e = 1;
1347 63470 : move16();
1348 : }
1349 : ELSE
1350 : {
1351 0 : shift = sub( currentGain_e, 1 );
1352 0 : move16();
1353 : }
1354 :
1355 : /* quantize the target gain */
1356 63470 : hStereoTCA->indx_ica_gD = usquant_fx( currentGain, &temp, shr( STEREO_TCA_GDMIN_FX_Q14, shift ), shr( STEREO_TCA_GDSTEP_FX_Q13, shift ), ( 1 << STEREO_BITS_TCA_GD ) ); /* Q13 */
1357 63470 : move16();
1358 : // hStereoTCA->targetGain_fx = powf( 10, temp );
1359 : // 10 ^ temp = 2 ^ (3.32192809488 * temp)
1360 : // 3.32192809488 in Q13 27213
1361 : // exponent of power function input will be 2 more since constant is in Q13
1362 63470 : exp = 2;
1363 63470 : move16();
1364 63470 : hStereoTCA->targetGain_fx = BASOP_util_Pow2( L_mult( temp, 27213 ), add( currentGain_e, 2 ), &exp ); /* Q31-exp */
1365 63470 : move32();
1366 63470 : hStereoTCA->targetGain_fx = L_shl( hStereoTCA->targetGain_fx, sub( exp, 2 ) ); // Q29
1367 63470 : move32();
1368 63470 : return;
1369 : }
1370 :
1371 : /*---------------------------------------------------------------
1372 : * Function icaMemUpdate()
1373 : *
1374 : * Recalculates the memories corresponding to the previous frame.
1375 : * ---------------------------------------------------------------*/
1376 3827 : static void icaMemUpdate_fx(
1377 : Encoder_State **sts, /* i/o: encoder state structure */
1378 : CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */
1379 : Word32 *bufChanL, /* i/o: L signal correction from previous frame q_com*/
1380 : Word32 *bufChanR, /* i/o: R signal correction from previous frame q_com*/
1381 : Word16 q_com,
1382 : const Word16 lMemRecalc, /* i : memory length at input Sampling Rate Q0*/
1383 : const Word16 lMemRecalc_SCh, /* i : SCh memory length at input Sampling Rate Q0*/
1384 : const Word16 input_frame /* i : frame length Q0*/
1385 : )
1386 : {
1387 : Word32 *ptr1, *ptr2;
1388 : Word16 i;
1389 : Word32 ratio_L, One_m_Ratio;
1390 :
1391 3827 : IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) )
1392 : {
1393 : /* Recalc of the memories - Downmix @ inputFs */
1394 : /*----------------------------------------------------------------*
1395 : * Create first part of the mixture using the old ratios
1396 : *----------------------------------------------------------------*/
1397 :
1398 3827 : IF( hCPE->hStereoTD->tdm_last_SM_flag )
1399 : {
1400 0 : ratio_L = hCPE->hStereoTD->tdm_last_ratio_SM_fx; /* Q31 */
1401 0 : move32();
1402 0 : One_m_Ratio = L_sub( ratio_L, MAX_32 );
1403 : }
1404 : ELSE
1405 : {
1406 3827 : ratio_L = hCPE->hStereoTD->tdm_last_ratio_fx; /* Q31 */
1407 3827 : move32();
1408 3827 : One_m_Ratio = L_sub( MAX_32, ratio_L );
1409 : }
1410 :
1411 3827 : ptr1 = sts[0]->input32_fx - add( lMemRecalc, lMemRecalc_SCh ); /* Q31-sts[0]->q_inp32 */
1412 3827 : ptr2 = sts[1]->input32_fx - add( lMemRecalc, lMemRecalc_SCh ); /* Q31-sts[1]->q_inp32 */
1413 :
1414 3827 : IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_TD ) )
1415 : {
1416 3765 : IF( hCPE->hStereoTD->flag_skip_DMX )
1417 : {
1418 30932 : FOR( i = lMemRecalc_SCh; i < ( lMemRecalc + lMemRecalc_SCh ); i++ )
1419 : {
1420 30840 : ptr1[i] = bufChanL[i]; /* q_com */
1421 30840 : move32();
1422 30840 : ptr2[i] = bufChanR[i]; /* q_com */
1423 30840 : move32();
1424 : }
1425 : }
1426 : ELSE
1427 : {
1428 895633 : FOR( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ )
1429 : {
1430 891960 : ptr1[i] = L_add( Mpy_32_32( bufChanR[i], One_m_Ratio ), Mpy_32_32( bufChanL[i], ratio_L ) ); /* q_com */
1431 891960 : move32();
1432 891960 : ptr2[i] = L_sub( Mpy_32_32( bufChanL[i], One_m_Ratio ), Mpy_32_32( bufChanR[i], ratio_L ) ); /* q_com */
1433 891960 : move32();
1434 : }
1435 : }
1436 : }
1437 : ELSE
1438 : {
1439 : Word16 fac, incr;
1440 : Word32 tmp1, tmp2;
1441 :
1442 : /* reset the past input signal (the signal is used in SWB BWE) */
1443 62 : set32_fx( sts[1]->input32_fx - input_frame, 0, input_frame );
1444 :
1445 62 : IF( hCPE->hStereoTD->flag_skip_DMX )
1446 : {
1447 : /* reconstruction of the Secondary channel past segment */
1448 813 : FOR( i = 0; i < lMemRecalc_SCh; i++ )
1449 : {
1450 805 : ptr2[i] = L_add( Mpy_32_32( bufChanL[i], One_m_Ratio ), Mpy_32_32( bufChanR[i], ratio_L ) ); /* q_com */
1451 805 : move32();
1452 : }
1453 :
1454 : /* overlap-add smoothing to equalize for different DMX signal energy between DFT and TD stereo */
1455 8 : fac = div_s( 1, lMemRecalc ); // Q15
1456 8 : incr = fac; // Q15
1457 8 : move16();
1458 :
1459 2768 : FOR( i = lMemRecalc_SCh; i < ( lMemRecalc + lMemRecalc_SCh ); i++ )
1460 : {
1461 2760 : tmp1 = bufChanL[i]; /* q_com */
1462 2760 : move32();
1463 2760 : tmp2 = bufChanR[i]; /* q_com */
1464 2760 : move32();
1465 :
1466 2760 : ptr1[i] = L_add( Mpy_32_16_1( ptr1[i], sub( MAX_16, fac ) ), Mpy_32_16_1( tmp1, fac ) ); /* q_com */
1467 2760 : move32();
1468 :
1469 : /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */
1470 2760 : ptr2[i] = tmp2; /* q_com */
1471 2760 : move32();
1472 :
1473 2760 : fac = add_sat( fac, incr );
1474 : }
1475 : }
1476 : ELSE
1477 : {
1478 : /* reconstruction of the Secondary channel past segment */
1479 3974 : FOR( i = 0; i < lMemRecalc_SCh; i++ )
1480 : {
1481 3920 : ptr2[i] = L_sub( Mpy_32_32( bufChanL[i], One_m_Ratio ), Mpy_32_32( bufChanR[i], ratio_L ) ); /* q_com */
1482 3920 : move32();
1483 : }
1484 :
1485 : /* overlap-add smoothing to equalize for different DMX signal energy between DFT and TD stereo */
1486 54 : fac = div_s( 1, lMemRecalc ); // Q15
1487 54 : incr = fac; // Q15
1488 54 : move16();
1489 13494 : FOR( i = lMemRecalc_SCh; i < ( lMemRecalc + lMemRecalc_SCh ); i++ )
1490 : {
1491 13440 : tmp1 = L_add( Mpy_32_32( bufChanR[i], One_m_Ratio ), Mpy_32_32( bufChanL[i], ratio_L ) ); /* q_com */
1492 13440 : tmp2 = L_sub( Mpy_32_32( bufChanL[i], One_m_Ratio ), Mpy_32_32( bufChanR[i], ratio_L ) ); /* q_com */
1493 :
1494 13440 : ptr1[i] = L_add( Mpy_32_16_1( ptr1[i], sub( MAX_16, fac ) ), Mpy_32_16_1( tmp1, fac ) ); /* q_com */
1495 13440 : move32();
1496 : /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */
1497 13440 : ptr2[i] = tmp2; /* q_com */
1498 13440 : move32();
1499 :
1500 13440 : fac = add_sat( fac, incr );
1501 : }
1502 : }
1503 : }
1504 : }
1505 :
1506 3827 : IF( hCPE->hStereoICBWE != NULL )
1507 : {
1508 : assert( L_MEM_RECALC_TBE_NS <= L_MEM_RECALC_NS );
1509 129 : i = NS2SA_FX2( sts[0]->input_Fs, L_MEM_RECALC_TBE_NS );
1510 129 : Copy_Scale_sig_32_16( bufChanL + sub( add( lMemRecalc, lMemRecalc_SCh ), i ), hCPE->hStereoICBWE->icbwe_inp_mem_fx[0], i, -Q16 ); /* q_com-16 */
1511 129 : Copy_Scale_sig_32_16( bufChanR + sub( add( lMemRecalc, lMemRecalc_SCh ), i ), hCPE->hStereoICBWE->icbwe_inp_mem_fx[1], i, -Q16 ); /* q_com-16 */
1512 129 : hCPE->hStereoICBWE->q_dataChan_fx = sub( q_com, Q16 );
1513 129 : move16();
1514 : }
1515 :
1516 3827 : return;
1517 : }
1518 : /*---------------------------------------------------------------
1519 : * stereo_tca_enc()
1520 : *
1521 : * Stereo temporal inter-channel adjustment/allocation processing module;
1522 : * Downmix, convert L/R to M/S.
1523 : * ---------------------------------------------------------------*/
1524 410255 : void stereo_tca_enc_fx(
1525 : CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */
1526 : const Word16 input_frame /* i : length of a frame per channel Q0*/
1527 : )
1528 : {
1529 : /* temp variables */
1530 : Word16 i, dsFactor, lMemRecalc;
1531 : Encoder_State **sts;
1532 : STEREO_TCA_ENC_HANDLE hStereoTCA;
1533 :
1534 : /* Buffers, input Left and right channels @ input_Fs*/
1535 : Word16 lMemRecalc_SCh;
1536 : Word32 input_mem_loc_fx[2][NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS )];
1537 : Word32 bufChanL_fx[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX];
1538 : Word32 bufChanR_fx[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX];
1539 : Word32 *ptrChanL_fx, *ptrChanR_fx;
1540 :
1541 410255 : set32_fx( bufChanL_fx, 0, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX );
1542 410255 : set32_fx( bufChanR_fx, 0, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX );
1543 410255 : set32_fx( input_mem_loc_fx[0], 0, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) );
1544 410255 : set32_fx( input_mem_loc_fx[1], 0, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) );
1545 : /* Buffers at internal sampling rate, i.e., CORR_INTER_FS */
1546 : Word32 bufChanL_DS_fx[L_FRAME_DS + ADDED_MEM_DS];
1547 : Word32 bufChanR_DS_fx[L_FRAME_DS + ADDED_MEM_DS];
1548 : Word32 *ptrChanL_DS_fx, *ptrChanR_DS_fx;
1549 : Word32 *target_fx;
1550 : Word16 target_idx;
1551 :
1552 : Word16 prevNCShift, currentNCShift;
1553 : Word16 tempLag[2];
1554 : Word32 corrEstStage2_fx[N_MAX_SHIFT_CHANGE + 1];
1555 : Word16 corrEstStage2_exp;
1556 : Word16 q_com, bufChan_q, input_mem_loc_q;
1557 : /* temp variables */
1558 : Word32 tempF1_fx, tempF_fx;
1559 : Word16 tempF1_exp;
1560 : Word16 tempS, tempS_buff[3];
1561 : Word16 maxCorrStatsDev, L_shift_adapt;
1562 410255 : Word16 musicMode = 0, neighborLimit;
1563 410255 : move16();
1564 : Word32 input_Fs;
1565 : Word16 prev_ICA_flag;
1566 :
1567 : /* initialization */
1568 410255 : sts = hCPE->hCoreCoder;
1569 410255 : hStereoTCA = hCPE->hStereoTCA;
1570 :
1571 410255 : input_Fs = sts[0]->input_Fs;
1572 410255 : move32();
1573 :
1574 410255 : q_com = sts[0]->q_inp32;
1575 410255 : move16();
1576 :
1577 410255 : lMemRecalc = NS2SA_FX2( input_Fs, L_MEM_RECALC_NS );
1578 410255 : move16();
1579 410255 : lMemRecalc_SCh = NS2SA_FX2( input_Fs, L_MEM_RECALC_SCH_NS );
1580 410255 : move16();
1581 :
1582 410255 : IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) )
1583 : {
1584 346785 : return;
1585 : }
1586 :
1587 : /* populate L/R memories into current buffers */
1588 63470 : Word16 tempp_scale = L_norm_arr( hStereoTCA->memChanL_fx, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH );
1589 63470 : tempp_scale = s_min( tempp_scale, L_norm_arr( hStereoTCA->memChanR_fx, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH ) );
1590 63470 : scale_sig32( hStereoTCA->memChanL_fx, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH, tempp_scale ); /* hStereoTCA->memChan_q + tempp_scale */
1591 63470 : scale_sig32( hStereoTCA->memChanR_fx, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH, tempp_scale ); /* hStereoTCA->memChan_q + tempp_scale */
1592 63470 : hStereoTCA->memChan_q = add( hStereoTCA->memChan_q, tempp_scale );
1593 63470 : move16();
1594 63470 : Copy32( hStereoTCA->memChanL_fx, bufChanL_fx, add( lMemRecalc, lMemRecalc_SCh ) ); /* hStereoTCA->memChan_q */
1595 63470 : Copy32( hStereoTCA->memChanR_fx, bufChanR_fx, add( lMemRecalc, lMemRecalc_SCh ) ); /* hStereoTCA->memChan_q */
1596 63470 : bufChan_q = hStereoTCA->memChan_q;
1597 63470 : move16();
1598 : /* pointers to the current frame */
1599 63470 : ptrChanL_fx = bufChanL_fx + add( lMemRecalc, lMemRecalc_SCh ); // Q:bufChan_q
1600 63470 : ptrChanR_fx = bufChanR_fx + add( lMemRecalc, lMemRecalc_SCh ); // Q:bufChan_q
1601 :
1602 : /* copy interleaved stereo data to two channels, e.g., L, R */
1603 63470 : Copy32( sts[0]->input32_fx, ptrChanL_fx, input_frame ); /* sts[0]->q_inp32 */
1604 63470 : Copy32( sts[1]->input32_fx, ptrChanR_fx, input_frame ); /* sts[1]->q_inp32 */
1605 :
1606 : /* Scaling buffers to common Q*/
1607 63470 : scale_sig32( ptrChanL_fx, input_frame, sub( s_min( q_com, bufChan_q ), q_com ) ); /* s_min( q_com, bufChan_q ) */
1608 63470 : scale_sig32( ptrChanR_fx, input_frame, sub( s_min( q_com, bufChan_q ), q_com ) ); /* s_min( q_com, bufChan_q ) */
1609 63470 : scale_sig32( bufChanL_fx, add( lMemRecalc, lMemRecalc_SCh ), sub( s_min( q_com, bufChan_q ), bufChan_q ) ); /* s_min( q_com, bufChan_q ) */
1610 63470 : scale_sig32( bufChanR_fx, add( lMemRecalc, lMemRecalc_SCh ), sub( s_min( q_com, bufChan_q ), bufChan_q ) ); /* s_min( q_com, bufChan_q ) */
1611 63470 : bufChan_q = s_min( q_com, bufChan_q );
1612 63470 : q_com = bufChan_q;
1613 63470 : move16();
1614 : /* UNCLR classifier update */
1615 63470 : IF( hCPE->hStereoClassif->lrtd_mode == 0 ) /* Normal TD mode, no attenuation */
1616 : {
1617 59426 : hStereoTCA->LRTD_G_ATT_cnt = 1;
1618 59426 : move16();
1619 : }
1620 4044 : ELSE IF( hCPE->hStereoTD != NULL )
1621 : {
1622 3827 : IF( hCPE->hStereoTD->tdm_LRTD_flag == 0 ) /* lrtd_mode == 1, but in td section */
1623 : {
1624 129 : hStereoTCA->LRTD_G_ATT_cnt = add( hStereoTCA->LRTD_G_ATT_cnt, 1 );
1625 129 : move16();
1626 129 : hStereoTCA->LRTD_G_ATT_cnt = s_min( 1000, hStereoTCA->LRTD_G_ATT_cnt );
1627 129 : move16();
1628 : }
1629 : }
1630 :
1631 63470 : IF( NE_16( hCPE->element_mode, IVAS_CPE_TD ) )
1632 : {
1633 59643 : hStereoTCA->refChanIndx = L_CH_INDX;
1634 59643 : move16();
1635 59643 : hStereoTCA->corrStatsSmoothFac_fx = 22938 /*0.7 in Q15 */;
1636 59643 : move16();
1637 59643 : estDownmixGain_fx( hStereoTCA, ptrChanL_fx, ptrChanR_fx, q_com, 0, input_frame, hCPE->element_mode, NULL, 0 );
1638 59643 : hStereoTCA->prevTargetGain_fx = hStereoTCA->targetGain_fx;
1639 59643 : move16();
1640 :
1641 : /* back up the L/R missing target */
1642 59643 : Copy32( bufChanL_fx + input_frame, hStereoTCA->memChanL_fx, add( lMemRecalc, lMemRecalc_SCh ) ); // bufChan_q
1643 59643 : Copy32( bufChanR_fx + input_frame, hStereoTCA->memChanR_fx, add( lMemRecalc, lMemRecalc_SCh ) ); // bufChan_q
1644 59643 : hStereoTCA->memChan_q = q_com;
1645 59643 : move16();
1646 59643 : hStereoTCA->lMemRecalc = 0;
1647 59643 : move16();
1648 59643 : hStereoTCA->lMemRecalc_12k8 = 0;
1649 59643 : move16();
1650 59643 : hStereoTCA->lMemRecalc_16k = 0;
1651 59643 : move16();
1652 :
1653 59643 : return;
1654 : }
1655 3827 : ELSE IF( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) )
1656 : {
1657 62 : tempF_fx = hStereoTCA->targetGain_fx; // Q29
1658 62 : move32();
1659 62 : tempF1_fx = hStereoTCA->prevTargetGain_fx; // Q29
1660 62 : move32();
1661 62 : tempS = hStereoTCA->prevRefChanIndx;
1662 62 : move16();
1663 :
1664 62 : Copy( hStereoTCA->prevCorrLagStats, tempS_buff, 3 ); /* Q0 */
1665 :
1666 62 : stereo_tca_init_enc_fx( hStereoTCA, input_Fs );
1667 :
1668 62 : hStereoTCA->targetGain_fx = tempF_fx; // Q29
1669 62 : move32();
1670 62 : hStereoTCA->prevTargetGain_fx = tempF1_fx; // Q29
1671 62 : move32();
1672 :
1673 62 : IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) )
1674 : {
1675 62 : hStereoTCA->targetGain_fx = L_min( hStereoTCA->targetGain_fx, ONE_IN_Q29 ); // Q29
1676 62 : move32();
1677 62 : hStereoTCA->prevTargetGain_fx = L_min( hStereoTCA->prevTargetGain_fx, ONE_IN_Q29 ); // Q29
1678 62 : move32();
1679 :
1680 62 : hStereoTCA->prevTargetGain_fx = ONE_IN_Q29; // Q29
1681 62 : move32();
1682 : }
1683 :
1684 62 : hStereoTCA->prevRefChanIndx = tempS;
1685 62 : move16();
1686 62 : Copy( tempS_buff, hStereoTCA->prevCorrLagStats, 3 ); /* Q0 */
1687 :
1688 : /* populate memory */
1689 62 : IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_MDCT ) )
1690 : {
1691 8 : Copy32( sts[0]->input32_fx - add( lMemRecalc, lMemRecalc_SCh ), bufChanL_fx, add( lMemRecalc, lMemRecalc_SCh ) ); /* sts[0]->q_inp32 */
1692 8 : Copy32( sts[1]->input32_fx - add( lMemRecalc, lMemRecalc_SCh ), bufChanR_fx, add( lMemRecalc, lMemRecalc_SCh ) ); /* sts[1]->q_inp32 */
1693 : }
1694 : }
1695 :
1696 : /* populate L/R DS memories into current buffers */
1697 3827 : Copy32( hStereoTCA->memChanL_DS_fx, bufChanL_DS_fx, ADDED_MEM_DS ); // hStereoTCA->memChan_DS_q
1698 3827 : Copy32( hStereoTCA->memChanR_DS_fx, bufChanR_DS_fx, ADDED_MEM_DS ); // hStereoTCA->memChan_DS_q
1699 :
1700 3827 : scale_sig32( bufChanL_fx, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX, sub( s_min( hStereoTCA->memChan_DS_q, bufChan_q ), bufChan_q ) ); // s_min( hStereoTCA->memChan_DS_q, bufChan_q )
1701 3827 : scale_sig32( bufChanR_fx, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX, sub( s_min( hStereoTCA->memChan_DS_q, bufChan_q ), bufChan_q ) ); // s_min( hStereoTCA->memChan_DS_q, bufChan_q )
1702 :
1703 3827 : scale_sig32( bufChanL_DS_fx, ADDED_MEM_DS, sub( s_min( hStereoTCA->memChan_DS_q, bufChan_q ), hStereoTCA->memChan_DS_q ) ); // s_min( hStereoTCA->memChan_DS_q, bufChan_q )
1704 3827 : scale_sig32( bufChanR_DS_fx, ADDED_MEM_DS, sub( s_min( hStereoTCA->memChan_DS_q, bufChan_q ), hStereoTCA->memChan_DS_q ) ); // s_min( hStereoTCA->memChan_DS_q, bufChan_q )
1705 3827 : scale_sig32( hStereoTCA->memdecim_fx, 12, sub( s_min( hStereoTCA->memChan_DS_q, bufChan_q ), hStereoTCA->memChan_DS_q ) ); // s_min( hStereoTCA->memChan_DS_q, bufChan_q )
1706 :
1707 3827 : bufChan_q = s_min( hStereoTCA->memChan_DS_q, bufChan_q );
1708 3827 : q_com = bufChan_q;
1709 3827 : move16();
1710 3827 : hStereoTCA->memChan_DS_q = bufChan_q;
1711 3827 : move16();
1712 :
1713 : /* pointers to the current frame of DS */
1714 :
1715 3827 : ptrChanL_DS_fx = bufChanL_DS_fx + ADDED_MEM_DS; /* hStereoTCA->memChan_DS_q */
1716 3827 : ptrChanR_DS_fx = bufChanR_DS_fx + ADDED_MEM_DS; /* hStereoTCA->memChan_DS_q */
1717 :
1718 : /* resample factor */
1719 3827 : dsFactor = extract_l( Mpy_32_32( input_Fs, 268436 /* 1/CORR_INTER_FS in Q31*/ ) ); // Q0
1720 :
1721 : /* resample the stereo channels */
1722 3827 : deEmphResample_fx( hStereoTCA, ptrChanL_fx, ptrChanR_fx, ptrChanL_DS_fx, ptrChanR_DS_fx, input_frame, dsFactor );
1723 :
1724 : /**********************NEED to Allign first 40 index in each channel ************************************/
1725 : /* inter-channel corrStats estimation */
1726 3827 : corrStatsEst_fx( hStereoTCA, bufChanL_DS_fx + ADDED_MEM_DS, bufChanR_DS_fx + ADDED_MEM_DS, q_com, ( L_FRAME_DS + L_XCORRMEM_DS ), dsFactor, hCPE->hCoreCoder[0]->vad_flag, hCPE->hCoreCoder[1]->vad_flag, hCPE->hStereoClassif );
1727 :
1728 : /*-----------------------------------------------------------------*
1729 : * refine the ICA stats
1730 : *-----------------------------------------------------------------*/
1731 :
1732 3827 : prev_ICA_flag = 0;
1733 3827 : move16();
1734 3827 : test();
1735 3827 : if ( hCPE->hStereoTD->prev_fr_LRTD_TD_dec && abs_s( hStereoTCA->prevCorrLagStats[2] ) != 0 )
1736 : {
1737 37 : prev_ICA_flag = 1;
1738 37 : move16();
1739 : }
1740 :
1741 3827 : test();
1742 3827 : IF( hCPE->hStereoTD->prev_fr_LRTD_TD_dec == 0 || EQ_16( prev_ICA_flag, 1 ) )
1743 220 : {
1744 : /* initialize the refinement search for NC-shift */
1745 220 : hStereoTCA->corrLagStats[2] = hStereoTCA->corrLagStats[1];
1746 220 : move16();
1747 220 : maxCorrStatsDev = N_MAX_SHIFT_CHANGE;
1748 220 : move16();
1749 220 : IF( LE_16( hStereoTCA->corrStatsSmoothFac_fx, 22938 /*0.7f*/ ) )
1750 : {
1751 0 : maxCorrStatsDev = 160; /* L_NCSHIFT_MAX @ 32kHz */
1752 0 : move16();
1753 : }
1754 :
1755 220 : IF( LT_32( input_Fs, 32000 ) )
1756 : {
1757 56 : maxCorrStatsDev = extract_l( Mpy_32_32( imult3216( input_Fs, maxCorrStatsDev ), 67109 /* 1/32000.0f in Q31*/ ) ); // Q0
1758 : }
1759 :
1760 220 : musicMode = ( hCPE->hCoreCoder[0]->sp_aud_decision0 == 1 || sts[0]->last_core > ACELP_CORE );
1761 220 : move16();
1762 :
1763 220 : IF( musicMode )
1764 : {
1765 45 : maxCorrStatsDev = 1;
1766 45 : move16();
1767 45 : set16_fx( hStereoTCA->corrLagStats + 1, 0, 2 );
1768 : }
1769 :
1770 220 : tempS = sub( hStereoTCA->corrLagStats[1], hStereoTCA->prevCorrLagStats[2] ); /* Q0 */
1771 :
1772 220 : IF( GT_16( abs_s( tempS ), maxCorrStatsDev ) )
1773 : {
1774 80 : IF( tempS > 0 )
1775 : {
1776 20 : hStereoTCA->corrLagStats[2] = add( hStereoTCA->prevCorrLagStats[2], maxCorrStatsDev ); /* Q0 */
1777 : }
1778 : ELSE
1779 : {
1780 60 : hStereoTCA->corrLagStats[2] = add( hStereoTCA->prevCorrLagStats[2], -maxCorrStatsDev ); /* Q0 */
1781 : }
1782 80 : move16();
1783 : }
1784 :
1785 220 : neighborLimit = maxCorrStatsDev;
1786 220 : move16();
1787 : /* refine and search based on the corrlag stats */
1788 220 : test();
1789 220 : test();
1790 220 : IF( tempS != 0 && NE_16( dsFactor, 1 ) && prev_ICA_flag == 0 )
1791 : {
1792 144 : tempF_fx = 0;
1793 144 : move32();
1794 144 : corrEstStage2_exp = 0;
1795 144 : move16();
1796 144 : IF( !musicMode )
1797 : {
1798 130 : tempLag[0] = s_min( hStereoTCA->corrLagStats[2], hStereoTCA->prevCorrLagStats[2] ); /* Q0 */
1799 130 : move16();
1800 130 : tempLag[1] = s_max( hStereoTCA->corrLagStats[2], hStereoTCA->prevCorrLagStats[2] ); /* Q0 */
1801 130 : move16();
1802 :
1803 130 : neighborLimit = s_min( 3, maxCorrStatsDev );
1804 :
1805 130 : IF( LT_16( hStereoTCA->prevCorrLagStats[2], hStereoTCA->corrLagStats[2] ) )
1806 : {
1807 92 : tempLag[1] = s_min( tempLag[1], add( tempLag[0], neighborLimit ) ); /* Q0 */
1808 : }
1809 : ELSE
1810 : {
1811 38 : tempLag[0] = s_max( tempLag[0], sub( tempLag[1], neighborLimit ) ); /* Q0 */
1812 : }
1813 130 : move16();
1814 130 : utilCrossCorr_fx( ptrChanL_fx, q_com, ptrChanR_fx, q_com, NULL, corrEstStage2_fx, &corrEstStage2_exp, tempLag, input_frame, 0 );
1815 :
1816 130 : hStereoTCA->corrLagStats[2] = maximum_l( corrEstStage2_fx, add( sub( tempLag[1], tempLag[0] ), 1 ), &tempF_fx );
1817 130 : move16();
1818 130 : hStereoTCA->corrLagStats[2] = add( hStereoTCA->corrLagStats[2], tempLag[0] );
1819 130 : move16();
1820 : }
1821 :
1822 144 : IF( GT_16( abs_s( tempS ), neighborLimit ) )
1823 : {
1824 113 : tempLag[0] = hStereoTCA->corrLagStats[1]; /* Q0 */
1825 113 : move16();
1826 113 : tempLag[1] = hStereoTCA->corrLagStats[1]; /* Q0 */
1827 113 : move16();
1828 113 : utilCrossCorr_fx( ptrChanL_fx, q_com, ptrChanR_fx, q_com, NULL, &tempF1_fx, &tempF1_exp, tempLag, input_frame, 0 );
1829 :
1830 113 : test();
1831 113 : IF( ( BASOP_Util_Cmp_Mant32Exp( tempF1_fx, tempF1_exp, tempF_fx, corrEstStage2_exp ) > 0 ) || musicMode )
1832 : {
1833 29 : IF( tempS > 0 )
1834 : {
1835 8 : hStereoTCA->corrLagStats[2] = add( hStereoTCA->prevCorrLagStats[2], s_min( abs_s( tempS ), maxCorrStatsDev ) ); /* Q0 */
1836 : }
1837 : ELSE
1838 : {
1839 21 : hStereoTCA->corrLagStats[2] = add( hStereoTCA->prevCorrLagStats[2], s_max( -abs_s( tempS ), -maxCorrStatsDev ) ); /* Q0 */
1840 : }
1841 29 : move16();
1842 : }
1843 : }
1844 :
1845 : /* restrict the reference channel for +/- variation */
1846 144 : test();
1847 144 : test();
1848 144 : test();
1849 144 : if ( ( hStereoTCA->corrLagStats[2] < 0 && hStereoTCA->prevCorrLagStats[2] > 0 ) || ( hStereoTCA->corrLagStats[2] > 0 && hStereoTCA->prevCorrLagStats[2] < 0 ) )
1850 : {
1851 1 : hStereoTCA->corrLagStats[2] = 0;
1852 1 : move16();
1853 : }
1854 : }
1855 :
1856 220 : IF( EQ_16( hCPE->hStereoTD->prev_fr_LRTD_TD_dec /*hCPE->hStereoClassif->lrtd_mode*/, 1 ) ) /* Content is considered as uncorrelated -> ICA shift is turned off */
1857 : {
1858 37 : hStereoTCA->corrLagStats[2] = 0;
1859 37 : move16();
1860 :
1861 37 : test();
1862 37 : if ( EQ_16( hCPE->hStereoTD->tdm_LRTD_flag, 1 ) && prev_ICA_flag == 0 )
1863 : {
1864 0 : hStereoTCA->prevCorrLagStats[2] = 0;
1865 0 : move16();
1866 : }
1867 : }
1868 :
1869 : /* Perform the following:
1870 : 1. adjust samples,
1871 : 2. interp shift variation,
1872 : 3. gain estimation */
1873 220 : prevNCShift = abs_s( hStereoTCA->prevCorrLagStats[2] ); /* Q0 */
1874 220 : currentNCShift = abs_s( hStereoTCA->corrLagStats[2] ); /* Q0 */
1875 :
1876 220 : IF( EQ_16( hStereoTCA->prevRefChanIndx, L_CH_INDX ) )
1877 : {
1878 192 : v_multc_fixed( bufChanL_fx, ONE_IN_Q29, bufChanL_fx, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); /* TO make in common Q bufChan_q - 2*/
1879 192 : Copy32( ptrChanL_fx - add( lMemRecalc, lMemRecalc_SCh ), input_mem_loc_fx[0], add( lMemRecalc, lMemRecalc_SCh ) ); // bufChan_q - 2
1880 192 : v_multc_fixed( ptrChanR_fx + sub( prevNCShift, add( lMemRecalc, lMemRecalc_SCh ) ), hStereoTCA->prevTargetGain_fx, input_mem_loc_fx[1], add( lMemRecalc, lMemRecalc_SCh ) ); // bufChan_q-2
1881 192 : v_multc_fixed( bufChanR_fx, ONE_IN_Q29, bufChanR_fx, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); /* TO make in common Q bufChan_q -2*/
1882 : }
1883 : ELSE
1884 : {
1885 28 : v_multc_fixed( bufChanL_fx, ONE_IN_Q29, bufChanL_fx, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); /* TO make in common Q bufChan_q -2*/
1886 28 : Copy32( ptrChanL_fx + sub( prevNCShift, add( lMemRecalc, lMemRecalc_SCh ) ), input_mem_loc_fx[0], add( lMemRecalc, lMemRecalc_SCh ) ); // bufChan_q -2
1887 28 : v_multc_fixed( ptrChanR_fx - add( lMemRecalc, lMemRecalc_SCh ), hStereoTCA->prevTargetGain_fx, input_mem_loc_fx[1], add( lMemRecalc, lMemRecalc_SCh ) ); // bufChan_q -2
1888 28 : v_multc_fixed( bufChanR_fx, ONE_IN_Q29, bufChanR_fx, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); /* TO make in common Q bufChan_q -2*/
1889 : }
1890 220 : bufChan_q = sub( bufChan_q, 2 );
1891 220 : q_com = bufChan_q;
1892 220 : move16();
1893 220 : input_mem_loc_q = bufChan_q;
1894 220 : move16();
1895 220 : target_fx = ptrChanR_fx; /* bufChan_q -2 */
1896 220 : target_idx = R_CH_INDX; /* Q0 */
1897 220 : move16();
1898 : /* identify target signal to correct for shift variations */
1899 220 : test();
1900 220 : test();
1901 220 : IF( ( prevNCShift == 0 && hStereoTCA->corrLagStats[2] < 0 ) || EQ_16( hStereoTCA->prevRefChanIndx, R_CH_INDX ) )
1902 : {
1903 49 : target_fx = ptrChanL_fx; /* bufChan_q - 2 */
1904 49 : target_idx = L_CH_INDX;
1905 49 : move16();
1906 : }
1907 :
1908 : /* target signal adjustment for temporal shift variations */
1909 220 : IF( sub( prevNCShift, currentNCShift ) != 0 )
1910 : {
1911 106 : L_shift_adapt = L_SHIFT_ADAPT_16k;
1912 106 : move16();
1913 106 : if ( GT_32( input_Fs, INT_FS_16k ) )
1914 : {
1915 82 : L_shift_adapt = L_SHIFT_ADAPT_MAX;
1916 82 : move16();
1917 : }
1918 :
1919 : /* Note!! : Always keep the assert (prevNCShift>>1) below according to the equation used here to get tempS */
1920 106 : tempS = shr( currentNCShift, 1 ); /* Q0 */
1921 :
1922 106 : IF( LE_32( abs_s( sub( currentNCShift, prevNCShift ) ), L_min( N_MAX_SHIFT_CHANGE, Mpy_32_32( imult3216( input_Fs, N_MAX_SHIFT_CHANGE ), 67109 /* 1/32000.0f in Q31*/ ) ) ) )
1923 : {
1924 87 : adjustTargetSignal_fx( ( target_fx - tempS ), prevNCShift, currentNCShift, L_shift_adapt, 0 );
1925 : }
1926 : ELSE
1927 : {
1928 19 : tempS = s_min( s_max( tempS, add( sub( prevNCShift, currentNCShift ), sub( L_shift_adapt, input_frame ) ) ), add( sub( prevNCShift, currentNCShift ), lMemRecalc ) ); /* Q0 */
1929 :
1930 19 : adjustTargetSignal_fx( ( target_fx - tempS ), prevNCShift, currentNCShift, L_shift_adapt, 1 );
1931 : }
1932 :
1933 106 : IF( target_idx == L_CH_INDX )
1934 : {
1935 40 : Copy32( target_fx - tempS, &( input_mem_loc_fx[target_idx][lMemRecalc + lMemRecalc_SCh - tempS - currentNCShift] ), add( currentNCShift, tempS ) ); /* bufChan_q - 2 */
1936 : }
1937 : ELSE
1938 : {
1939 66 : v_multc_fixed( target_fx - tempS, hStereoTCA->prevTargetGain_fx, &( input_mem_loc_fx[target_idx][lMemRecalc + lMemRecalc_SCh - tempS - currentNCShift] ), add( currentNCShift, tempS ) ); /* bufChan_q - 2 */
1940 66 : scale_sig32( input_mem_loc_fx[target_idx], sub( sub( add( lMemRecalc, lMemRecalc_SCh ), tempS ), currentNCShift ), -2 );
1941 66 : scale_sig32( &input_mem_loc_fx[target_idx][lMemRecalc + lMemRecalc_SCh], sub( NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ), add( lMemRecalc, lMemRecalc_SCh ) ), -2 );
1942 66 : scale_sig32( input_mem_loc_fx[0], NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ), -2 );
1943 66 : input_mem_loc_q = sub( bufChan_q, 2 );
1944 : }
1945 : }
1946 :
1947 : /* reference channel index */
1948 220 : IF( hStereoTCA->corrLagStats[2] >= 0 )
1949 : {
1950 190 : hStereoTCA->refChanIndx = L_CH_INDX;
1951 : }
1952 : ELSE
1953 : {
1954 30 : hStereoTCA->refChanIndx = R_CH_INDX;
1955 : }
1956 220 : move16();
1957 :
1958 : /* Estimate and quantize the gain for scaling */
1959 :
1960 220 : estDownmixGain_fx( hStereoTCA, ptrChanL_fx, ptrChanR_fx, q_com, currentNCShift, sub( input_frame, currentNCShift ), hCPE->element_mode, hCPE->hStereoClassif, hCPE->hStereoTD->tdm_LRTD_flag );
1961 :
1962 : /* quantize the corrStats */
1963 :
1964 : Word16 temp_exp, tempF_16fx;
1965 220 : Word16 scalar_value = BASOP_Util_Divide1616_Scale( currentNCShift, dsFactor, &temp_exp ); /* Q15-temp_exp */
1966 :
1967 220 : scalar_value = shl_sat( scalar_value, sub( temp_exp, 5 ) ); /*Q10*/
1968 220 : hStereoTCA->indx_ica_NCShift = usquant_fx( scalar_value, &tempF_16fx, 0, 512 /* 0.5 in Q10 */, ( 1 << STEREO_BITS_TCA_CORRSTATS ) ); /* Q0 */
1969 :
1970 220 : tempF_fx = tempF_16fx;
1971 220 : move32();
1972 : }
1973 : ELSE
1974 : {
1975 3607 : hStereoTCA->refChanIndx = L_CH_INDX;
1976 3607 : move16();
1977 3607 : hStereoTCA->corrLagStats[2] = 0;
1978 3607 : move16();
1979 3607 : hStereoTCA->prevCorrLagStats[2] = 0;
1980 3607 : move16();
1981 3607 : hStereoTCA->indx_ica_NCShift = 0;
1982 3607 : move16();
1983 :
1984 3607 : currentNCShift = 0; /* only to avoid compilation warning */
1985 3607 : move16();
1986 3607 : target_fx = ptrChanL_fx; /* only to avoid compilation warning bufChan_q*/
1987 3607 : move16();
1988 3607 : target_idx = L_CH_INDX; /* only to avoid compilation warning */
1989 3607 : move16();
1990 :
1991 3607 : v_multc_fixed( bufChanL_fx, ONE_IN_Q29, bufChanL_fx, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); /* TO make in common Q bufChan_q -2*/
1992 :
1993 3607 : Copy32( ptrChanL_fx - add( lMemRecalc, lMemRecalc_SCh ), input_mem_loc_fx[0], add( lMemRecalc, lMemRecalc_SCh ) ); // bufChan_q -2
1994 3607 : v_multc_fixed( ptrChanR_fx - add( lMemRecalc, lMemRecalc_SCh ), hStereoTCA->prevTargetGain_fx, input_mem_loc_fx[1], add( lMemRecalc, lMemRecalc_SCh ) ); // bufChan_q -2
1995 :
1996 3607 : v_multc_fixed( bufChanR_fx, ONE_IN_Q29, bufChanR_fx, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); /* TO make in common Q bufChan_q -2 */
1997 3607 : bufChan_q = sub( bufChan_q, 2 );
1998 3607 : q_com = bufChan_q;
1999 3607 : move16();
2000 3607 : input_mem_loc_q = bufChan_q;
2001 3607 : move16();
2002 : /* Estimate and quantize the gain for scaling */
2003 :
2004 3607 : estDownmixGain_fx( hStereoTCA, ptrChanL_fx, ptrChanR_fx, q_com, 0, input_frame, hCPE->element_mode, hCPE->hStereoClassif, hCPE->hStereoTD->tdm_LRTD_flag );
2005 : }
2006 :
2007 : /*-----------------------------------------------------------------*
2008 : * updates and memory backups
2009 : *-----------------------------------------------------------------*/
2010 :
2011 : /* back up the L/R missing target */
2012 3827 : Copy32( bufChanL_fx + input_frame, hStereoTCA->memChanL_fx, add( lMemRecalc, lMemRecalc_SCh ) ); /* bufChan_q */
2013 3827 : Copy32( bufChanR_fx + input_frame, hStereoTCA->memChanR_fx, add( lMemRecalc, lMemRecalc_SCh ) ); /* bufChan_q */
2014 3827 : hStereoTCA->memChan_q = bufChan_q;
2015 :
2016 3827 : IF( currentNCShift != 0 )
2017 : {
2018 : /* Temporal channel adjustment of the LA samples based on the NC shift */
2019 96 : tcaTargetCh_LA_fx( hStereoTCA, ptrChanL_fx, ptrChanR_fx, &q_com, currentNCShift, input_frame );
2020 :
2021 96 : scale_sig32( bufChanL_fx, add( lMemRecalc, lMemRecalc_SCh ), sub( s_min( q_com, bufChan_q ), bufChan_q ) ); // s_min( q_com, bufChan_q )
2022 96 : scale_sig32( bufChanL_fx + add( lMemRecalc, lMemRecalc_SCh ), add( input_frame, currentNCShift ), sub( s_min( q_com, bufChan_q ), q_com ) ); // s_min( q_com, bufChan_q )
2023 96 : scale_sig32( bufChanL_fx + add( add( lMemRecalc, lMemRecalc_SCh ), add( input_frame, currentNCShift ) ), sub( L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX, add( add( lMemRecalc, lMemRecalc_SCh ), add( input_frame, currentNCShift ) ) ), sub( s_min( q_com, bufChan_q ), bufChan_q ) ); // s_min( q_com, bufChan_q )
2024 :
2025 : /* Scaling to common Q*/
2026 96 : scale_sig32( bufChanR_fx, add( lMemRecalc, lMemRecalc_SCh ), sub( s_min( q_com, bufChan_q ), bufChan_q ) ); // s_min( q_com, bufChan_q )
2027 96 : scale_sig32( bufChanR_fx + add( lMemRecalc, lMemRecalc_SCh ), add( input_frame, currentNCShift ), sub( s_min( q_com, bufChan_q ), q_com ) ); // s_min( q_com, bufChan_q )
2028 96 : scale_sig32( bufChanR_fx + add( add( lMemRecalc, lMemRecalc_SCh ), add( input_frame, currentNCShift ) ), sub( L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX, add( add( lMemRecalc, lMemRecalc_SCh ), add( input_frame, currentNCShift ) ) ), sub( s_min( q_com, bufChan_q ), bufChan_q ) ); // s_min( q_com, bufChan_q )
2029 96 : bufChan_q = s_min( q_com, bufChan_q );
2030 96 : q_com = bufChan_q;
2031 : }
2032 :
2033 : /* Update of changed samples corresponding to the memory */
2034 : /* Scaling to common Q*/
2035 3827 : scale_sig32( input_mem_loc_fx[0], NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ), sub( s_min( input_mem_loc_q, sts[0]->q_inp32 ), input_mem_loc_q ) ); // s_min( input_mem_loc_q, sts[0]->q_inp32 )
2036 3827 : scale_sig32( input_mem_loc_fx[1], NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ), sub( s_min( input_mem_loc_q, sts[0]->q_inp32 ), input_mem_loc_q ) ); // s_min( input_mem_loc_q, sts[0]->q_inp32 )
2037 3827 : scale_sig32( sts[0]->input_buff32_fx, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ), sub( s_min( input_mem_loc_q, sts[0]->q_inp32 ), sts[0]->q_inp32 ) ); // s_min( input_mem_loc_q, sts[0]->q_inp32 )
2038 3827 : scale_sig32( sts[1]->input_buff32_fx, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ), sub( s_min( input_mem_loc_q, sts[1]->q_inp32 ), sts[1]->q_inp32 ) ); // s_min( input_mem_loc_q, sts[0]->q_inp32 )
2039 :
2040 3827 : input_mem_loc_q = s_min( input_mem_loc_q, sts[0]->q_inp32 ); /* sts[0]->q_inp32 */
2041 3827 : sts[0]->q_inp32 = input_mem_loc_q;
2042 3827 : move16();
2043 3827 : sts[1]->q_inp32 = input_mem_loc_q;
2044 3827 : move16();
2045 :
2046 3827 : icaMemUpdate_fx( sts, hCPE, input_mem_loc_fx[0], input_mem_loc_fx[1], input_mem_loc_q, lMemRecalc, lMemRecalc_SCh, input_frame );
2047 :
2048 : /* populate the st->input target buffer */
2049 3827 : test();
2050 3827 : IF( hCPE->hStereoTD->prev_fr_LRTD_TD_dec == 0 || EQ_16( prev_ICA_flag, 1 ) )
2051 : {
2052 220 : Word16 shift = sub( q_com, sts[target_idx]->q_inp32 );
2053 135580 : FOR( Word16 idx = 0; idx < input_frame; idx++ )
2054 : {
2055 135360 : sts[target_idx]->input32_fx[idx] = L_shr( target_fx[currentNCShift + idx], shift );
2056 135360 : move32();
2057 : }
2058 : }
2059 :
2060 3827 : IF( NE_16( hCPE->element_mode, IVAS_CPE_DFT ) )
2061 : {
2062 : /* Scale the Right channel with the gain */
2063 : Word16 j;
2064 3827 : Word16 l_ica_ovl = NS2SA_FX2( input_Fs, STEREO_L_TCA_OVLP_NS );
2065 :
2066 3827 : Word16 winSlope = div_s( 1, l_ica_ovl ); // Q15
2067 :
2068 3827 : tempF1_fx = hStereoTCA->targetGain_fx; // Q29
2069 3827 : move32();
2070 3827 : tempF_fx = hStereoTCA->prevTargetGain_fx; // Q29
2071 3827 : move32();
2072 :
2073 629827 : FOR( ( i = 0, j = 0 ); i < l_ica_ovl; ( i++, j++ ) )
2074 : {
2075 626000 : sts[1]->input32_fx[i] = L_add( Mpy_32_32( sts[1]->input32_fx[i], Mpy_32_16_1( tempF_fx, sub( MAX_16, imult1616( j, winSlope ) ) ) ), Mpy_32_32( sts[1]->input32_fx[i], Mpy_32_16_1( tempF1_fx, imult1616( j, winSlope ) ) ) ); // inpq-2
2076 626000 : move32();
2077 : }
2078 :
2079 1881827 : FOR( ; i < input_frame; i++ )
2080 : {
2081 1878000 : sts[1]->input32_fx[i] = Mpy_32_32( sts[1]->input32_fx[i], tempF1_fx ); // inpq-2
2082 1878000 : move32();
2083 : }
2084 :
2085 3827 : scale_sig32( sts[1]->input_buff32_fx, (Word16) Mpy_32_32( input_Fs, 42949673 ) /* 1/50 in Q31*/, -2 ); // inpq-2
2086 3827 : scale_sig32( sts[0]->input_buff32_fx, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ), -2 ); // inpq-2
2087 3827 : sts[0]->q_inp32 = sub( sts[0]->q_inp32, 2 );
2088 3827 : move16();
2089 3827 : sts[1]->q_inp32 = sub( sts[1]->q_inp32, 2 );
2090 3827 : move16();
2091 : }
2092 :
2093 : /* update L/R DS memories */
2094 3827 : Copy32( bufChanL_DS_fx + L_FRAME_DS, hStereoTCA->memChanL_DS_fx, ADDED_MEM_DS ); /* hStereoTCA->memChan_DS_q */
2095 3827 : Copy32( bufChanR_DS_fx + L_FRAME_DS, hStereoTCA->memChanR_DS_fx, ADDED_MEM_DS ); /* hStereoTCA->memChan_DS_q */
2096 :
2097 : /* save the reference channel index for next frame */
2098 3827 : hStereoTCA->prevRefChanIndx = hStereoTCA->refChanIndx; /* Q0 */
2099 3827 : move16();
2100 : /* save the corr lag stats for next frame */
2101 3827 : Copy( hStereoTCA->corrLagStats, hStereoTCA->prevCorrLagStats, 3 ); /* Q0 */
2102 :
2103 : /* save the target gain for next frame */
2104 3827 : hStereoTCA->prevTargetGain_fx = hStereoTCA->targetGain_fx; // Q29
2105 3827 : move32();
2106 3827 : return;
2107 : }
2108 : /*-------------------------------------------------------------------*
2109 : * stereo_tca_init_enc()
2110 : *
2111 : * Stereo temporal inter-channel adjustment (ICA) encoder initialization
2112 : *-------------------------------------------------------------------*/
2113 893 : void stereo_tca_init_enc_fx(
2114 : STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo ICA handle */
2115 : const Word32 input_Fs /* i : input sampling frequency Q0*/
2116 : )
2117 : {
2118 : Word16 div1;
2119 : Word16 div_e;
2120 893 : hStereoTCA->lMemRecalc = NS2SA_FX2( input_Fs, L_MEM_RECALC_NS );
2121 893 : move16();
2122 893 : div1 = BASOP_Util_Divide3232_Scale( L_mult( hStereoTCA->lMemRecalc, INT_FS_12k8 ), input_Fs, &div_e ); /* Q15-div_e */
2123 893 : hStereoTCA->lMemRecalc_12k8 = shr( div1, 1 + sub( 15, div_e ) );
2124 893 : move16();
2125 :
2126 893 : div1 = BASOP_Util_Divide3232_Scale( L_mult( hStereoTCA->lMemRecalc, INT_FS_16k ), input_Fs, &div_e ); /* Q15-div_e */
2127 893 : hStereoTCA->lMemRecalc_16k = shr( div1, 1 + sub( 15, div_e ) );
2128 893 : move16();
2129 :
2130 893 : hStereoTCA->refChanIndx = L_CH_INDX;
2131 893 : hStereoTCA->prevRefChanIndx = L_CH_INDX;
2132 893 : move16();
2133 893 : move16();
2134 :
2135 893 : hStereoTCA->targetGain_fx = ONE_IN_Q29; // Q29
2136 893 : hStereoTCA->prevTargetGain_fx = ONE_IN_Q29; // Q29
2137 893 : hStereoTCA->instTargetGain_fx = ONE_IN_Q29; // Q29
2138 893 : move32();
2139 893 : move32();
2140 893 : move32();
2141 893 : hStereoTCA->corrStatsSmoothFac_fx = 22938; // Q15
2142 893 : move16();
2143 :
2144 893 : set16_fx( hStereoTCA->corrLagStats, 0, 3 );
2145 893 : set16_fx( hStereoTCA->prevCorrLagStats, 0, 3 );
2146 :
2147 893 : set32_fx( hStereoTCA->memChanL_fx, 0, add( L_MEM_RECALC_48K, L_MEM_RECALC_48k_SCH ) );
2148 893 : set32_fx( hStereoTCA->memChanR_fx, 0, add( L_MEM_RECALC_48K, L_MEM_RECALC_48k_SCH ) );
2149 893 : hStereoTCA->memChan_q = 31;
2150 893 : move16();
2151 893 : set32_fx( hStereoTCA->memChanL_DS_fx, 0, ADDED_MEM_DS );
2152 893 : set32_fx( hStereoTCA->memChanR_DS_fx, 0, ADDED_MEM_DS );
2153 893 : hStereoTCA->memChan_DS_q = Q31;
2154 893 : move16();
2155 893 : hStereoTCA->mem_tempF_fx = 0;
2156 893 : move32();
2157 893 : hStereoTCA->mem_tempF_exp = 0;
2158 893 : move16();
2159 893 : set32_fx( hStereoTCA->corrEstPrev_fx[0], 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) );
2160 893 : set32_fx( hStereoTCA->corrEstPrev_fx[1], 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) );
2161 893 : set32_fx( hStereoTCA->corrEstPrev_fx[2], 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) );
2162 893 : hStereoTCA->corrEstPrev_exp = 0;
2163 893 : move16();
2164 893 : set32_fx( hStereoTCA->corrEstLT_fx, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) );
2165 893 : hStereoTCA->corrEstLT_exp = 0;
2166 893 : move16();
2167 893 : set32_fx( hStereoTCA->memdecim_fx, 0, 12 );
2168 893 : hStereoTCA->ica_envVarLT_fx = 2097152000; // 2000 in Q20
2169 893 : move32();
2170 893 : hStereoTCA->ica_envVarLT_exp = 11; // 2000 in Q20
2171 893 : move16();
2172 :
2173 893 : set32_fx( hStereoTCA->C_mem_fx, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) );
2174 893 : set16_fx( hStereoTCA->C_mem_exp, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) );
2175 893 : hStereoTCA->E1_mem_fx = 0;
2176 893 : move32();
2177 893 : hStereoTCA->E2_mem_fx = 0;
2178 893 : move32();
2179 893 : hStereoTCA->E1_mem_exp = 0;
2180 893 : move16();
2181 893 : hStereoTCA->E2_mem_exp = 0;
2182 893 : move16();
2183 893 : set32_fx( hStereoTCA->delay_0_mem_fx, 0, MAX_DELAYREGLEN );
2184 893 : hStereoTCA->delay_0_mem_exp = 0;
2185 893 : move16();
2186 893 : hStereoTCA->smooth_dist_reg_prv_corr_fx = MAX_32; // Q15
2187 893 : hStereoTCA->smooth_dist_reg_prv_corr_exp = 0; // Q15
2188 893 : hStereoTCA->LRTD_G_ATT_cnt = 1;
2189 893 : move16();
2190 893 : move16();
2191 :
2192 893 : return;
2193 : }
2194 : /*-------------------------------------------------------------------*
2195 : * Function unclr_calc_corr_features()
2196 : *
2197 : *-------------------------------------------------------------------*/
2198 3827 : static void unclr_calc_corr_features_fx(
2199 : STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier handle */
2200 : STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */
2201 : Word32 buf1[], /* i : left channel q_com*/
2202 : Word32 buf2[], /* i : right channel q_com*/
2203 : Word16 q_com,
2204 : const Word16 length, /* i : length of input signal buffers Q0*/
2205 : Word32 corrEst[], /* i : buffer containing inter-channel correlation values corrEst_exp*/
2206 : Word16 corrEst_exp,
2207 : const Word16 lagSearchRange[], /* i : minimum and maximum lags for corrEst[] Q0*/
2208 : Word32 *corrEst_ncorr, /* o : norm. x-correlation btw. current and previous correlation buffers corrEst_ncorr_exp*/
2209 : Word16 *corrEst_ncorr_exp )
2210 : {
2211 : Word16 i, corrLagMax, d_corrLagMax, tempLen, k;
2212 : Word32 num, den;
2213 : Word32 corrL, corrR, ener, ener_side, mono_i, side_i, ic_Lm, ic_Rm, tdm_es_em, m_corrL_corrR, d_corrL_corrR;
2214 : Word32 sum_prod, corrEstMax;
2215 : Word16 corrL_exp, corrR_exp, ener_exp, ener_side_exp, sum_prod_exp, exp, exp1, exp2, num_exp, den_exp;
2216 :
2217 3827 : corrL = ONE_IN_Q31;
2218 3827 : move32();
2219 3827 : corrL_exp = 0;
2220 3827 : move16();
2221 3827 : corrR = ONE_IN_Q31;
2222 3827 : move32();
2223 3827 : corrR_exp = 0;
2224 3827 : move16();
2225 3827 : ener = ONE_IN_Q31;
2226 3827 : move32();
2227 3827 : ener_exp = 0;
2228 3827 : move16();
2229 3827 : ener_side = ONE_IN_Q31;
2230 3827 : move32();
2231 3827 : ener_side_exp = 0;
2232 3827 : move16();
2233 3827 : sum_prod = 0;
2234 3827 : move32();
2235 3827 : sum_prod_exp = 0;
2236 3827 : move16();
2237 :
2238 616147 : FOR( i = 0; i < length; i++ )
2239 : {
2240 612320 : mono_i = BASOP_Util_Add_Mant32Exp( L_shr( buf1[i], 1 ), sub( 31, q_com ), L_shr( buf2[i], 1 ), sub( 31, q_com ), &exp ); /* Q31-exp */
2241 612320 : corrL = BASOP_Util_Add_Mant32Exp( corrL, corrL_exp, Mpy_32_32( buf1[i], mono_i ), add( sub( 31, q_com ), exp ), &corrL_exp ); /* Q31-corrL_exp */
2242 612320 : corrR = BASOP_Util_Add_Mant32Exp( corrR, corrR_exp, Mpy_32_32( buf2[i], mono_i ), add( sub( 31, q_com ), exp ), &corrR_exp ); /* Q31-corrR_exp */
2243 612320 : ener = BASOP_Util_Add_Mant32Exp( ener, ener_exp, Mpy_32_32( mono_i, mono_i ), shl( exp, 1 ), &ener_exp );
2244 :
2245 612320 : side_i = BASOP_Util_Add_Mant32Exp( L_shr( buf1[i], 1 ), sub( 31, q_com ), L_negate( L_shr( buf2[i], 1 ) ), sub( 31, q_com ), &exp ); /* Q31-exp */
2246 612320 : ener_side = BASOP_Util_Add_Mant32Exp( ener_side, ener_side_exp, Mpy_32_32( side_i, side_i ), shl( exp, 1 ), &ener_side_exp ); /* Q31-ener_side_exp */
2247 :
2248 : Word16 n1, n2, prod_i_exp;
2249 : Word32 x, y, prod_i;
2250 612320 : n1 = norm_l( buf1[i] );
2251 612320 : n2 = norm_l( buf2[i] );
2252 612320 : x = L_shl( buf1[i], n1 ); // q: q_com + n1
2253 612320 : y = L_shl( buf2[i], n2 ); // q: q_com + n2
2254 612320 : prod_i = Mpy_32_32( x, y ); // q: q_com * 2 + n1 + n2 - 31
2255 612320 : prod_i_exp = sub( 62, add( shl( q_com, 1 ), add( n1, n2 ) ) );
2256 612320 : sum_prod = BASOP_Util_Add_Mant32Exp( sum_prod, sum_prod_exp, prod_i, prod_i_exp, &sum_prod_exp ); /* Q31-sum_prod_exp */
2257 : }
2258 :
2259 : /* average energy of L and R channels */
2260 3827 : hStereoClassif->ave_ener_L_fx = Mpy_32_32( hStereoTCA->E1_mem_fx, 13421772 /* 1/length in Q31*/ ); /* Q31-hStereoClassif->ave_ener_L_fx_e */
2261 3827 : move32();
2262 3827 : hStereoClassif->ave_ener_L_fx_e = hStereoTCA->E1_mem_exp;
2263 3827 : move16();
2264 3827 : hStereoClassif->ave_ener_R_fx = Mpy_32_32( hStereoTCA->E2_mem_fx, 13421772 /* 1/length in Q31*/ ); /* Q31-hStereoClassif->ave_ener_R_fx_e */
2265 3827 : move32();
2266 3827 : hStereoClassif->ave_ener_R_fx_e = hStereoTCA->E2_mem_exp;
2267 3827 : move16();
2268 :
2269 : /* unnormalized L/R correlation */
2270 3827 : IF( sum_prod )
2271 : {
2272 3827 : sum_prod = BASOP_Util_Log10( L_abs( sum_prod ), sum_prod_exp ); /* Q31-sum_prod_exp */
2273 3827 : sum_prod_exp = 6;
2274 3827 : move16();
2275 : }
2276 : ELSE
2277 : {
2278 0 : sum_prod = 0;
2279 0 : move32();
2280 0 : sum_prod_exp = 0;
2281 0 : move16();
2282 : }
2283 :
2284 3827 : hStereoClassif->unclr_fv_fx[E_sum_prod] = L_shr( sum_prod, 10 ); // Q15
2285 3827 : move32();
2286 3827 : hStereoClassif->xtalk_fv_fx[E_sum_prod] = L_shr( sum_prod, 10 ); // Q15
2287 3827 : move32();
2288 : /* S/M energy ratio */
2289 3827 : Word32 inp1 = Sqrt32( Mpy_32_32( ener_side, 13421773 /* 1/L_FRAME_DS in Q31*/ ), &ener_side_exp ); /* Q31-ener_side_exp */
2290 3827 : inp1 = BASOP_Util_Log10( inp1, ener_side_exp ); /* Q31-ener_side_exp */
2291 3827 : Word16 temp = ener_exp;
2292 3827 : move16();
2293 3827 : Word32 inp2 = Sqrt32( Mpy_32_32( ener, 13421773 /* 1/L_FRAME_DS in Q31*/ ), &ener_exp ); /* Q31-ener_exp */
2294 3827 : inp2 = BASOP_Util_Log10( inp2, ener_exp ); /* Q31-ener_exp */
2295 3827 : ener_exp = temp;
2296 3827 : move16();
2297 :
2298 3827 : tdm_es_em = L_abs( Mpy_32_32( L_sub( inp1, inp2 ), 1342177280 ) ); /* Q25 + Q27 - Q31 = 21*/
2299 :
2300 3827 : hStereoClassif->unclr_fv_fx[E_tdm_es_em] = L_shr( tdm_es_em, 6 ); // Q15
2301 3827 : move32();
2302 3827 : hStereoClassif->xtalk_fv_fx[E_tdm_es_em] = L_shr( tdm_es_em, 6 ); // Q15
2303 3827 : move32();
2304 :
2305 : /* L/R correlation values (zero lag, maximum) */
2306 3827 : corrLagMax = maximum_l( corrEst, sub( lagSearchRange[1], add( lagSearchRange[0], 1 ) ), &corrEstMax );
2307 3827 : d_corrLagMax = sub( corrLagMax, hStereoClassif->unclr_corrLagMax_prev );
2308 :
2309 3827 : hStereoClassif->unclr_fv_fx[E_d_corrLagMax] = L_shl( d_corrLagMax, 15 );
2310 3827 : move32();
2311 3827 : hStereoClassif->unclr_corrLagMax_prev = corrLagMax;
2312 3827 : move32();
2313 3827 : hStereoClassif->xtalk_fv_fx[E_d_corrLagMax] = L_shl( d_corrLagMax, 15 );
2314 3827 : move32();
2315 :
2316 3827 : if ( corrEstMax < 0 )
2317 : {
2318 0 : corrEstMax = 0;
2319 0 : move32();
2320 : }
2321 :
2322 3827 : hStereoClassif->unclr_fv_fx[E_corrEst0] = L_shl( corrEst[abs_s( lagSearchRange[0] )], sub( corrEst_exp, 16 ) ); /* Q15 */
2323 3827 : move32();
2324 3827 : hStereoClassif->unclr_fv_fx[E_corrEstMax] = L_shl( corrEstMax, sub( corrEst_exp, 16 ) ); /* Q15 */
2325 3827 : move32();
2326 3827 : hStereoClassif->unclr_fv_fx[E_corrLagMax] = L_shl( corrLagMax, 15 ); /* Q15 */
2327 3827 : move32();
2328 3827 : hStereoClassif->xtalk_fv_fx[E_corrEst0] = L_shl( corrEst[abs_s( lagSearchRange[0] )], sub( corrEst_exp, 16 ) ); /* Q15 */
2329 3827 : move32();
2330 3827 : hStereoClassif->xtalk_fv_fx[E_corrEstMax] = L_shl( corrEstMax, sub( corrEst_exp, 16 ) ); /* Q15 */
2331 3827 : move32();
2332 3827 : hStereoClassif->xtalk_fv_fx[E_corrLagMax] = L_shl( corrLagMax, 15 ); /* Q15 */
2333 3827 : move32();
2334 :
2335 : /* L/M and R/M correlation */
2336 3827 : if ( corrL < 0 )
2337 : {
2338 113 : corrL = 0;
2339 113 : move32();
2340 : }
2341 :
2342 3827 : if ( corrR < 0 )
2343 : {
2344 58 : corrR = 0;
2345 58 : move32();
2346 : }
2347 :
2348 3827 : ic_Lm = BASOP_Util_Divide3232_Scale_newton( corrL, ener, &exp1 ); /* Q31-exp1 */
2349 3827 : exp1 = add( exp1, sub( corrL_exp, ener_exp ) );
2350 3827 : ic_Rm = BASOP_Util_Divide3232_Scale_newton( corrR, ener, &exp2 ); /* Q31-exp2 */
2351 3827 : exp2 = add( exp2, sub( corrR_exp, ener_exp ) );
2352 :
2353 3827 : m_corrL_corrR = L_sub( L_max( L_abs( L_shl( ic_Lm, sub( exp1, s_max( exp1, exp2 ) ) ) ), L_abs( L_shl( ic_Rm, sub( exp2, s_max( exp1, exp2 ) ) ) ) ), L_min( L_abs( L_shl( ic_Lm, sub( exp1, s_max( exp1, exp2 ) ) ) ), L_abs( L_shl( ic_Rm, sub( exp2, s_max( exp1, exp2 ) ) ) ) ) ); // s_max(exp1, exp2)
2354 :
2355 3827 : inp1 = BASOP_Util_Add_Mant32Exp( corrL, corrL_exp, L_negate( corrR ), corrR_exp, &exp ); /* Q31-exp */
2356 3827 : IF( inp1 )
2357 : {
2358 3827 : d_corrL_corrR = BASOP_Util_Log10( L_abs( inp1 ), exp ); // Q25
2359 : }
2360 : ELSE
2361 : {
2362 0 : d_corrL_corrR = 0;
2363 0 : move32();
2364 : }
2365 :
2366 3827 : hStereoClassif->unclr_fv_fx[E_m_corrL_corrR] = L_shl( m_corrL_corrR, sub( s_max( exp1, exp2 ), 16 ) ); // Q15
2367 3827 : move32();
2368 3827 : hStereoClassif->unclr_fv_fx[E_d_corrL_corrR] = L_shr( d_corrL_corrR, 10 ); // Q15
2369 3827 : move32();
2370 3827 : hStereoClassif->xtalk_fv_fx[E_m_corrL_corrR] = L_shl( m_corrL_corrR, sub( s_max( exp1, exp2 ), 16 ) ); // Q15
2371 3827 : move32();
2372 :
2373 : /* norm. x-correlation btw. current and previous correlation buffers */
2374 3827 : tempLen = ( 2 * L_NCSHIFT_DS + 1 );
2375 3827 : move16();
2376 :
2377 3827 : Word64 L64_sum = 0;
2378 3827 : move64();
2379 313814 : FOR( k = 0; k < tempLen; k++ )
2380 : {
2381 309987 : L64_sum = W_mac_32_32( L64_sum, corrEst[k], hStereoTCA->corrEstPrev_fx[2][k] ); /* 2*(Q31-corrEst_exp)+1 */
2382 : }
2383 3827 : k = W_norm( L64_sum );
2384 3827 : L64_sum = W_shl( L64_sum, k ); /* 2*(Q31-corrEst_exp)+1+k */
2385 3827 : num = W_extract_h( L64_sum ); // ener_side_q
2386 3827 : num_exp = sub( 31, sub( add( add( add( sub( 31, corrEst_exp ), sub( 31, hStereoTCA->corrEstPrev_exp ) ), 1 ), k ), 32 ) );
2387 :
2388 3827 : exp1 = corrEst_exp;
2389 3827 : move16();
2390 3827 : inp1 = sum2_32_exp_fx( corrEst, tempLen, &exp1, 3 );
2391 :
2392 3827 : exp2 = hStereoTCA->corrEstPrev_exp;
2393 3827 : move16();
2394 3827 : inp2 = sum2_32_exp_fx( hStereoTCA->corrEstPrev_fx[2], tempLen, &exp2, 3 );
2395 :
2396 3827 : den_exp = add( exp1, exp2 );
2397 3827 : den = Sqrt32( Mpy_32_32( inp1, inp2 ), &den_exp ); /* Q31-den_exp */
2398 :
2399 3827 : IF( den == 0 )
2400 : {
2401 62 : *corrEst_ncorr = 0;
2402 62 : move32();
2403 62 : *corrEst_ncorr_exp = 0;
2404 62 : move16();
2405 : }
2406 : ELSE
2407 : {
2408 3765 : *corrEst_ncorr = BASOP_Util_Divide3232_Scale_newton( num, den, &exp ); /* Q31-corrEst_ncorr_exp */
2409 3765 : *corrEst_ncorr_exp = add( exp, sub( num_exp, den_exp ) );
2410 3765 : move32();
2411 3765 : move16();
2412 : }
2413 :
2414 3827 : hStereoClassif->unclr_fv_fx[E_corrEst_ncorr] = L_shl( *corrEst_ncorr, sub( *corrEst_ncorr_exp, 16 ) ); /* Q15 */
2415 3827 : move32();
2416 3827 : hStereoClassif->xtalk_fv_fx[E_corrEst_ncorr] = L_shl( *corrEst_ncorr, sub( *corrEst_ncorr_exp, 16 ) ); /* Q15 */
2417 3827 : move32();
2418 :
2419 3827 : return;
2420 : }
|