Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : #include <stdint.h>
34 : #include "options.h"
35 : #include <math.h>
36 : #include "ivas_cnst.h"
37 : #include "ivas_prot_fx.h"
38 : #include "prot_fx.h"
39 : #include "prot_fx_enc.h"
40 : #include "wmc_auto.h"
41 : #include <assert.h>
42 :
43 :
44 : /*--------------------------------------------------------------*
45 : * Local constants
46 : *---------------------------------------------------------------*/
47 :
48 : #define SPAR_CORR_THRES 0.9f
49 : #define DEFAULT_CORR_THRES 0.3f
50 : #define SPAR_CORR_THRES_Q31 1932735283
51 : #define DEFAULT_CORR_THRES_Q31 644245094
52 :
53 : /*-------------------------------------------------------------------------
54 : * getChannelEnergies()
55 : *
56 : * Calculate energy for each cahnnel
57 : *-------------------------------------------------------------------------*/
58 201419 : void getChannelEnergies_fx(
59 : Encoder_State **sts, /* i/o: Encoder state structure */
60 : Word32 nrg[MCT_MAX_CHANNELS], /* o : buffer with energies for each channel */
61 : Word16 nrg_e[MCT_MAX_CHANNELS], /* o : exponents of energies for each channel */
62 : const Word16 nchan /* i : number of channels */
63 : )
64 : {
65 : Word16 ch, n, gb, sum2_e;
66 : Word32 sum2;
67 : Word16 nSubframes, L_subframe;
68 : Encoder_State *st;
69 :
70 : /* Calculate energies per channel */
71 1162962 : FOR( ch = 0; ch < nchan; ch++ )
72 : {
73 961543 : st = sts[ch];
74 961543 : IF( NE_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
75 : {
76 946185 : IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) )
77 : {
78 924929 : nSubframes = 1;
79 924929 : move16();
80 924929 : L_subframe = st->hTcxEnc->L_frameTCX;
81 924929 : move16();
82 : }
83 : ELSE
84 : {
85 21256 : nSubframes = NB_DIV;
86 21256 : move16();
87 21256 : L_subframe = shr( st->hTcxEnc->L_frameTCX, 1 );
88 : }
89 :
90 946185 : gb = find_guarded_bits_fx( (Word32) L_subframe );
91 :
92 946185 : sum2_e = st->hTcxEnc->spectrum_e[0];
93 946185 : move16();
94 946185 : nrg[ch] = 0;
95 946185 : move32();
96 1913626 : FOR( n = 0; n < nSubframes; n++ )
97 : {
98 967441 : sum2 = sum2_32_exp_fx( st->hTcxEnc->spectrum_fx[n], L_subframe, &sum2_e, gb ); // 31 - sum2_e
99 :
100 967441 : nrg[ch] = BASOP_Util_Add_Mant32Exp( nrg[ch], nrg_e[ch], sum2, sum2_e, &nrg_e[ch] );
101 967441 : move32();
102 :
103 967441 : sum2_e = st->hTcxEnc->spectrum_e[0];
104 967441 : move16();
105 : }
106 :
107 946185 : nrg[ch] = Sqrt32( nrg[ch], &nrg_e[ch] ); // nrg_e
108 946185 : move32();
109 : }
110 : }
111 :
112 201419 : return;
113 : }
114 :
115 :
116 : /*-------------------------------------------------------------------------
117 : * getNextBestCorrelation()
118 : *
119 : * find channel pair with highest cross-correlation
120 : *-------------------------------------------------------------------------*/
121 100985 : static void getNextBestCorrelation_fx(
122 : Word32 xCorrMatrix[][MCT_MAX_CHANNELS], /* i : cross-correlation matrix, Qx */
123 : Word16 *_ch1, /* o : first channel of selected channel-pair */
124 : Word16 *_ch2, /* o : second channel of selected channel-pair, Qx */
125 : Word32 *max_corr, /* o : normalized cross correlation value of selected channel pair */
126 : const Word16 sortInd,
127 : const Word16 nChannels )
128 : {
129 : Word32 tmp_corrVals[( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2];
130 : Word16 tmp_org[( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2];
131 : Word16 i, tmp_idx;
132 : Word16 ch1, ch2;
133 :
134 100985 : set32_fx( tmp_corrVals, 0, ( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2 );
135 :
136 : /* first sort correlation matrix */
137 100985 : i = 0;
138 100985 : move16();
139 593996 : FOR( ch1 = 0; ch1 < nChannels; ch1++ )
140 : {
141 1658027 : FOR( ch2 = ch1 + 1; ch2 < nChannels; ch2++ )
142 : {
143 1165016 : IF( L_abs( xCorrMatrix[ch1][ch2] ) > 0 )
144 : {
145 726675 : assert( i < ( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2 );
146 726675 : tmp_corrVals[i] = L_abs( xCorrMatrix[ch1][ch2] ); // Qx
147 726675 : move32();
148 726675 : i = add( i, 1 );
149 : }
150 : }
151 : }
152 :
153 100985 : tmp_idx = sub( shr( imult1616( nChannels, sub( nChannels, 1 ) ), 1 ), 1 );
154 :
155 : /* sort values */
156 100985 : v_sort_ind_fixed( tmp_corrVals, tmp_org, add( tmp_idx, 1 ) );
157 :
158 : /* get max, or 2nd max and so on depending on sortInd value */
159 100985 : *max_corr = tmp_corrVals[( tmp_idx - sortInd )]; // Qx
160 100985 : move32();
161 :
162 : /*find channel pair for this max_corr*/
163 593996 : FOR( ch1 = 0; ch1 < nChannels; ch1++ )
164 : {
165 1378593 : FOR( ch2 = ch1 + 1; ch2 < nChannels; ch2++ )
166 : {
167 1014277 : IF( EQ_32( L_abs( xCorrMatrix[ch1][ch2] ), *max_corr ) )
168 : {
169 128695 : *_ch1 = ch1;
170 128695 : *_ch2 = ch2;
171 128695 : *max_corr = xCorrMatrix[ch1][ch2]; /* assign to max_corr its actual value */ // Qx
172 128695 : move16();
173 128695 : move16();
174 128695 : move32();
175 128695 : BREAK;
176 : }
177 : }
178 : }
179 :
180 100985 : return;
181 : }
182 :
183 :
184 : /*-----------------------------------------------------------------------*
185 : * getCorrelationMatrix()
186 : *
187 : * calculates the cross correlation matrix for all active
188 : * channels
189 : *-----------------------------------------------------------------------*/
190 100480 : static void getCorrelationMatrix_fx(
191 : Encoder_State **sts, /* i : core coder handle */
192 : MCT_ENC_HANDLE hMCT, /* i : MCT handle */
193 : Word32 xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS], /* o : cross-correlation matrix, exponent: xCorrMatrix_e */
194 : Word16 *xCorrMatrix_e /* o : exponent of cross-correlation matrix */
195 : )
196 : {
197 : Word16 ch1, ch2, n, nchan, res_q, s, max_e;
198 : Word16 xCorrMatrix_exp[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS];
199 : Word32 L_tmp;
200 : Word64 W_tmp;
201 :
202 100480 : nchan = hMCT->nchan_out_woLFE;
203 100480 : move16();
204 :
205 : /* correlation */
206 580236 : FOR( ch1 = 0; ch1 < nchan; ch1++ )
207 : {
208 2017233 : FOR( ch2 = ch1; ch2 < nchan; ch2++ )
209 : {
210 1537477 : xCorrMatrix[ch1][ch2] = 0;
211 1537477 : move32();
212 1537477 : xCorrMatrix_exp[ch1][ch2] = 0;
213 1537477 : move16();
214 :
215 1537477 : test();
216 1537477 : test();
217 1537477 : IF( EQ_16( sts[ch1]->core, sts[ch2]->core ) && NE_32( sts[ch1]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) &&
218 : NE_32( sts[ch2]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
219 : {
220 : Word16 nSubframes;
221 : Word16 L_subframe;
222 1473574 : IF( EQ_16( sts[ch1]->core, TCX_20 ) )
223 : {
224 1449982 : nSubframes = 1;
225 1449982 : move16();
226 1449982 : L_subframe = sts[ch1]->hTcxEnc->L_frameTCX;
227 1449982 : move16();
228 : }
229 : ELSE
230 : {
231 23592 : nSubframes = NB_DIV;
232 23592 : move16();
233 23592 : L_subframe = shr( sts[ch1]->hTcxEnc->L_frameTCX, 1 );
234 : }
235 :
236 2970740 : FOR( n = 0; n < nSubframes; n++ )
237 : {
238 1497166 : res_q = sub( 31, sts[0]->hTcxEnc->spectrum_e[0] );
239 1497166 : L_tmp = dotp_fixed_32( sts[ch1]->hTcxEnc->spectrum_fx[n], sts[ch2]->hTcxEnc->spectrum_fx[n], L_subframe, 1, &res_q );
240 1497166 : xCorrMatrix[ch1][ch2] = BASOP_Util_Add_Mant32Exp( xCorrMatrix[ch1][ch2], xCorrMatrix_exp[ch1][ch2], L_tmp, sub( 31, res_q ), &xCorrMatrix_exp[ch1][ch2] );
241 1497166 : move32();
242 : }
243 : }
244 : }
245 : }
246 :
247 : /* normalize */
248 580236 : FOR( ch1 = 0; ch1 < nchan; ch1++ )
249 : {
250 1537477 : FOR( ch2 = ch1 + 1; ch2 < nchan; ch2++ )
251 : {
252 : // tmp = sqrtf( xCorrMatrix[ch1][ch1] * xCorrMatrix[ch2][ch2] );
253 1057721 : W_tmp = W_mult0_32_32( xCorrMatrix[ch1][ch1], xCorrMatrix[ch2][ch2] ); // ( 31 - xCorrMatrix_exp[ch1][ch1] ) + ( 31 - xCorrMatrix_exp[ch2][ch2] )
254 1057721 : s = W_norm( W_tmp );
255 1057721 : L_tmp = W_extract_h( W_shl( W_tmp, s ) ); // s + ( 31 - xCorrMatrix_exp[ch1][ch1] ) + ( 31 - xCorrMatrix_exp[ch2][ch2] ) - 32
256 :
257 1057721 : s = sub( add( s, 30 ), add( xCorrMatrix_exp[ch1][ch1], xCorrMatrix_exp[ch2][ch2] ) ); // s = s + ( 31 - xCorrMatrix_exp[ch1][ch1] ) + ( 31 - xCorrMatrix_exp[ch2][ch2] ) - 32;
258 1057721 : s = sub( 31, s );
259 1057721 : L_tmp = Sqrt32( L_tmp, &s );
260 :
261 1057721 : IF( L_tmp > 0 )
262 : {
263 : // xCorrMatrix[ch1][ch2] /= tmp;
264 1026778 : xCorrMatrix[ch1][ch2] = L_deposit_h( BASOP_Util_Divide3232_Scale( xCorrMatrix[ch1][ch2], L_tmp, &res_q ) );
265 1026778 : xCorrMatrix_exp[ch1][ch2] = add( res_q, sub( xCorrMatrix_exp[ch1][ch2], s ) );
266 1026778 : move32();
267 1026778 : move16();
268 : }
269 : ELSE
270 : {
271 30943 : xCorrMatrix[ch1][ch2] = 0;
272 30943 : xCorrMatrix_exp[ch1][ch2] = 0;
273 30943 : move32();
274 30943 : move16();
275 : }
276 : }
277 : }
278 :
279 : /* Aligning the variable exponents for each element to a common exponent */
280 100480 : s = 31;
281 100480 : *xCorrMatrix_e = 0;
282 100480 : move16();
283 100480 : move16();
284 :
285 479756 : FOR( ch1 = 0; ch1 < nchan - 1; ch1++ )
286 : {
287 379276 : s = s_min( s, getScaleFactor32( &xCorrMatrix[ch1][ch1 + 1], sub( nchan, add( ch1, 1 ) ) ) );
288 379276 : maximum_s( &xCorrMatrix_exp[ch1][ch1 + 1], sub( nchan, add( ch1, 1 ) ), &max_e );
289 379276 : *xCorrMatrix_e = s_max( *xCorrMatrix_e, max_e );
290 379276 : move16();
291 : }
292 :
293 580236 : FOR( ch1 = 0; ch1 < nchan; ch1++ )
294 : {
295 1537477 : FOR( ch2 = ch1 + 1; ch2 < nchan; ch2++ )
296 : {
297 1057721 : xCorrMatrix[ch1][ch2] = L_shl_sat( xCorrMatrix[ch1][ch2], add( s, sub( xCorrMatrix_exp[ch1][ch2], *xCorrMatrix_e ) ) ); // xCorrMatrix_e - s
298 1057721 : move32();
299 : }
300 : }
301 100480 : *xCorrMatrix_e = sub( *xCorrMatrix_e, s );
302 100480 : move16();
303 :
304 100480 : return;
305 : }
306 :
307 :
308 : /*-----------------------------------------------------------------*
309 : * getBestCorrelation()
310 : *
311 : * searches for the best correlated channel pair
312 : *------------------------------------------------------------------*/
313 96449 : static void getBestCorrelation_fx(
314 : MCT_ENC_HANDLE hMCT, /* i : MCT handle */
315 : Word16 *_ch1, /* o : first channel of selected channel-pair, Q0 */
316 : Word16 *_ch2, /* o : second channel of selected channel-pair, Q0 */
317 : Word32 *max_corr, /* o : normalized cross correlation value of selected channel pair, Qx */
318 : Word32 xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS] ) /* i : cross-correlation matrix, Qx */
319 : {
320 : Word16 ch1, ch2;
321 :
322 96449 : *_ch1 = -1;
323 96449 : *_ch2 = -1;
324 96449 : *max_corr = 0;
325 96449 : move16();
326 96449 : move16();
327 96449 : move32();
328 :
329 640848 : FOR( ch1 = 0; ch1 < ( hMCT->nchan_out_woLFE ); ch1++ )
330 : {
331 1986092 : FOR( ch2 = ch1 + 1; ch2 < ( hMCT->nchan_out_woLFE ); ch2++ )
332 : {
333 1441693 : IF( LT_32( L_abs( *max_corr ), L_abs( xCorrMatrix[ch1][ch2] ) ) )
334 : {
335 199075 : *max_corr = xCorrMatrix[ch1][ch2]; // Qx
336 199075 : move32();
337 :
338 199075 : *_ch1 = ch1;
339 199075 : *_ch2 = ch2;
340 199075 : move16();
341 199075 : move16();
342 : }
343 : }
344 : }
345 :
346 96449 : return;
347 : }
348 :
349 :
350 : /*----------------------------------------------------------------------*
351 : * getBlockValues()
352 : * stereo processing for the channels of current block
353 : *----------------------------------------------------------------------*/
354 97034 : static void getBlockValues_fx(
355 : Encoder_State **sts, /* i/o: core coder handle */
356 : const Word16 ch1, /* i : first channel of channel-pair */
357 : const Word16 ch2, /* i : second channel of channel-pair */
358 : MCT_BLOCK_DATA *hBlock, /* i : stereo block handle */
359 : Word32 *mdst_spectrum[MCT_MAX_CHANNELS][2], /* i/o: MDST spectrum, Q = q_spec */
360 : Word32 *inv_spectrum[MCT_MAX_CHANNELS][2], /* i/o: inverse spectrum, Q = q_spec */
361 : Word32 *inv_mdst_spectrum[MCT_MAX_CHANNELS][2], /* i/o: invers MDST spectrum, Q = q_spec */
362 : Word16 q_spec /* i : common Q factor of the above spectrum buffers */
363 : )
364 : {
365 : Word16 n;
366 : Word32 *p_mdst_spectrum[2][2];
367 : Word32 *p_inv_spectrum[2][2];
368 : Word32 *p_inv_mdst_spectrum[2][2];
369 : Encoder_State *p_st[2];
370 :
371 : /* init return values: */
372 97034 : hBlock->isActive = 1;
373 97034 : move16();
374 :
375 : /* map vectors to current block channels */
376 291102 : FOR( n = 0; n < 2; n++ )
377 : {
378 194068 : p_mdst_spectrum[0][n] = mdst_spectrum[ch1][n]; // q_spec
379 194068 : p_mdst_spectrum[1][n] = mdst_spectrum[ch2][n]; // q_spec
380 194068 : p_inv_spectrum[0][n] = inv_spectrum[ch1][n]; // q_spec
381 194068 : p_inv_spectrum[1][n] = inv_spectrum[ch2][n]; // q_spec
382 194068 : p_inv_mdst_spectrum[0][n] = inv_mdst_spectrum[ch1][n]; // q_spec
383 194068 : p_inv_mdst_spectrum[1][n] = inv_mdst_spectrum[ch2][n]; // q_spec
384 : }
385 97034 : p_st[0] = sts[ch1];
386 97034 : p_st[1] = sts[ch2];
387 :
388 97034 : stereo_coder_tcx_fx( hBlock->hStereoMdct, p_st, hBlock->mask, p_mdst_spectrum, p_inv_spectrum, p_inv_mdst_spectrum, 1, sub( 31, q_spec ), sub( 31, q_spec ) );
389 :
390 97034 : test();
391 97034 : test();
392 97034 : test();
393 97034 : test();
394 97034 : if ( ( EQ_16( sts[ch1]->core, TCX_20_CORE ) && hBlock->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO ) || ( EQ_16( sts[ch1]->core, TCX_10_CORE ) && hBlock->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO && hBlock->hStereoMdct->mdct_stereo_mode[1] == SMDCT_DUAL_MONO ) )
395 : {
396 4868 : hBlock->isActive = 0;
397 4868 : move16();
398 : }
399 :
400 97034 : return;
401 : }
402 :
403 :
404 : /*-------------------------------------------------------------------*
405 : * updateCorrelationMatrix()
406 : *
407 : * updates the cross correlation matrix with modified spectra after
408 : * stereo block processing
409 : *-------------------------------------------------------------------*/
410 92166 : static void updateCorrelationMatrix_fx(
411 : Encoder_State **sts,
412 : MCT_ENC_HANDLE hMCT,
413 : const Word16 _ch1,
414 : const Word16 _ch2,
415 : Word32 xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS] // Qx
416 : )
417 : {
418 : Word16 ch1, ch2, n;
419 :
420 : /* correlation: */
421 619178 : FOR( ch1 = 0; ch1 < ( hMCT->nchan_out_woLFE ); ch1++ )
422 : {
423 2512762 : FOR( ch2 = ch1; ch2 < ( hMCT->nchan_out_woLFE ); ch2++ )
424 : {
425 1985750 : test();
426 1985750 : test();
427 1985750 : IF( EQ_16( sts[ch1]->core, sts[ch2]->core ) && NE_32( sts[ch1]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) &&
428 : NE_32( sts[ch2]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
429 : {
430 : Word16 nSubframes;
431 1917213 : IF( EQ_16( sts[ch1]->core, TCX_20 ) )
432 : {
433 1874783 : nSubframes = 1;
434 1874783 : move16();
435 : }
436 : ELSE
437 : {
438 42430 : nSubframes = NB_DIV;
439 42430 : move16();
440 : }
441 :
442 1917213 : test();
443 1917213 : test();
444 1917213 : test();
445 1917213 : IF( EQ_16( ch1, _ch1 ) || EQ_16( ch2, _ch2 ) || EQ_16( ch1, _ch2 ) || EQ_16( ch2, _ch1 ) )
446 : {
447 1885128 : FOR( n = 0; n < nSubframes; n++ )
448 : {
449 950716 : xCorrMatrix[ch1][ch2] = 0; /*disable combinations with channels already processed */
450 950716 : move32();
451 : }
452 : }
453 : }
454 : }
455 : }
456 :
457 92166 : return;
458 : }
459 :
460 :
461 : /*----------------------------------------------------------*
462 : * channelPairToIndex()
463 : * get the index of each channel pair
464 : *----------------------------------------------------------*/
465 92166 : static Word16 channelPairToIndex_fx(
466 : const Word16 chIdx1,
467 : const Word16 chIdx2,
468 : const Word16 nChannels )
469 : {
470 : Word16 ch1, ch2;
471 : Word16 pairIdx;
472 :
473 92166 : pairIdx = 0;
474 92166 : move16();
475 :
476 351271 : FOR( ch2 = 1; ch2 < nChannels; ch2++ )
477 : {
478 1140781 : FOR( ch1 = 0; ch1 < ch2; ch1++ )
479 : {
480 881676 : test();
481 881676 : IF( EQ_16( ch1, chIdx1 ) && EQ_16( ch2, chIdx2 ) )
482 : {
483 92166 : return pairIdx;
484 : }
485 : ELSE
486 : {
487 789510 : pairIdx = add( pairIdx, 1 );
488 : }
489 : }
490 : }
491 :
492 0 : return -1;
493 : }
494 :
495 : /*--------------------------------------------------------------------*
496 : * getGlobalILD()
497 : * get broadband ILD to mean energy and normalize channels with ratio
498 : *--------------------------------------------------------------------*/
499 100480 : static void getGlobalILD_fx(
500 : Encoder_State **sts,
501 : MCT_ENC_HANDLE hMCT,
502 : Word32 *mdst_spectrum[MCT_MAX_CHANNELS][2], // Exponent is same as spectrum_fx i.e. spectrum_e
503 : const Word16 nchan )
504 : {
505 : Word16 k, ch, nSubframes, L_subframe;
506 : Word32 nrg[MCT_MAX_CHANNELS];
507 : Word16 nrg_e[MCT_MAX_CHANNELS];
508 : Word16 ratio_fx, qratio;
509 100480 : Word32 meanE = 0;
510 : Word32 L_tmp;
511 100480 : Word16 cnt = 0, meanE_e = 0, L_tmp_e;
512 100480 : move32();
513 100480 : move16();
514 100480 : move16();
515 :
516 : /*Initializations*/
517 100480 : set16_fx( hMCT->lowE_ch, 0, nchan );
518 :
519 100480 : getChannelEnergies_fx( sts, nrg, nrg_e, nchan );
520 :
521 : /*calculate total energy without LFE*/
522 580236 : FOR( ch = 0; ch < nchan; ch++ )
523 : {
524 479756 : IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
525 : {
526 472934 : meanE = BASOP_Util_Add_Mant32Exp( meanE, meanE_e, nrg[ch], nrg_e[ch], &meanE_e );
527 472934 : cnt = add( cnt, 1 );
528 : }
529 : }
530 :
531 : /*calculate mean energy*/
532 100480 : assert( cnt >= 2 );
533 100480 : L_tmp = BASOP_Util_Divide3216_Scale( meanE, cnt, &L_tmp_e );
534 100480 : L_tmp_e = add( L_tmp_e, sub( meanE_e, 15 ) );
535 :
536 : // meanE = max( meanE / cnt, EPSILON );
537 100480 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_tmp, L_tmp_e, EPSILON_FX_M, EPSILON_FX_E ), 1 ) )
538 : {
539 100480 : meanE = L_deposit_h( (Word16) L_tmp );
540 100480 : meanE_e = L_tmp_e;
541 100480 : move32();
542 100480 : move16();
543 : }
544 : ELSE
545 : {
546 0 : meanE = EPSILON_FX_M;
547 0 : meanE_e = EPSILON_FX_E;
548 0 : move32();
549 0 : move16();
550 : }
551 :
552 580236 : FOR( ch = 0; ch < nchan; ch++ )
553 : {
554 479756 : IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
555 : {
556 472934 : IF( EQ_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) )
557 : {
558 462306 : nSubframes = 1;
559 462306 : move16();
560 462306 : L_subframe = sts[ch]->hTcxEnc->L_frameTCX;
561 462306 : move16();
562 : }
563 : ELSE
564 : {
565 10628 : nSubframes = NB_DIV;
566 10628 : move16();
567 10628 : L_subframe = shr( sts[ch]->hTcxEnc->L_frameTCX, 1 );
568 : }
569 :
570 472934 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( nrg[ch], nrg_e[ch], meanE, meanE_e ), 1 ) ) /*change it to meanE if final solution*/
571 : {
572 : // ratio_fx = meanE / nrg[ch];
573 174644 : ratio_fx = BASOP_Util_Divide3232_Scale( meanE, nrg[ch], &L_tmp_e );
574 174644 : L_tmp_e = add( L_tmp_e, sub( meanE_e, nrg_e[ch] ) );
575 174644 : ratio_fx = shl_sat( ratio_fx, L_tmp_e );
576 :
577 174644 : hMCT->mc_global_ild[ch] = s_max( 1, s_min( SMDCT_ILD_RANGE - 1, mult_r( SMDCT_ILD_RANGE, ratio_fx ) ) );
578 174644 : move16();
579 :
580 174644 : qratio = div_l( L_shl( hMCT->mc_global_ild[ch], 11 ), SMDCT_ILD_RANGE / 2 ); // Q11
581 : }
582 : ELSE
583 : {
584 : // ratio_fx = nrg[ch] / meanE;
585 298290 : ratio_fx = BASOP_Util_Divide3232_Scale( nrg[ch], meanE, &L_tmp_e );
586 298290 : L_tmp_e = add( L_tmp_e, sub( nrg_e[ch], meanE_e ) );
587 298290 : ratio_fx = shl_sat( ratio_fx, L_tmp_e );
588 :
589 298290 : hMCT->lowE_ch[ch] = 1;
590 298290 : move16();
591 :
592 298290 : hMCT->mc_global_ild[ch] = s_max( 1, s_min( SMDCT_ILD_RANGE - 1, mult_r( SMDCT_ILD_RANGE, ratio_fx ) ) );
593 298290 : move16();
594 :
595 298290 : qratio = shl_sat( div_l( ( (Word32) SMDCT_ILD_RANGE << 11 ), hMCT->mc_global_ild[ch] ), 1 ); // Q11
596 : }
597 :
598 956496 : FOR( k = 0; k < nSubframes; k++ )
599 : {
600 483562 : sts[ch]->hTcxEnc->spectrum_e[k] = add( sts[ch]->hTcxEnc->spectrum_e[k], 4 ); // Updating exponent of spectrum as q_ratio is in Q11
601 : }
602 472934 : IF( GT_16( nSubframes, 1 ) )
603 : {
604 10628 : sts[ch]->hTcxEnc->spectrum_long_e = add( sts[ch]->hTcxEnc->spectrum_long_e, 4 );
605 10628 : move16();
606 : }
607 :
608 956496 : FOR( k = 0; k < nSubframes; k++ )
609 : {
610 483562 : v_multc_fixed( sts[ch]->hTcxEnc->spectrum_fx[k], L_deposit_h( qratio ), sts[ch]->hTcxEnc->spectrum_fx[k], L_subframe ); // sts[ch]->hTcxEnc->spectrum_e
611 483562 : v_multc_fixed( mdst_spectrum[ch][k], L_deposit_h( qratio ), mdst_spectrum[ch][k], L_subframe ); // sts[ch]->hTcxEnc->spectrum_e
612 : }
613 : }
614 : }
615 :
616 :
617 100480 : return;
618 : }
619 :
620 :
621 : /*--------------------------------------------------------------------*
622 : * apply_MCT_enc()
623 : *
624 : * apply MCT algorithm to input channels
625 : *--------------------------------------------------------------------*/
626 100939 : void apply_MCT_enc_fx(
627 : MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */
628 : Encoder_State **sts, /* i/o: encoder state structure */
629 : Word32 *mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: MDST spectrum Qx*/
630 : Word32 *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse spectrum Qx*/
631 : Word32 *inv_mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum Qx*/
632 : const Word16 nchan /* i : number of channels */
633 : )
634 : {
635 : Word16 ch, k, ch1, ch2, nSubframes, L_subframeTCX;
636 : Word32 max_corr;
637 : Word16 forceKeepTree, pair, qratio;
638 : Word32 sumCorrDiff, thr;
639 : Word32 xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS];
640 : Word16 currBlockDataCnt;
641 : Word16 cpEle[MCT_MAX_CHANNELS];
642 : Word16 inactiveBlockDetected;
643 : Word16 tmp_ch1, tmp_ch2, tmp;
644 : Word32 tmp_max_corr, L_tmp;
645 100939 : Word16 count_active_ch = 0;
646 100939 : Word16 xCorrMatrix_e = 0, sumCorrDiff_e = 0, L_tmp_e;
647 100939 : move16();
648 100939 : move16();
649 100939 : move16();
650 :
651 100939 : push_wmops( "mct_core_enc_mct" );
652 :
653 100939 : forceKeepTree = 1;
654 100939 : inactiveBlockDetected = 0;
655 100939 : move16();
656 100939 : move16();
657 100939 : set16_fx( cpEle, 0, MCT_MAX_CHANNELS );
658 :
659 : /*Determine active channels*/
660 582726 : FOR( ch = 0; ch < nchan; ch++ )
661 : {
662 481787 : IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
663 : {
664 473251 : count_active_ch = add( count_active_ch, 1 );
665 : }
666 : ELSE
667 : {
668 8536 : hMCT->mc_global_ild[ch] = 0;
669 8536 : move16();
670 : }
671 : }
672 :
673 : /*there should be at least one cp*/
674 100939 : IF( GE_16( count_active_ch, CPE_CHANNELS ) )
675 : {
676 : /*Normalize energies with global ILD*/
677 100480 : getGlobalILD_fx( sts, hMCT, mdst_spectrum, nchan );
678 100480 : getCorrelationMatrix_fx( sts, hMCT, xCorrMatrix, &xCorrMatrix_e );
679 :
680 : /*check if previous tree should be kept*/
681 100480 : sumCorrDiff = 0;
682 100480 : move32();
683 : // thr = 0.15f * (float) ( count_active_ch ) * ( count_active_ch - 1 ) / 2.0f;
684 100480 : thr = Mpy_32_16_1( 161061274, imult1616( count_active_ch, sub( count_active_ch, 1 ) ) ); /* Q16 */ /* 161061274 = 0.15 / 2 in Q31 */
685 :
686 479756 : FOR( ch2 = 1; ch2 < nchan; ch2++ )
687 : {
688 1436997 : FOR( ch1 = 0; ch1 < ch2; ch1++ )
689 : {
690 1057721 : test();
691 1057721 : IF( NE_32( sts[ch1]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) &&
692 : NE_32( sts[ch2]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
693 : {
694 1026778 : L_tmp = L_abs( BASOP_Util_Add_Mant32Exp( hMCT->lastxCorrMatrix_fx[ch1][ch2], hMCT->lastxCorrMatrix_e, L_negate( xCorrMatrix[ch1][ch2] ), xCorrMatrix_e, &L_tmp_e ) );
695 1026778 : sumCorrDiff = BASOP_Util_Add_Mant32Exp( sumCorrDiff, sumCorrDiff_e, L_tmp, L_tmp_e, &sumCorrDiff_e );
696 : }
697 : }
698 : }
699 :
700 100480 : if ( EQ_16( BASOP_Util_Cmp_Mant32Exp( sumCorrDiff, sumCorrDiff_e, thr, 15 ), 1 ) )
701 : {
702 40728 : forceKeepTree = 0;
703 40728 : move16();
704 : }
705 :
706 : /* check if keepTree is applied on unallowed blocks (e.g. channel pairs with different cores) */
707 100480 : IF( forceKeepTree )
708 : {
709 59752 : IF( !hMCT->currBlockDataCnt )
710 : {
711 22629 : forceKeepTree = 0;
712 22629 : move16();
713 : }
714 : ELSE
715 : {
716 102586 : FOR( pair = 0; pair < hMCT->currBlockDataCnt; pair++ )
717 : {
718 65463 : if ( xCorrMatrix[hMCT->hBlockData[pair]->ch1][hMCT->hBlockData[pair]->ch2] == 0 )
719 : {
720 131 : forceKeepTree = 0;
721 131 : move16();
722 : }
723 : }
724 : }
725 : }
726 :
727 : /*save initial correlation matrix for next frame*/
728 580236 : FOR( ch1 = 0; ch1 < nchan; ch1++ )
729 : {
730 2017233 : FOR( ch2 = ch1; ch2 < nchan; ch2++ )
731 : {
732 1537477 : hMCT->lastxCorrMatrix_fx[ch1][ch2] = xCorrMatrix[ch1][ch2];
733 1537477 : move32();
734 : }
735 : }
736 100480 : hMCT->lastxCorrMatrix_e = xCorrMatrix_e;
737 100480 : move16();
738 100480 : move16();
739 100480 : currBlockDataCnt = 0;
740 197434 : WHILE( ( currBlockDataCnt < hMCT->nchan_out_woLFE ) )
741 : {
742 : /* find best fitting channel pair: */
743 197434 : ch1 = -1;
744 197434 : ch2 = -1;
745 197434 : max_corr = 0;
746 197434 : move16();
747 197434 : move16();
748 197434 : move32();
749 :
750 197434 : IF( !forceKeepTree )
751 : {
752 100985 : getNextBestCorrelation_fx( xCorrMatrix, &ch1, &ch2, &max_corr, inactiveBlockDetected, nchan );
753 : }
754 : ELSE
755 : {
756 96449 : getBestCorrelation_fx( hMCT, &tmp_ch1, &tmp_ch2, &tmp_max_corr, xCorrMatrix );
757 :
758 96449 : IF( EQ_16( currBlockDataCnt, hMCT->currBlockDataCnt ) )
759 : {
760 31425 : BREAK;
761 : }
762 : ELSE
763 : {
764 65024 : ch1 = hMCT->hBlockData[currBlockDataCnt]->ch1;
765 65024 : ch2 = hMCT->hBlockData[currBlockDataCnt]->ch2;
766 65024 : move16();
767 65024 : move16();
768 :
769 : /*don't allow forcing of channel-pair if their correlation is under the threshold*/
770 65024 : max_corr = xCorrMatrix[ch1][ch2];
771 65024 : move32();
772 :
773 65024 : tmp = BASOP_Util_Cmp_Mant32Exp( L_abs( max_corr ), xCorrMatrix_e, DEFAULT_CORR_THRES_Q31 /* 0.3 in Q31 */, 0 );
774 65024 : test();
775 65024 : IF( EQ_16( tmp, -1 ) || tmp == 0 )
776 : {
777 5067 : ch1 = tmp_ch1;
778 5067 : ch2 = tmp_ch2;
779 5067 : max_corr = tmp_max_corr;
780 5067 : forceKeepTree = 0;
781 5067 : move16();
782 5067 : move16();
783 5067 : move32();
784 5067 : move16();
785 : }
786 : }
787 : }
788 :
789 166009 : test();
790 166009 : test();
791 166009 : test();
792 166009 : IF( ( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_abs( max_corr ), xCorrMatrix_e, DEFAULT_CORR_THRES_Q31, 0 ), 1 ) && !hMCT->hbr_mct ) || ( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_abs( max_corr ), xCorrMatrix_e, SPAR_CORR_THRES_Q31, 0 ), 1 ) && hMCT->hbr_mct ) )
793 : {
794 97034 : IF( !forceKeepTree )
795 : {
796 : /*save channel pair*/
797 37090 : hMCT->hBlockData[currBlockDataCnt]->ch1 = ch1;
798 37090 : hMCT->hBlockData[currBlockDataCnt]->ch2 = ch2;
799 37090 : move16();
800 37090 : move16();
801 : }
802 :
803 : /* calculate all related values: */
804 97034 : assert( sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE );
805 :
806 97034 : getBlockValues_fx( sts, ch1, ch2, hMCT->hBlockData[currBlockDataCnt], mdst_spectrum, inv_spectrum, inv_mdst_spectrum, sub( 31, sts[0]->hTcxEnc->spectrum_e[0] ) );
807 :
808 97034 : IF( hMCT->hBlockData[currBlockDataCnt]->isActive == 0 )
809 : {
810 4868 : inactiveBlockDetected = add( inactiveBlockDetected, 1 );
811 4868 : IF( GT_16( inactiveBlockDetected, shr( hMCT->nchan_out_woLFE, 1 ) ) )
812 : {
813 80 : BREAK;
814 : }
815 4788 : forceKeepTree = 0;
816 4788 : move16();
817 :
818 4788 : CONTINUE; /* skip inactive blocks where stereo mode is dual-mono */
819 : }
820 :
821 92166 : updateCorrelationMatrix_fx( sts, hMCT, ch1, ch2, xCorrMatrix );
822 92166 : cpEle[ch1] = 1;
823 92166 : cpEle[ch2] = 1;
824 92166 : move16();
825 92166 : move16();
826 :
827 92166 : currBlockDataCnt = add( currBlockDataCnt, 1 );
828 : }
829 : ELSE
830 : {
831 : BREAK;
832 : }
833 : }
834 :
835 : /*save number of blocks for next frame*/
836 100480 : hMCT->currBlockDataCnt = currBlockDataCnt;
837 100480 : move16();
838 :
839 580236 : FOR( ch = 0; ch < nchan; ch++ )
840 : {
841 479756 : IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
842 : {
843 472934 : test();
844 472934 : IF( ( !cpEle[ch] ) || hMCT->currBlockDataCnt == 0 )
845 : {
846 288602 : IF( EQ_16( sts[ch]->core, TCX_20_CORE ) )
847 : {
848 281990 : nSubframes = 1;
849 281990 : move16();
850 281990 : L_subframeTCX = sts[ch]->hTcxEnc->L_frameTCX;
851 281990 : move16();
852 : }
853 : ELSE
854 : {
855 6612 : nSubframes = NB_DIV;
856 6612 : move16();
857 6612 : L_subframeTCX = shr( sts[ch]->hTcxEnc->L_frameTCX, 1 );
858 : }
859 :
860 : Word16 exp;
861 288602 : IF( hMCT->lowE_ch[ch] )
862 : {
863 : // qratio = (float) hMCT->mc_global_ild[ch] / SMDCT_ILD_RANGE;
864 182835 : qratio = div_l( L_shl( hMCT->mc_global_ild[ch], 11 ), SMDCT_ILD_RANGE ); // Q10
865 : }
866 : ELSE
867 : {
868 : // qratio = (float) SMDCT_ILD_RANGE / hMCT->mc_global_ild[ch];
869 105767 : qratio = div_l( ( SMDCT_ILD_RANGE << 11 ), hMCT->mc_global_ild[ch] ); // Q10
870 : }
871 288602 : exp = norm_s( qratio );
872 288602 : qratio = shl( qratio, exp );
873 288602 : exp = sub( 5, exp ); // Q = 10 + exp
874 :
875 583816 : FOR( k = 0; k < nSubframes; k++ )
876 : {
877 295214 : v_multc_fixed( sts[ch]->hTcxEnc->spectrum_fx[k], L_deposit_h( qratio ), sts[ch]->hTcxEnc->spectrum_fx[k], L_subframeTCX );
878 295214 : v_multc_fixed( mdst_spectrum[ch][k], L_deposit_h( qratio ), mdst_spectrum[ch][k], L_subframeTCX );
879 295214 : set32_fx( inv_spectrum[ch][k], 0, L_subframeTCX );
880 : }
881 288602 : sts[ch]->hTcxEnc->spectrum_e[1] = add( sts[ch]->hTcxEnc->spectrum_e[0], exp );
882 288602 : sts[ch]->hTcxEnc->spectrum_e[0] = add( sts[ch]->hTcxEnc->spectrum_e[0], exp );
883 288602 : sts[ch]->hTcxEnc->spectrum_long_e = add( sts[ch]->hTcxEnc->spectrum_long_e, exp );
884 288602 : hMCT->mc_global_ild[ch] = 0;
885 288602 : move16();
886 288602 : move16();
887 288602 : move16();
888 288602 : move16();
889 : }
890 : }
891 : }
892 : }
893 : ELSE
894 : {
895 459 : hMCT->currBlockDataCnt = 0;
896 459 : move16();
897 2490 : FOR( ch = 0; ch < nchan; ch++ )
898 : {
899 2031 : hMCT->mc_global_ild[ch] = 0;
900 2031 : move16();
901 : }
902 : }
903 :
904 100939 : pop_wmops();
905 :
906 100939 : return;
907 : }
908 :
909 : /*--------------------------------------------------------------------*
910 : * write_mct_bitstream()
911 : *
912 : * write mct metadata to bitstream
913 : *--------------------------------------------------------------------*/
914 100939 : void write_mct_bitstream_fx(
915 : Encoder_State **sts, /* i/o: encoder state structure */
916 : MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */
917 : const Word16 nchan /* i : number of channels */
918 : )
919 : {
920 : Word16 pair, ch;
921 : Word16 channelPairIndex;
922 : Word16 nbits_start;
923 : MCT_BLOCK_DATA_HANDLE hBlock;
924 : Encoder_State *p_st[2];
925 100939 : BSTR_ENC_HANDLE hBstr = sts[0]->hBstr;
926 :
927 100939 : nbits_start = hBstr->nb_bits_tot;
928 100939 : move16();
929 :
930 100939 : push_next_indice( hBstr, hMCT->currBlockDataCnt, MCT_NUM_BLOCK_DATA_BITS );
931 :
932 : /* first write core info and overlap mode for all channels */
933 582726 : FOR( ch = 0; ch < nchan; ch++ )
934 : {
935 481787 : test();
936 481787 : IF( hMCT->currBlockDataCnt && NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
937 : {
938 291976 : push_next_indice( hBstr, hMCT->mc_global_ild[ch], SMDCT_GLOBAL_ILD_BITS );
939 : }
940 : }
941 :
942 100939 : IF( hMCT->currBlockDataCnt )
943 : {
944 351870 : FOR( ch = 0; ch < nchan; ch++ )
945 : {
946 295260 : IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
947 : {
948 291976 : push_next_indice( hBstr, hMCT->lowE_ch[ch], 1 );
949 : }
950 : }
951 : }
952 :
953 : /* Do for each stereo block */
954 193105 : FOR( pair = hMCT->currBlockDataCnt - 1; pair >= 0; pair-- )
955 : {
956 92166 : hBlock = hMCT->hBlockData[pair];
957 :
958 : /*calculate channel pair index and write it to BS*/
959 92166 : channelPairIndex = channelPairToIndex_fx( hBlock->ch1, hBlock->ch2, nchan );
960 92166 : push_next_indice( hBstr, channelPairIndex, hMCT->bitsChannelPairIndex );
961 :
962 : /*point to encoder states of actual channels to write block pair bits*/
963 92166 : p_st[0] = sts[hBlock->ch1];
964 92166 : p_st[1] = sts[hBlock->ch2];
965 :
966 : /*then business as usual for each block pair */
967 92166 : write_stereo_to_bitstream_fx( hMCT->hBlockData[pair]->hStereoMdct, p_st, hBlock->mask, 1, hBstr );
968 : }
969 :
970 100939 : hMCT->nBitsMCT = sub( hBstr->nb_bits_tot, nbits_start );
971 100939 : move16();
972 :
973 100939 : return;
974 : }
975 :
976 : /*--------------------------------------------------------------------*
977 : * mctStereoIGF_enc()
978 : *
979 : * IGF analysis of channels after MCT processing
980 : *--------------------------------------------------------------------*/
981 35801 : void mctStereoIGF_enc_fx(
982 : MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */
983 : Encoder_State **sts, /* i/o: encoder state structure */
984 : Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2], /* i : MDCT spectrum for ITF */
985 : Word16 q_origSpec, /* i : Q for MDCT spectrum */
986 : Word32 *powerSpec_fx[MCT_MAX_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum,or estimate */
987 : Word16 q_powerSpec[MCT_MAX_CHANNELS], /* i : Q for powSpec_fx */
988 : Word32 *powerSpecMsInv_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : same as powerSpec_fx but for inverse spect.*/
989 : Word16 *q_powerSpecMsInv[MCT_MAX_CHANNELS][NB_DIV], /* i : Q for powSpecMsInv_fx */
990 : Word32 *inv_spectrum_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */
991 : const Word16 sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */
992 : )
993 : {
994 : Word32 *p_powerSpecMsInv_fx[CPE_CHANNELS][NB_DIV];
995 : Word16 *q_p_powerSpecMsInv_fx[CPE_CHANNELS][NB_DIV];
996 : Word32 *p_inv_spectrum_fx[CPE_CHANNELS][NB_DIV];
997 : Word32 *p_orig_spectrum_fx[CPE_CHANNELS][NB_DIV];
998 : Word32 *p_powerSpec_fx[NB_DIV];
999 : Word16 *p_exp_powerSpec_fx[NB_DIV];
1000 :
1001 : Word16 b, nSubframes, L_subframeTCX;
1002 : Word16 p_ch[2], n, ch, ch1, ch2;
1003 : Word16 q_pS_ch[2];
1004 : Encoder_State *p_st[NB_DIV];
1005 : Encoder_State *st;
1006 : Word16 singleChEle[MCT_MAX_CHANNELS];
1007 : Word16 q_spectrum;
1008 : Word16 exp_powerSpec[MCT_MAX_CHANNELS][L_FRAME48k];
1009 :
1010 35801 : L_subframeTCX = 0; /* to avoid compilation warning */
1011 35801 : move16();
1012 35801 : set16_fx( singleChEle, 1, hMCT->nchan_out_woLFE );
1013 :
1014 96410 : FOR( b = 0; b < hMCT->currBlockDataCnt; b++ )
1015 : {
1016 60609 : ch1 = hMCT->hBlockData[b]->ch1;
1017 60609 : ch2 = hMCT->hBlockData[b]->ch2;
1018 60609 : move16();
1019 60609 : move16();
1020 :
1021 60609 : p_ch[0] = ch1;
1022 60609 : p_ch[1] = ch2;
1023 60609 : move16();
1024 60609 : move16();
1025 :
1026 60609 : singleChEle[hMCT->hBlockData[b]->ch1] = 0;
1027 60609 : singleChEle[hMCT->hBlockData[b]->ch2] = 0;
1028 60609 : move16();
1029 60609 : move16();
1030 :
1031 : /* point to encoder states of actual channels to write block pair bits */
1032 60609 : p_st[0] = sts[ch1];
1033 60609 : p_st[1] = sts[ch2];
1034 :
1035 60609 : IF( ch1 > 0 )
1036 : {
1037 37200 : sts[ch1]->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot;
1038 : }
1039 :
1040 60609 : IF( ch2 > 0 )
1041 : {
1042 60609 : sts[ch2]->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot;
1043 : }
1044 :
1045 60609 : p_powerSpec_fx[0] = powerSpec_fx[ch1]; // q_powerSpec
1046 60609 : p_exp_powerSpec_fx[0] = exp_powerSpec[ch1]; // q_powerSpec
1047 60609 : p_powerSpec_fx[1] = powerSpec_fx[ch2];
1048 60609 : p_exp_powerSpec_fx[1] = exp_powerSpec[ch2];
1049 :
1050 : /* Band-wise M/S for MDST */
1051 60609 : nSubframes = NB_DIV;
1052 60609 : move16();
1053 60609 : if ( EQ_16( p_st[0]->hTcxEnc->tcxMode, TCX_20 ) )
1054 : {
1055 59112 : nSubframes = 1;
1056 59112 : move16();
1057 : }
1058 :
1059 122715 : FOR( n = 0; n < nSubframes; n++ )
1060 : {
1061 62106 : p_orig_spectrum_fx[0][n] = orig_spectrum_fx[ch1][n]; // q_origSpec
1062 62106 : p_orig_spectrum_fx[1][n] = orig_spectrum_fx[ch2][n];
1063 62106 : p_powerSpecMsInv_fx[0][n] = powerSpecMsInv_fx[ch1][n]; // q_powerSpec
1064 62106 : p_powerSpecMsInv_fx[1][n] = powerSpecMsInv_fx[ch2][n];
1065 62106 : q_p_powerSpecMsInv_fx[0][n] = q_powerSpecMsInv[ch1][n]; // q_powerSpec
1066 62106 : q_p_powerSpecMsInv_fx[1][n] = q_powerSpecMsInv[ch2][n];
1067 62106 : p_inv_spectrum_fx[0][n] = inv_spectrum_fx[ch1][n];
1068 62106 : p_inv_spectrum_fx[1][n] = inv_spectrum_fx[ch2][n];
1069 62106 : q_pS_ch[0] = q_powerSpec[ch1];
1070 62106 : q_pS_ch[1] = q_powerSpec[ch2];
1071 62106 : move16();
1072 62106 : move16();
1073 :
1074 62106 : test();
1075 62106 : IF( NE_16( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n], hMCT->hBlockData[b]->hStereoMdct->IGFStereoMode[n] ) ||
1076 : EQ_16( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n], SMDCT_BW_MS ) )
1077 32977 : {
1078 : Word16 exp_inv_spectrum_fx[CPE_CHANNELS];
1079 :
1080 98931 : FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
1081 : {
1082 65954 : exp_inv_spectrum_fx[ch] = p_st[ch]->hTcxEnc->spectrum_e[n];
1083 65954 : move16();
1084 : }
1085 32977 : set16_fx( exp_powerSpec[ch1], sub( Q31, q_pS_ch[0] ), L_FRAME48k );
1086 32977 : set16_fx( exp_powerSpec[ch2], sub( Q31, q_pS_ch[1] ), L_FRAME48k );
1087 32977 : ProcessStereoIGF_fx( hMCT->hBlockData[b]->hStereoMdct, p_st, hMCT->hBlockData[b]->mask, p_orig_spectrum_fx, q_origSpec, q_origSpec, p_powerSpec_fx, p_exp_powerSpec_fx,
1088 32977 : p_powerSpecMsInv_fx, q_p_powerSpecMsInv_fx, p_inv_spectrum_fx, exp_inv_spectrum_fx, n, sp_aud_decision0[ch1], p_st[0]->total_brate, 1 );
1089 : }
1090 : ELSE
1091 : {
1092 87387 : FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
1093 : {
1094 58258 : st = p_st[ch];
1095 :
1096 58258 : L_subframeTCX = shr( st->hTcxEnc->L_frameTCX, 1 );
1097 58258 : if ( EQ_16( nSubframes, 1 ) )
1098 : {
1099 54808 : L_subframeTCX = st->hTcxEnc->L_frameTCX;
1100 54808 : move16();
1101 : }
1102 :
1103 58258 : q_spectrum = sub( 31, st->hTcxEnc->spectrum_e[n] );
1104 :
1105 58258 : set16_fx( exp_powerSpec[p_ch[ch]], sub( Q31, q_powerSpec[p_ch[ch]] ), L_FRAME48k );
1106 58258 : ProcessIGF_ivas_fx( st, L_FRAME48k, st->hTcxEnc->spectrum_fx[n], &q_spectrum, orig_spectrum_fx[p_ch[ch]][n], q_origSpec, &powerSpec_fx[p_ch[ch]][n * L_subframeTCX], &exp_powerSpec[p_ch[ch]][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 );
1107 :
1108 58258 : st->hTcxEnc->spectrum_e[n] = sub( 31, q_spectrum );
1109 58258 : move16();
1110 : }
1111 : }
1112 : }
1113 : }
1114 :
1115 : /* channel elements that are coded separately detected */
1116 35801 : IF( sum16_fx( singleChEle, ( hMCT->nchan_out_woLFE ) ) != 0 )
1117 : {
1118 210745 : FOR( ch = 0; ch < ( hMCT->nchan_out_woLFE ); ch++ )
1119 : {
1120 174948 : IF( singleChEle[ch] )
1121 : {
1122 53746 : st = sts[ch];
1123 :
1124 53746 : IF( EQ_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
1125 : {
1126 1259 : CONTINUE;
1127 : }
1128 :
1129 52487 : IF( ch > 0 )
1130 : {
1131 40095 : st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot;
1132 : }
1133 :
1134 52487 : nSubframes = NB_DIV;
1135 52487 : move16();
1136 52487 : if ( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) )
1137 : {
1138 50953 : nSubframes = 1;
1139 50953 : move16();
1140 : }
1141 :
1142 106508 : FOR( n = 0; n < nSubframes; n++ )
1143 : {
1144 54021 : q_spectrum = sub( 31, st->hTcxEnc->spectrum_e[n] );
1145 :
1146 54021 : set16_fx( exp_powerSpec[ch], sub( Q31, q_powerSpec[ch] ), L_FRAME48k );
1147 54021 : ProcessIGF_ivas_fx( st, L_FRAME48k, st->hTcxEnc->spectrum_fx[n], &q_spectrum, orig_spectrum_fx[ch][n], q_origSpec, &powerSpec_fx[ch][n * L_subframeTCX], &exp_powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 );
1148 :
1149 54021 : st->hTcxEnc->spectrum_e[n] = sub( 31, q_spectrum );
1150 54021 : move16();
1151 : }
1152 : }
1153 : }
1154 : }
1155 :
1156 35801 : return;
1157 : }
|