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 199482 : 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 1116856 : FOR( ch = 0; ch < nchan; ch++ )
72 : {
73 917374 : st = sts[ch];
74 917374 : IF( NE_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
75 : {
76 891599 : IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) )
77 : {
78 872313 : nSubframes = 1;
79 872313 : move16();
80 872313 : L_subframe = st->hTcxEnc->L_frameTCX;
81 872313 : move16();
82 : }
83 : ELSE
84 : {
85 19286 : nSubframes = NB_DIV;
86 19286 : move16();
87 19286 : L_subframe = shr( st->hTcxEnc->L_frameTCX, 1 );
88 : }
89 :
90 891599 : gb = find_guarded_bits_fx( (Word32) L_subframe );
91 :
92 891599 : sum2_e = st->hTcxEnc->spectrum_e[0];
93 891599 : move16();
94 891599 : nrg[ch] = 0;
95 891599 : move32();
96 1802484 : FOR( n = 0; n < nSubframes; n++ )
97 : {
98 910885 : sum2 = sum2_32_exp_fx( st->hTcxEnc->spectrum_fx[n], L_subframe, &sum2_e, gb ); // 31 - sum2_e
99 :
100 910885 : nrg[ch] = BASOP_Util_Add_Mant32Exp( nrg[ch], nrg_e[ch], sum2, sum2_e, &nrg_e[ch] );
101 910885 : move32();
102 :
103 910885 : sum2_e = st->hTcxEnc->spectrum_e[0];
104 910885 : move16();
105 : }
106 :
107 891599 : nrg[ch] = Sqrt32( nrg[ch], &nrg_e[ch] ); // nrg_e
108 891599 : move32();
109 : }
110 : }
111 :
112 199482 : return;
113 : }
114 :
115 :
116 : /*-------------------------------------------------------------------------
117 : * getNextBestCorrelation()
118 : *
119 : * find channel pair with highest cross-correlation
120 : *-------------------------------------------------------------------------*/
121 99511 : 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 99511 : set32_fx( tmp_corrVals, 0, ( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2 );
135 :
136 : /* first sort correlation matrix */
137 99511 : i = 0;
138 99511 : move16();
139 565155 : FOR( ch1 = 0; ch1 < nChannels; ch1++ )
140 : {
141 1532013 : FOR( ch2 = ch1 + 1; ch2 < nChannels; ch2++ )
142 : {
143 1066369 : IF( L_abs( xCorrMatrix[ch1][ch2] ) > 0 )
144 : {
145 645086 : assert( i < ( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2 );
146 645086 : tmp_corrVals[i] = L_abs( xCorrMatrix[ch1][ch2] ); // Qx
147 645086 : move32();
148 645086 : i = add( i, 1 );
149 : }
150 : }
151 : }
152 :
153 99511 : tmp_idx = sub( shr( imult1616( nChannels, sub( nChannels, 1 ) ), 1 ), 1 );
154 :
155 : /* sort values */
156 99511 : 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 99511 : *max_corr = tmp_corrVals[( tmp_idx - sortInd )]; // Qx
160 99511 : move32();
161 :
162 : /*find channel pair for this max_corr*/
163 565155 : FOR( ch1 = 0; ch1 < nChannels; ch1++ )
164 : {
165 1257400 : FOR( ch2 = ch1 + 1; ch2 < nChannels; ch2++ )
166 : {
167 920198 : IF( EQ_32( L_abs( xCorrMatrix[ch1][ch2] ), *max_corr ) )
168 : {
169 128442 : *_ch1 = ch1;
170 128442 : *_ch2 = ch2;
171 128442 : *max_corr = xCorrMatrix[ch1][ch2]; /* assign to max_corr its actual value */ // Qx
172 128442 : move16();
173 128442 : move16();
174 128442 : move32();
175 128442 : BREAK;
176 : }
177 : }
178 : }
179 :
180 99511 : return;
181 : }
182 :
183 :
184 : /*-----------------------------------------------------------------------*
185 : * getCorrelationMatrix()
186 : *
187 : * calculates the cross correlation matrix for all active
188 : * channels
189 : *-----------------------------------------------------------------------*/
190 99513 : 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 99513 : nchan = hMCT->nchan_out_woLFE;
203 99513 : move16();
204 :
205 : /* correlation */
206 557190 : FOR( ch1 = 0; ch1 < nchan; ch1++ )
207 : {
208 1891740 : FOR( ch2 = ch1; ch2 < nchan; ch2++ )
209 : {
210 1434063 : xCorrMatrix[ch1][ch2] = 0;
211 1434063 : move32();
212 1434063 : xCorrMatrix_exp[ch1][ch2] = 0;
213 1434063 : move16();
214 :
215 1434063 : test();
216 1434063 : test();
217 1434063 : 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 1357483 : IF( EQ_16( sts[ch1]->core, TCX_20 ) )
223 : {
224 1336477 : nSubframes = 1;
225 1336477 : move16();
226 1336477 : L_subframe = sts[ch1]->hTcxEnc->L_frameTCX;
227 1336477 : move16();
228 : }
229 : ELSE
230 : {
231 21006 : nSubframes = NB_DIV;
232 21006 : move16();
233 21006 : L_subframe = shr( sts[ch1]->hTcxEnc->L_frameTCX, 1 );
234 : }
235 :
236 2735972 : FOR( n = 0; n < nSubframes; n++ )
237 : {
238 1378489 : res_q = sub( 31, sts[0]->hTcxEnc->spectrum_e[0] );
239 1378489 : L_tmp = dotp_fixed_32( sts[ch1]->hTcxEnc->spectrum_fx[n], sts[ch2]->hTcxEnc->spectrum_fx[n], L_subframe, 1, &res_q );
240 1378489 : 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 1378489 : move32();
242 : }
243 : }
244 : }
245 : }
246 :
247 : /* normalize */
248 557190 : FOR( ch1 = 0; ch1 < nchan; ch1++ )
249 : {
250 1434063 : FOR( ch2 = ch1 + 1; ch2 < nchan; ch2++ )
251 : {
252 : // tmp = sqrtf( xCorrMatrix[ch1][ch1] * xCorrMatrix[ch2][ch2] );
253 976386 : W_tmp = W_mult0_32_32( xCorrMatrix[ch1][ch1], xCorrMatrix[ch2][ch2] ); // ( 31 - xCorrMatrix_exp[ch1][ch1] ) + ( 31 - xCorrMatrix_exp[ch2][ch2] )
254 976386 : s = W_norm( W_tmp );
255 976386 : L_tmp = W_extract_h( W_shl( W_tmp, s ) ); // s + ( 31 - xCorrMatrix_exp[ch1][ch1] ) + ( 31 - xCorrMatrix_exp[ch2][ch2] ) - 32
256 :
257 976386 : 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 976386 : s = sub( 31, s );
259 976386 : L_tmp = Sqrt32( L_tmp, &s );
260 :
261 976386 : IF( L_tmp > 0 )
262 : {
263 : // xCorrMatrix[ch1][ch2] /= tmp;
264 935280 : xCorrMatrix[ch1][ch2] = L_deposit_h( BASOP_Util_Divide3232_Scale( xCorrMatrix[ch1][ch2], L_tmp, &res_q ) );
265 935280 : xCorrMatrix_exp[ch1][ch2] = add( res_q, sub( xCorrMatrix_exp[ch1][ch2], s ) );
266 935280 : move32();
267 935280 : move16();
268 : }
269 : ELSE
270 : {
271 41106 : xCorrMatrix[ch1][ch2] = 0;
272 41106 : xCorrMatrix_exp[ch1][ch2] = 0;
273 41106 : move32();
274 41106 : move16();
275 : }
276 : }
277 : }
278 :
279 : /* Aligning the variable exponents for each element to a common exponent */
280 99513 : s = 31;
281 99513 : *xCorrMatrix_e = 0;
282 99513 : move16();
283 99513 : move16();
284 :
285 457677 : FOR( ch1 = 0; ch1 < nchan - 1; ch1++ )
286 : {
287 358164 : s = s_min( s, getScaleFactor32( &xCorrMatrix[ch1][ch1 + 1], sub( nchan, add( ch1, 1 ) ) ) );
288 358164 : maximum_s( &xCorrMatrix_exp[ch1][ch1 + 1], sub( nchan, add( ch1, 1 ) ), &max_e );
289 358164 : *xCorrMatrix_e = s_max( *xCorrMatrix_e, max_e );
290 358164 : move16();
291 : }
292 :
293 557190 : FOR( ch1 = 0; ch1 < nchan; ch1++ )
294 : {
295 1434063 : FOR( ch2 = ch1 + 1; ch2 < nchan; ch2++ )
296 : {
297 976386 : xCorrMatrix[ch1][ch2] = L_shl_sat( xCorrMatrix[ch1][ch2], add( s, sub( xCorrMatrix_exp[ch1][ch2], *xCorrMatrix_e ) ) ); // xCorrMatrix_e - s
298 976386 : move32();
299 : }
300 : }
301 99513 : *xCorrMatrix_e = sub( *xCorrMatrix_e, s );
302 99513 : move16();
303 :
304 99513 : return;
305 : }
306 :
307 :
308 : /*-----------------------------------------------------------------*
309 : * getBestCorrelation()
310 : *
311 : * searches for the best correlated channel pair
312 : *------------------------------------------------------------------*/
313 93608 : 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 93608 : *_ch1 = -1;
323 93608 : *_ch2 = -1;
324 93608 : *max_corr = 0;
325 93608 : move16();
326 93608 : move16();
327 93608 : move32();
328 :
329 616897 : FOR( ch1 = 0; ch1 < ( hMCT->nchan_out_woLFE ); ch1++ )
330 : {
331 1905777 : FOR( ch2 = ch1 + 1; ch2 < ( hMCT->nchan_out_woLFE ); ch2++ )
332 : {
333 1382488 : IF( LT_32( L_abs( *max_corr ), L_abs( xCorrMatrix[ch1][ch2] ) ) )
334 : {
335 186298 : *max_corr = xCorrMatrix[ch1][ch2]; // Qx
336 186298 : move32();
337 :
338 186298 : *_ch1 = ch1;
339 186298 : *_ch2 = ch2;
340 186298 : move16();
341 186298 : move16();
342 : }
343 : }
344 : }
345 :
346 93608 : return;
347 : }
348 :
349 :
350 : /*----------------------------------------------------------------------*
351 : * getBlockValues()
352 : * stereo processing for the channels of current block
353 : *----------------------------------------------------------------------*/
354 93690 : 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 93690 : hBlock->isActive = 1;
373 93690 : move16();
374 :
375 : /* map vectors to current block channels */
376 281070 : FOR( n = 0; n < 2; n++ )
377 : {
378 187380 : p_mdst_spectrum[0][n] = mdst_spectrum[ch1][n]; // q_spec
379 187380 : p_mdst_spectrum[1][n] = mdst_spectrum[ch2][n]; // q_spec
380 187380 : p_inv_spectrum[0][n] = inv_spectrum[ch1][n]; // q_spec
381 187380 : p_inv_spectrum[1][n] = inv_spectrum[ch2][n]; // q_spec
382 187380 : p_inv_mdst_spectrum[0][n] = inv_mdst_spectrum[ch1][n]; // q_spec
383 187380 : p_inv_mdst_spectrum[1][n] = inv_mdst_spectrum[ch2][n]; // q_spec
384 : }
385 93690 : p_st[0] = sts[ch1];
386 93690 : p_st[1] = sts[ch2];
387 :
388 93690 : 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 93690 : test();
391 93690 : test();
392 93690 : test();
393 93690 : test();
394 93690 : 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 4077 : hBlock->isActive = 0;
397 4077 : move16();
398 : }
399 :
400 93690 : return;
401 : }
402 :
403 :
404 : /*-------------------------------------------------------------------*
405 : * updateCorrelationMatrix()
406 : *
407 : * updates the cross correlation matrix with modified spectra after
408 : * stereo block processing
409 : *-------------------------------------------------------------------*/
410 89613 : 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 595448 : FOR( ch1 = 0; ch1 < ( hMCT->nchan_out_woLFE ); ch1++ )
422 : {
423 2407987 : FOR( ch2 = ch1; ch2 < ( hMCT->nchan_out_woLFE ); ch2++ )
424 : {
425 1902152 : test();
426 1902152 : test();
427 1902152 : 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 1829062 : IF( EQ_16( sts[ch1]->core, TCX_20 ) )
432 : {
433 1788622 : nSubframes = 1;
434 1788622 : move16();
435 : }
436 : ELSE
437 : {
438 40440 : nSubframes = NB_DIV;
439 40440 : move16();
440 : }
441 :
442 1829062 : test();
443 1829062 : test();
444 1829062 : test();
445 1829062 : IF( EQ_16( ch1, _ch1 ) || EQ_16( ch2, _ch2 ) || EQ_16( ch1, _ch2 ) || EQ_16( ch2, _ch1 ) )
446 : {
447 1797824 : FOR( n = 0; n < nSubframes; n++ )
448 : {
449 906565 : xCorrMatrix[ch1][ch2] = 0; /*disable combinations with channels already processed */
450 906565 : move32();
451 : }
452 : }
453 : }
454 : }
455 : }
456 :
457 89613 : return;
458 : }
459 :
460 :
461 : /*----------------------------------------------------------*
462 : * channelPairToIndex()
463 : * get the index of each channel pair
464 : *----------------------------------------------------------*/
465 89613 : 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 89613 : pairIdx = 0;
474 89613 : move16();
475 :
476 333076 : FOR( ch2 = 1; ch2 < nChannels; ch2++ )
477 : {
478 1073212 : FOR( ch1 = 0; ch1 < ch2; ch1++ )
479 : {
480 829749 : test();
481 829749 : IF( EQ_16( ch1, chIdx1 ) && EQ_16( ch2, chIdx2 ) )
482 : {
483 89613 : return pairIdx;
484 : }
485 : ELSE
486 : {
487 740136 : 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 99513 : 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 99513 : Word32 meanE = 0;
510 : Word32 L_tmp;
511 99513 : Word16 cnt = 0, meanE_e = 0, L_tmp_e;
512 99513 : move32();
513 99513 : move16();
514 99513 : move16();
515 :
516 : /*Initializations*/
517 99513 : set16_fx( hMCT->lowE_ch, 0, nchan );
518 :
519 99513 : getChannelEnergies_fx( sts, nrg, nrg_e, nchan );
520 :
521 : /*calculate total energy without LFE*/
522 557190 : FOR( ch = 0; ch < nchan; ch++ )
523 : {
524 457677 : IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
525 : {
526 445645 : meanE = BASOP_Util_Add_Mant32Exp( meanE, meanE_e, nrg[ch], nrg_e[ch], &meanE_e );
527 445645 : cnt = add( cnt, 1 );
528 : }
529 : }
530 :
531 : /*calculate mean energy*/
532 99513 : assert( cnt >= 2 );
533 99513 : L_tmp = BASOP_Util_Divide3216_Scale( meanE, cnt, &L_tmp_e );
534 99513 : L_tmp_e = add( L_tmp_e, sub( meanE_e, 15 ) );
535 :
536 : // meanE = max( meanE / cnt, EPSILON );
537 99513 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_tmp, L_tmp_e, EPSILON_FX_M, EPSILON_FX_E ), 1 ) )
538 : {
539 99513 : meanE = L_deposit_h( (Word16) L_tmp );
540 99513 : meanE_e = L_tmp_e;
541 99513 : move32();
542 99513 : 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 557190 : FOR( ch = 0; ch < nchan; ch++ )
553 : {
554 457677 : IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
555 : {
556 445645 : IF( EQ_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) )
557 : {
558 436002 : nSubframes = 1;
559 436002 : move16();
560 436002 : L_subframe = sts[ch]->hTcxEnc->L_frameTCX;
561 436002 : move16();
562 : }
563 : ELSE
564 : {
565 9643 : nSubframes = NB_DIV;
566 9643 : move16();
567 9643 : L_subframe = shr( sts[ch]->hTcxEnc->L_frameTCX, 1 );
568 : }
569 :
570 445645 : 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 166036 : ratio_fx = BASOP_Util_Divide3232_Scale( meanE, nrg[ch], &L_tmp_e );
574 166036 : L_tmp_e = add( L_tmp_e, sub( meanE_e, nrg_e[ch] ) );
575 166036 : ratio_fx = shl_sat( ratio_fx, L_tmp_e );
576 :
577 166036 : hMCT->mc_global_ild[ch] = s_max( 1, s_min( SMDCT_ILD_RANGE - 1, mult_r( SMDCT_ILD_RANGE, ratio_fx ) ) );
578 166036 : move16();
579 :
580 166036 : 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 279609 : ratio_fx = BASOP_Util_Divide3232_Scale( nrg[ch], meanE, &L_tmp_e );
586 279609 : L_tmp_e = add( L_tmp_e, sub( nrg_e[ch], meanE_e ) );
587 279609 : ratio_fx = shl_sat( ratio_fx, L_tmp_e );
588 :
589 279609 : hMCT->lowE_ch[ch] = 1;
590 279609 : move16();
591 :
592 279609 : hMCT->mc_global_ild[ch] = s_max( 1, s_min( SMDCT_ILD_RANGE - 1, mult_r( SMDCT_ILD_RANGE, ratio_fx ) ) );
593 279609 : move16();
594 :
595 279609 : qratio = shl_sat( div_l( ( (Word32) SMDCT_ILD_RANGE << 11 ), hMCT->mc_global_ild[ch] ), 1 ); // Q11
596 : }
597 :
598 900933 : FOR( k = 0; k < nSubframes; k++ )
599 : {
600 455288 : 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 445645 : IF( GT_16( nSubframes, 1 ) )
603 : {
604 9643 : sts[ch]->hTcxEnc->spectrum_long_e = add( sts[ch]->hTcxEnc->spectrum_long_e, 4 );
605 9643 : move16();
606 : }
607 :
608 900933 : FOR( k = 0; k < nSubframes; k++ )
609 : {
610 455288 : 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 455288 : 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 99513 : return;
618 : }
619 :
620 :
621 : /*--------------------------------------------------------------------*
622 : * apply_MCT_enc()
623 : *
624 : * apply MCT algorithm to input channels
625 : *--------------------------------------------------------------------*/
626 99969 : 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 99969 : Word16 count_active_ch = 0;
646 99969 : Word16 xCorrMatrix_e = 0, sumCorrDiff_e = 0, L_tmp_e;
647 99969 : move16();
648 99969 : move16();
649 99969 : move16();
650 :
651 99969 : push_wmops( "mct_core_enc_mct" );
652 :
653 99969 : forceKeepTree = 1;
654 99969 : inactiveBlockDetected = 0;
655 99969 : move16();
656 99969 : move16();
657 99969 : set16_fx( cpEle, 0, MCT_MAX_CHANNELS );
658 :
659 : /*Determine active channels*/
660 559666 : FOR( ch = 0; ch < nchan; ch++ )
661 : {
662 459697 : IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
663 : {
664 445954 : count_active_ch = add( count_active_ch, 1 );
665 : }
666 : ELSE
667 : {
668 13743 : hMCT->mc_global_ild[ch] = 0;
669 13743 : move16();
670 : }
671 : }
672 :
673 : /*there should be at least one cp*/
674 99969 : IF( GE_16( count_active_ch, CPE_CHANNELS ) )
675 : {
676 : /*Normalize energies with global ILD*/
677 99513 : getGlobalILD_fx( sts, hMCT, mdst_spectrum, nchan );
678 99513 : getCorrelationMatrix_fx( sts, hMCT, xCorrMatrix, &xCorrMatrix_e );
679 :
680 : /*check if previous tree should be kept*/
681 99513 : sumCorrDiff = 0;
682 99513 : move32();
683 : // thr = 0.15f * (float) ( count_active_ch ) * ( count_active_ch - 1 ) / 2.0f;
684 99513 : thr = Mpy_32_16_1( 161061274, imult1616( count_active_ch, sub( count_active_ch, 1 ) ) ); /* Q16 */ /* 161061274 = 0.15 / 2 in Q31 */
685 :
686 457677 : FOR( ch2 = 1; ch2 < nchan; ch2++ )
687 : {
688 1334550 : FOR( ch1 = 0; ch1 < ch2; ch1++ )
689 : {
690 976386 : test();
691 976386 : 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 935280 : 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 935280 : sumCorrDiff = BASOP_Util_Add_Mant32Exp( sumCorrDiff, sumCorrDiff_e, L_tmp, L_tmp_e, &sumCorrDiff_e );
696 : }
697 : }
698 : }
699 :
700 99513 : if ( EQ_16( BASOP_Util_Cmp_Mant32Exp( sumCorrDiff, sumCorrDiff_e, thr, 15 ), 1 ) )
701 : {
702 41947 : forceKeepTree = 0;
703 41947 : move16();
704 : }
705 :
706 : /* check if keepTree is applied on unallowed blocks (e.g. channel pairs with different cores) */
707 99513 : IF( forceKeepTree )
708 : {
709 57566 : IF( !hMCT->currBlockDataCnt )
710 : {
711 22049 : forceKeepTree = 0;
712 22049 : move16();
713 : }
714 : ELSE
715 : {
716 98875 : FOR( pair = 0; pair < hMCT->currBlockDataCnt; pair++ )
717 : {
718 63358 : if ( xCorrMatrix[hMCT->hBlockData[pair]->ch1][hMCT->hBlockData[pair]->ch2] == 0 )
719 : {
720 107 : forceKeepTree = 0;
721 107 : move16();
722 : }
723 : }
724 : }
725 : }
726 :
727 : /*save initial correlation matrix for next frame*/
728 557190 : FOR( ch1 = 0; ch1 < nchan; ch1++ )
729 : {
730 1891740 : FOR( ch2 = ch1; ch2 < nchan; ch2++ )
731 : {
732 1434063 : hMCT->lastxCorrMatrix_fx[ch1][ch2] = xCorrMatrix[ch1][ch2];
733 1434063 : move32();
734 : }
735 : }
736 99513 : hMCT->lastxCorrMatrix_e = xCorrMatrix_e;
737 99513 : move16();
738 99513 : move16();
739 99513 : currBlockDataCnt = 0;
740 193119 : WHILE( ( currBlockDataCnt < hMCT->nchan_out_woLFE ) )
741 : {
742 : /* find best fitting channel pair: */
743 193119 : ch1 = -1;
744 193119 : ch2 = -1;
745 193119 : max_corr = 0;
746 193119 : move16();
747 193119 : move16();
748 193119 : move32();
749 :
750 193119 : IF( !forceKeepTree )
751 : {
752 99511 : getNextBestCorrelation_fx( xCorrMatrix, &ch1, &ch2, &max_corr, inactiveBlockDetected, nchan );
753 : }
754 : ELSE
755 : {
756 93608 : getBestCorrelation_fx( hMCT, &tmp_ch1, &tmp_ch2, &tmp_max_corr, xCorrMatrix );
757 :
758 93608 : IF( EQ_16( currBlockDataCnt, hMCT->currBlockDataCnt ) )
759 : {
760 30640 : BREAK;
761 : }
762 : ELSE
763 : {
764 62968 : ch1 = hMCT->hBlockData[currBlockDataCnt]->ch1;
765 62968 : ch2 = hMCT->hBlockData[currBlockDataCnt]->ch2;
766 62968 : move16();
767 62968 : move16();
768 :
769 : /*don't allow forcing of channel-pair if their correlation is under the threshold*/
770 62968 : max_corr = xCorrMatrix[ch1][ch2];
771 62968 : move32();
772 :
773 62968 : tmp = BASOP_Util_Cmp_Mant32Exp( L_abs( max_corr ), xCorrMatrix_e, DEFAULT_CORR_THRES_Q31 /* 0.3 in Q31 */, 0 );
774 62968 : test();
775 62968 : IF( EQ_16( tmp, -1 ) || tmp == 0 )
776 : {
777 4320 : ch1 = tmp_ch1;
778 4320 : ch2 = tmp_ch2;
779 4320 : max_corr = tmp_max_corr;
780 4320 : forceKeepTree = 0;
781 4320 : move16();
782 4320 : move16();
783 4320 : move32();
784 4320 : move16();
785 : }
786 : }
787 : }
788 :
789 162479 : test();
790 162479 : test();
791 162479 : test();
792 162479 : 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 93690 : IF( !forceKeepTree )
795 : {
796 : /*save channel pair*/
797 35055 : hMCT->hBlockData[currBlockDataCnt]->ch1 = ch1;
798 35055 : hMCT->hBlockData[currBlockDataCnt]->ch2 = ch2;
799 35055 : move16();
800 35055 : move16();
801 : }
802 :
803 : /* calculate all related values: */
804 93690 : assert( sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE );
805 :
806 93690 : 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 93690 : IF( hMCT->hBlockData[currBlockDataCnt]->isActive == 0 )
809 : {
810 4077 : inactiveBlockDetected = add( inactiveBlockDetected, 1 );
811 4077 : IF( GT_16( inactiveBlockDetected, shr( hMCT->nchan_out_woLFE, 1 ) ) )
812 : {
813 84 : BREAK;
814 : }
815 3993 : forceKeepTree = 0;
816 3993 : move16();
817 :
818 3993 : CONTINUE; /* skip inactive blocks where stereo mode is dual-mono */
819 : }
820 :
821 89613 : updateCorrelationMatrix_fx( sts, hMCT, ch1, ch2, xCorrMatrix );
822 89613 : cpEle[ch1] = 1;
823 89613 : cpEle[ch2] = 1;
824 89613 : move16();
825 89613 : move16();
826 :
827 89613 : currBlockDataCnt = add( currBlockDataCnt, 1 );
828 : }
829 : ELSE
830 : {
831 : BREAK;
832 : }
833 : }
834 :
835 : /*save number of blocks for next frame*/
836 99513 : hMCT->currBlockDataCnt = currBlockDataCnt;
837 99513 : move16();
838 :
839 557190 : FOR( ch = 0; ch < nchan; ch++ )
840 : {
841 457677 : IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
842 : {
843 445645 : test();
844 445645 : IF( ( !cpEle[ch] ) || hMCT->currBlockDataCnt == 0 )
845 : {
846 266419 : IF( EQ_16( sts[ch]->core, TCX_20_CORE ) )
847 : {
848 260560 : nSubframes = 1;
849 260560 : move16();
850 260560 : L_subframeTCX = sts[ch]->hTcxEnc->L_frameTCX;
851 260560 : move16();
852 : }
853 : ELSE
854 : {
855 5859 : nSubframes = NB_DIV;
856 5859 : move16();
857 5859 : L_subframeTCX = shr( sts[ch]->hTcxEnc->L_frameTCX, 1 );
858 : }
859 :
860 : Word16 exp;
861 266419 : IF( hMCT->lowE_ch[ch] )
862 : {
863 : // qratio = (float) hMCT->mc_global_ild[ch] / SMDCT_ILD_RANGE;
864 168821 : 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 97598 : qratio = div_l( ( SMDCT_ILD_RANGE << 11 ), hMCT->mc_global_ild[ch] ); // Q10
870 : }
871 266419 : exp = norm_s( qratio );
872 266419 : qratio = shl( qratio, exp );
873 266419 : exp = sub( 5, exp ); // Q = 10 + exp
874 :
875 538697 : FOR( k = 0; k < nSubframes; k++ )
876 : {
877 272278 : v_multc_fixed( sts[ch]->hTcxEnc->spectrum_fx[k], L_deposit_h( qratio ), sts[ch]->hTcxEnc->spectrum_fx[k], L_subframeTCX );
878 272278 : v_multc_fixed( mdst_spectrum[ch][k], L_deposit_h( qratio ), mdst_spectrum[ch][k], L_subframeTCX );
879 272278 : set32_fx( inv_spectrum[ch][k], 0, L_subframeTCX );
880 : }
881 266419 : sts[ch]->hTcxEnc->spectrum_e[1] = add( sts[ch]->hTcxEnc->spectrum_e[0], exp );
882 266419 : sts[ch]->hTcxEnc->spectrum_e[0] = add( sts[ch]->hTcxEnc->spectrum_e[0], exp );
883 266419 : sts[ch]->hTcxEnc->spectrum_long_e = add( sts[ch]->hTcxEnc->spectrum_long_e, exp );
884 266419 : hMCT->mc_global_ild[ch] = 0;
885 266419 : move16();
886 266419 : move16();
887 266419 : move16();
888 266419 : move16();
889 : }
890 : }
891 : }
892 : }
893 : ELSE
894 : {
895 456 : hMCT->currBlockDataCnt = 0;
896 456 : move16();
897 2476 : FOR( ch = 0; ch < nchan; ch++ )
898 : {
899 2020 : hMCT->mc_global_ild[ch] = 0;
900 2020 : move16();
901 : }
902 : }
903 :
904 99969 : pop_wmops();
905 :
906 99969 : return;
907 : }
908 :
909 : /*--------------------------------------------------------------------*
910 : * write_mct_bitstream()
911 : *
912 : * write mct metadata to bitstream
913 : *--------------------------------------------------------------------*/
914 99969 : 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 99969 : BSTR_ENC_HANDLE hBstr = sts[0]->hBstr;
926 :
927 99969 : nbits_start = hBstr->nb_bits_tot;
928 99969 : move16();
929 :
930 99969 : push_next_indice( hBstr, hMCT->currBlockDataCnt, MCT_NUM_BLOCK_DATA_BITS );
931 :
932 : /* first write core info and overlap mode for all channels */
933 559666 : FOR( ch = 0; ch < nchan; ch++ )
934 : {
935 459697 : test();
936 459697 : IF( hMCT->currBlockDataCnt && NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
937 : {
938 272784 : push_next_indice( hBstr, hMCT->mc_global_ild[ch], SMDCT_GLOBAL_ILD_BITS );
939 : }
940 : }
941 :
942 99969 : IF( hMCT->currBlockDataCnt )
943 : {
944 332890 : FOR( ch = 0; ch < nchan; ch++ )
945 : {
946 278096 : IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
947 : {
948 272784 : push_next_indice( hBstr, hMCT->lowE_ch[ch], 1 );
949 : }
950 : }
951 : }
952 :
953 : /* Do for each stereo block */
954 189582 : FOR( pair = hMCT->currBlockDataCnt - 1; pair >= 0; pair-- )
955 : {
956 89613 : hBlock = hMCT->hBlockData[pair];
957 :
958 : /*calculate channel pair index and write it to BS*/
959 89613 : channelPairIndex = channelPairToIndex_fx( hBlock->ch1, hBlock->ch2, nchan );
960 89613 : push_next_indice( hBstr, channelPairIndex, hMCT->bitsChannelPairIndex );
961 :
962 : /*point to encoder states of actual channels to write block pair bits*/
963 89613 : p_st[0] = sts[hBlock->ch1];
964 89613 : p_st[1] = sts[hBlock->ch2];
965 :
966 : /*then business as usual for each block pair */
967 89613 : write_stereo_to_bitstream_fx( hMCT->hBlockData[pair]->hStereoMdct, p_st, hBlock->mask, 1, hBstr );
968 : }
969 :
970 99969 : hMCT->nBitsMCT = sub( hBstr->nb_bits_tot, nbits_start );
971 99969 : move16();
972 :
973 99969 : return;
974 : }
975 :
976 : /*--------------------------------------------------------------------*
977 : * mctStereoIGF_enc()
978 : *
979 : * IGF analysis of channels after MCT processing
980 : *--------------------------------------------------------------------*/
981 34621 : 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][L_FRAME48k], /* 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], /* 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 : Word32 *p_inv_spectrum_fx[CPE_CHANNELS][NB_DIV];
996 : Word32 *p_orig_spectrum_fx[CPE_CHANNELS][NB_DIV];
997 : Word32 *p_powerSpec_fx[NB_DIV];
998 :
999 : Word16 b, nSubframes, L_subframeTCX;
1000 : Word16 p_ch[2], n, ch, ch1, ch2;
1001 : Word16 q_pSI_ch[2];
1002 : Word16 q_pS_ch[2];
1003 : Encoder_State *p_st[NB_DIV];
1004 : Encoder_State *st;
1005 : Word16 singleChEle[MCT_MAX_CHANNELS];
1006 : Word16 q_spectrum;
1007 : Word16 exp_powerSpec[MCT_MAX_CHANNELS][N_MAX + L_MDCT_OVLP_MAX];
1008 :
1009 34621 : L_subframeTCX = 0; /* to avoid compilation warning */
1010 34621 : move16();
1011 34621 : set16_fx( singleChEle, 1, hMCT->nchan_out_woLFE );
1012 :
1013 93543 : FOR( b = 0; b < hMCT->currBlockDataCnt; b++ )
1014 : {
1015 58922 : ch1 = hMCT->hBlockData[b]->ch1;
1016 58922 : ch2 = hMCT->hBlockData[b]->ch2;
1017 58922 : move16();
1018 58922 : move16();
1019 :
1020 58922 : p_ch[0] = ch1;
1021 58922 : p_ch[1] = ch2;
1022 58922 : move16();
1023 58922 : move16();
1024 :
1025 58922 : singleChEle[hMCT->hBlockData[b]->ch1] = 0;
1026 58922 : singleChEle[hMCT->hBlockData[b]->ch2] = 0;
1027 58922 : move16();
1028 58922 : move16();
1029 :
1030 : /* point to encoder states of actual channels to write block pair bits */
1031 58922 : p_st[0] = sts[ch1];
1032 58922 : p_st[1] = sts[ch2];
1033 :
1034 58922 : IF( ch1 > 0 )
1035 : {
1036 34411 : sts[ch1]->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot;
1037 : }
1038 :
1039 58922 : IF( ch2 > 0 )
1040 : {
1041 58922 : sts[ch2]->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot;
1042 : }
1043 :
1044 58922 : p_powerSpec_fx[0] = powerSpec_fx[ch1]; // q_powerSpec
1045 58922 : p_powerSpec_fx[1] = powerSpec_fx[ch2];
1046 :
1047 : /* Band-wise M/S for MDST */
1048 58922 : nSubframes = NB_DIV;
1049 58922 : move16();
1050 58922 : if ( EQ_16( p_st[0]->hTcxEnc->tcxMode, TCX_20 ) )
1051 : {
1052 57497 : nSubframes = 1;
1053 57497 : move16();
1054 : }
1055 :
1056 119269 : FOR( n = 0; n < nSubframes; n++ )
1057 : {
1058 60347 : p_orig_spectrum_fx[0][n] = orig_spectrum_fx[ch1][n]; // q_origSpec
1059 60347 : p_orig_spectrum_fx[1][n] = orig_spectrum_fx[ch2][n];
1060 60347 : p_powerSpecMsInv_fx[0][n] = powerSpecMsInv_fx[ch1][n]; // q_powerSpec
1061 60347 : p_powerSpecMsInv_fx[1][n] = powerSpecMsInv_fx[ch2][n];
1062 60347 : p_inv_spectrum_fx[0][n] = inv_spectrum_fx[ch1][n];
1063 60347 : p_inv_spectrum_fx[1][n] = inv_spectrum_fx[ch2][n];
1064 60347 : q_pS_ch[0] = q_powerSpec[ch1];
1065 60347 : q_pSI_ch[0] = q_powerSpecMsInv[ch1];
1066 60347 : q_pS_ch[1] = q_powerSpec[ch2];
1067 60347 : q_pSI_ch[1] = q_powerSpecMsInv[ch2];
1068 60347 : move16();
1069 60347 : move16();
1070 :
1071 60347 : test();
1072 60347 : IF( NE_16( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n], hMCT->hBlockData[b]->hStereoMdct->IGFStereoMode[n] ) ||
1073 : EQ_16( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n], SMDCT_BW_MS ) )
1074 31546 : {
1075 : Word16 exp_powerSpec_fx[CPE_CHANNELS], exp_powerSpecMsInv_fx[CPE_CHANNELS], exp_inv_spectrum_fx[CPE_CHANNELS];
1076 :
1077 94638 : FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
1078 : {
1079 63092 : exp_powerSpec_fx[ch] = sub( Q31, q_pS_ch[ch] );
1080 63092 : exp_powerSpecMsInv_fx[ch] = sub( Q31, q_pSI_ch[ch] );
1081 63092 : exp_inv_spectrum_fx[ch] = p_st[ch]->hTcxEnc->spectrum_e[n];
1082 63092 : move16();
1083 63092 : move16();
1084 63092 : move16();
1085 : }
1086 :
1087 31546 : ProcessStereoIGF_fx( hMCT->hBlockData[b]->hStereoMdct, p_st, hMCT->hBlockData[b]->mask, p_orig_spectrum_fx, q_origSpec, q_origSpec, p_powerSpec_fx, exp_powerSpec_fx,
1088 31546 : p_powerSpecMsInv_fx, exp_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 86403 : FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
1093 : {
1094 57602 : st = p_st[ch];
1095 :
1096 57602 : L_subframeTCX = shr( st->hTcxEnc->L_frameTCX, 1 );
1097 57602 : if ( EQ_16( nSubframes, 1 ) )
1098 : {
1099 54200 : L_subframeTCX = st->hTcxEnc->L_frameTCX;
1100 54200 : move16();
1101 : }
1102 :
1103 57602 : q_spectrum = sub( 31, st->hTcxEnc->spectrum_e[n] );
1104 :
1105 57602 : set16_fx( exp_powerSpec[p_ch[ch]], sub( Q31, q_powerSpec[p_ch[ch]] ), N_MAX + L_MDCT_OVLP_MAX );
1106 57602 : 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 57602 : st->hTcxEnc->spectrum_e[n] = sub( 31, q_spectrum );
1109 57602 : move16();
1110 : }
1111 : }
1112 : }
1113 : }
1114 :
1115 : /* channel elements that are coded separately detected */
1116 34621 : IF( sum16_fx( singleChEle, ( hMCT->nchan_out_woLFE ) ) != 0 )
1117 : {
1118 197877 : FOR( ch = 0; ch < ( hMCT->nchan_out_woLFE ); ch++ )
1119 : {
1120 163261 : IF( singleChEle[ch] )
1121 : {
1122 45439 : st = sts[ch];
1123 :
1124 45439 : IF( EQ_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
1125 : {
1126 2828 : CONTINUE;
1127 : }
1128 :
1129 42611 : IF( ch > 0 )
1130 : {
1131 32501 : st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot;
1132 : }
1133 :
1134 42611 : nSubframes = NB_DIV;
1135 42611 : move16();
1136 42611 : if ( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) )
1137 : {
1138 41341 : nSubframes = 1;
1139 41341 : move16();
1140 : }
1141 :
1142 86492 : FOR( n = 0; n < nSubframes; n++ )
1143 : {
1144 43881 : q_spectrum = sub( 31, st->hTcxEnc->spectrum_e[n] );
1145 :
1146 43881 : set16_fx( exp_powerSpec[ch], sub( Q31, q_powerSpec[ch] ), N_MAX + L_MDCT_OVLP_MAX );
1147 43881 : 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 43881 : st->hTcxEnc->spectrum_e[n] = sub( 31, q_spectrum );
1150 43881 : move16();
1151 : }
1152 : }
1153 : }
1154 : }
1155 :
1156 34621 : return;
1157 : }
|