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 <assert.h>
37 : #include "prot_fx.h"
38 : #include "ivas_prot_rend_fx.h"
39 : #include "ivas_rom_com.h"
40 : #include "ivas_rom_rend.h"
41 : #include "wmc_auto.h"
42 : #include "ivas_prot_fx.h"
43 :
44 : #include "debug.h"
45 :
46 : /*----------------------------------------------------------------------------------*
47 : * Local constants
48 : *----------------------------------------------------------------------------------*/
49 :
50 :
51 : #define LS_OUT_CONV_SMOOTHING_FACTOR_Q31 93415539
52 : #define LS_OUT_CONV_CLIP_FACTOR_MAX_Q30 2147483647
53 : #define LS_OUT_CONV_CLIP_FACTOR_MIN_Q30 322122547
54 :
55 :
56 : /*----------------------------------------------------------------------------------*
57 : * Local functions
58 : *----------------------------------------------------------------------------------*/
59 :
60 3637445 : static void ivas_lssetupconversion_computeEQFactor_fx(
61 : Word32 *outputEnergy,
62 : Word16 output_exp,
63 : Word32 *inputEnergy,
64 : Word16 input_exp,
65 : Word32 *EQ )
66 : {
67 3637445 : test();
68 3637445 : IF( ( *outputEnergy == 0 ) && ( *inputEnergy == 0 ) )
69 : {
70 873192 : *EQ = ONE_IN_Q30; // Q30
71 873192 : move32();
72 873192 : return;
73 : }
74 : /* Compute the Equalization Gain */
75 : Word16 tmp_e;
76 2764253 : Word16 tmp = BASOP_Util_Divide3232_Scale( *outputEnergy, L_add( EPSILON_FX, *inputEnergy ), &tmp_e );
77 2764253 : tmp_e = add( tmp_e, sub( output_exp, input_exp ) );
78 2764253 : Word32 tmp_32 = L_deposit_h( tmp );
79 2764253 : tmp_32 = Sqrt32( tmp_32, &tmp_e );
80 2764253 : *EQ = L_shr_sat( tmp_32, sub( 1, tmp_e ) ); // range of EQ in float 0.3 - 2.0
81 2764253 : move32();
82 :
83 2764253 : *EQ = L_min( *EQ, LS_OUT_CONV_CLIP_FACTOR_MAX_Q30 );
84 2764253 : *EQ = L_max( *EQ, LS_OUT_CONV_CLIP_FACTOR_MIN_Q30 );
85 2764253 : move32();
86 2764253 : move32();
87 :
88 2764253 : return;
89 : }
90 :
91 :
92 69 : static void ivas_lssetupconversion_mdct_init_bands_fx(
93 : const Word16 output_frame, /* i : output frame length */
94 : const Word16 tcx_mode, /* i : tcx mode (TCX10, TCX 20) */
95 : Word16 *sfbOffset, /* o : sfb offset table */
96 : Word16 *sfbCnt /* o : number of sfbs */
97 : )
98 : {
99 : SpectrumWarping const *lpcBndsParam;
100 : Word16 i, cnt, specStartOffset, L_frameTCX;
101 : const UWord8 *sfbWidths;
102 :
103 69 : IF( EQ_16( tcx_mode, TCX_20_CORE ) )
104 : {
105 69 : L_frameTCX = output_frame;
106 69 : move16();
107 : }
108 : ELSE
109 : {
110 0 : L_frameTCX = shr( output_frame, 1 );
111 : }
112 :
113 :
114 69 : SWITCH( output_frame )
115 : {
116 69 : case L_FRAME48k:
117 : case L_FRAME32k:
118 69 : lpcBndsParam = sw32000Hz;
119 69 : BREAK;
120 0 : case L_FRAME25_6k:
121 0 : lpcBndsParam = sw25600Hz;
122 0 : BREAK;
123 0 : case L_FRAME16k:
124 0 : lpcBndsParam = sw16000Hz;
125 0 : BREAK;
126 0 : default:
127 0 : assert( !"Subband division not defined for this frame size" );
128 : return;
129 : }
130 :
131 69 : IF( EQ_16( tcx_mode, TCX_20_CORE ) )
132 : {
133 69 : sfbWidths = lpcBndsParam->bandLengthsTCX20;
134 69 : cnt = 64;
135 69 : move16();
136 : }
137 : ELSE
138 : {
139 0 : sfbWidths = lpcBndsParam->bandLengthsTCX10;
140 0 : cnt = 32;
141 0 : move16();
142 : }
143 :
144 : /* calc sfb offsets */
145 69 : specStartOffset = 0;
146 69 : move16();
147 :
148 4485 : FOR( i = 0; i < cnt; i++ )
149 : {
150 4416 : sfbOffset[i] = s_min( specStartOffset, L_frameTCX );
151 4416 : move16();
152 4416 : specStartOffset = add( specStartOffset, sfbWidths[i] );
153 :
154 4416 : IF( GE_16( sfbOffset[i], L_frameTCX ) )
155 : {
156 0 : BREAK;
157 : }
158 : }
159 :
160 69 : *sfbCnt = i;
161 69 : move16();
162 69 : sfbOffset[*sfbCnt] = s_min( specStartOffset, L_frameTCX );
163 69 : move16();
164 :
165 69 : IF( LT_16( sfbOffset[*sfbCnt], L_frameTCX ) )
166 : {
167 66 : Word16 nMissingBins = sub( L_frameTCX, sfbOffset[*sfbCnt] );
168 :
169 66 : IF( LT_16( shr( (Word16) sfbWidths[i], 1 ), nMissingBins ) )
170 : {
171 66 : ( *sfbCnt ) = add( ( *sfbCnt ), 1 );
172 66 : move16();
173 : }
174 66 : sfbOffset[*sfbCnt] = L_frameTCX;
175 66 : move16();
176 : }
177 :
178 69 : return;
179 : }
180 :
181 :
182 1 : static void get_custom_ls_conversion_matrix_fx(
183 : const EFAP_HANDLE hEFAPdata, /* i : EFAP handle */
184 : const IVAS_OUTPUT_SETUP hTransSetup, /* i : Transport channel configuration handle */
185 : const LSSETUP_CUSTOM_HANDLE hLsSetupCustom, /* i : Custom LS Setup handle */
186 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion /* o : LS Setup Conversion Handle */
187 : )
188 : {
189 : Word16 ch_in, ch_in_woLFE;
190 : Word16 ch_out, ch_out_woLFE;
191 : Word16 nchan_in, nchan_out;
192 : Word16 lfe_in_idx, lfe_out_idx;
193 :
194 : Word32 dmxCoeff_LFE;
195 : Word32 tmp_gains[MAX_OUTPUT_CHANNELS];
196 :
197 1 : lfe_in_idx = -1;
198 1 : move16();
199 1 : lfe_out_idx = -1;
200 1 : move16();
201 :
202 1 : nchan_in = add( hTransSetup.nchan_out_woLFE, hTransSetup.num_lfe );
203 1 : nchan_out = add( hLsSetupCustom->num_spk, hLsSetupCustom->num_lfe );
204 :
205 : /* The below code will need to be restructured in case additional LFEs must be supported */
206 1 : if ( hTransSetup.num_lfe > 0 )
207 : {
208 1 : lfe_in_idx = hTransSetup.index_lfe[0];
209 1 : move16();
210 : }
211 1 : if ( hLsSetupCustom->num_lfe > 0 )
212 : {
213 0 : lfe_out_idx = hLsSetupCustom->lfe_idx[0];
214 0 : move16();
215 : }
216 :
217 1 : IF( EQ_16( hTransSetup.nchan_out_woLFE, 1 ) )
218 : {
219 0 : dmxCoeff_LFE = ONE_IN_Q30;
220 0 : move32();
221 : }
222 : ELSE
223 : {
224 1 : dmxCoeff_LFE = L_shl( (Word32) div_s( 1, hTransSetup.nchan_out_woLFE ), Q15 ); // Q30
225 : }
226 :
227 7 : FOR( ( ch_in = 0, ch_in_woLFE = 0 ); ch_in < nchan_in; ( ch_in++, ch_in_woLFE++ ) )
228 : {
229 6 : IF( EQ_16( lfe_in_idx, ch_in ) )
230 : {
231 1 : IF( lfe_out_idx >= 0 )
232 : {
233 : /* re-route LFE */
234 0 : hLsSetUpConversion->dmxMtx_fx[ch_in][lfe_out_idx] = ONE_IN_Q30;
235 0 : move32();
236 : }
237 : ELSE
238 : {
239 : /* mix the LFE to all channels */
240 1 : set32_fx( hLsSetUpConversion->dmxMtx_fx[ch_in], dmxCoeff_LFE, nchan_out );
241 : }
242 :
243 1 : ch_in_woLFE = sub( ch_in_woLFE, 1 );
244 : }
245 5 : ELSE IF( NE_16( lfe_out_idx, ch_in ) )
246 : {
247 : /* Set the values of hLsSetUpConversion->dmxMtx to EFAP gains, skipping LFE */
248 5 : efap_determine_gains_fx( hEFAPdata, tmp_gains, hTransSetup.ls_azimuth_fx[ch_in_woLFE], hTransSetup.ls_elevation_fx[ch_in_woLFE], EFAP_MODE_EFAP );
249 :
250 85 : FOR( ( ch_out = 0, ch_out_woLFE = 0 ); ch_out < nchan_out; ( ch_out++, ch_out_woLFE++ ) )
251 : {
252 80 : IF( EQ_16( lfe_out_idx, ch_out ) )
253 : {
254 0 : ch_out_woLFE = sub( ch_out_woLFE, 1 );
255 : }
256 : ELSE
257 : {
258 80 : hLsSetUpConversion->dmxMtx_fx[ch_in][ch_out] = tmp_gains[ch_out_woLFE]; // Q30
259 80 : move32();
260 : }
261 : }
262 : }
263 : }
264 :
265 1 : return;
266 : }
267 :
268 125 : static ivas_error get_ls_conversion_matrix_fx(
269 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion,
270 : const AUDIO_CONFIG input_config,
271 : const AUDIO_CONFIG output_config )
272 : {
273 : Word16 i, k;
274 : Word16 ch_in, ch_out;
275 : Word16 nchan_in, nchan_out;
276 : Word16 index;
277 : Word32 value;
278 : const LS_CONVERSION_MATRIX_FX *conversion_matrix_fx;
279 :
280 125 : conversion_matrix_fx = NULL;
281 :
282 125 : nchan_in = audioCfg2channels( input_config );
283 125 : nchan_out = audioCfg2channels( output_config );
284 :
285 : /* Search the table for a mapping */
286 3437 : FOR( i = 0; i < LS_SETUP_CONVERSION_NUM_MAPPINGS; i++ )
287 : {
288 3437 : test();
289 3437 : IF( ( EQ_32( input_config, ls_conversion_mapping_fx[i].input_config ) ) && ( EQ_32( output_config, ls_conversion_mapping_fx[i].output_config ) ) )
290 : {
291 : /* Special handling for MONO and STEREO downmix */
292 125 : test();
293 125 : IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) )
294 : {
295 82 : FOR( ( ch_in = 0, k = 0 ); ch_in < nchan_in; ( ch_in++, k++ ) )
296 : {
297 : /* Skip two rows in the matrix for 5.1.x formats */
298 74 : test();
299 74 : test();
300 74 : IF( EQ_16( ch_in, 6 ) && ( EQ_32( input_config, IVAS_AUDIO_CONFIG_5_1_2 ) || EQ_32( input_config, IVAS_AUDIO_CONFIG_5_1_4 ) ) )
301 : {
302 1 : k = add( k, 2 );
303 : }
304 :
305 216 : FOR( ch_out = 0; ch_out < nchan_out; ch_out++ )
306 : {
307 142 : IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) )
308 : {
309 6 : hLsSetUpConversion->dmxMtx_fx[ch_in][ch_out] = ls_conversion_cicpX_mono_fx[k][ch_out]; // Q30
310 6 : move32();
311 : }
312 : ELSE
313 : {
314 136 : hLsSetUpConversion->dmxMtx_fx[ch_in][ch_out] = ls_conversion_cicpX_stereo_fx[k][ch_out]; // Q30
315 136 : move32();
316 : }
317 : }
318 : }
319 8 : return IVAS_ERR_OK;
320 : }
321 : ELSE
322 : {
323 117 : conversion_matrix_fx = ls_conversion_mapping_fx[i].conversion_matrix_fx;
324 :
325 : /* If a mapping is defined with a NULL matrix, 1:1 upmix of input channels */
326 117 : IF( conversion_matrix_fx == NULL )
327 : {
328 812 : FOR( k = 0; k < nchan_in; k++ )
329 : {
330 696 : hLsSetUpConversion->dmxMtx_fx[k][k] = ONE_IN_Q30;
331 696 : move32();
332 : }
333 116 : return IVAS_ERR_OK;
334 : }
335 : ELSE
336 : {
337 9 : FOR( k = 1; k < ( conversion_matrix_fx[0].index + 1 ); k++ )
338 : {
339 8 : index = conversion_matrix_fx[k].index;
340 8 : move16();
341 8 : value = conversion_matrix_fx[k].value; // Q30
342 8 : move16();
343 :
344 8 : IF( index != 0 )
345 : {
346 7 : ch_in = idiv1616( index, nchan_out );
347 : }
348 : ELSE
349 : {
350 1 : ch_in = 0;
351 1 : move16();
352 : }
353 8 : ch_out = index % nchan_out;
354 8 : move16();
355 :
356 8 : hLsSetUpConversion->dmxMtx_fx[ch_in][ch_out] = value; // Q30
357 8 : move32();
358 : }
359 : }
360 1 : return IVAS_ERR_OK;
361 : }
362 : }
363 : }
364 :
365 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "The conversion matrix between these formats is not defined!\n" );
366 : }
367 :
368 :
369 : /*-------------------------------------------------------------------------
370 : * ivas_ls_setup_conversion_open()
371 : *
372 : * Open the LS configuration Conversion Module
373 : *-------------------------------------------------------------------------*/
374 :
375 126 : ivas_error ivas_ls_setup_conversion_open_fx(
376 : Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
377 : )
378 : {
379 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
380 : Word16 chIdx, inChannels, outChannels;
381 : Word16 output_frame;
382 : Word32 output_Fs;
383 : Word16 paramUpmixMonoStereo;
384 : #ifdef FIX_1052_EXT_OUTPUT
385 : ivas_error error;
386 : #endif
387 :
388 126 : test();
389 126 : test();
390 126 : test();
391 126 : IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) && ( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_STEREO ) ) )
392 : {
393 1 : paramUpmixMonoStereo = TRUE;
394 1 : move16();
395 : }
396 : ELSE
397 : {
398 125 : paramUpmixMonoStereo = FALSE;
399 125 : move16();
400 : }
401 126 : output_Fs = st_ivas->hDecoderConfig->output_Fs;
402 126 : move32();
403 126 : outChannels = st_ivas->hDecoderConfig->nchan_out;
404 126 : move16();
405 126 : output_frame = (Word16) ( output_Fs / FRAMES_PER_SEC );
406 :
407 : /* Allocate memory to the handle */
408 126 : IF( ( hLsSetUpConversion = (LSSETUP_CONVERSION_HANDLE) malloc( sizeof( LSSETUP_CONVERSION_STRUCT ) ) ) == NULL )
409 : {
410 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
411 : }
412 :
413 126 : assert( LE_16( outChannels, MAX_OUTPUT_CHANNELS ) );
414 :
415 126 : IF( EQ_32( st_ivas->renderer_type, RENDERER_MC_PARAMMC ) )
416 : {
417 57 : inChannels = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe );
418 57 : hLsSetUpConversion->sfbCnt = (Word16) ( L_add( output_Fs, 400 ) / CLDFB_BANDWIDTH );
419 715 : FOR( chIdx = 0; chIdx < outChannels; chIdx++ )
420 : {
421 658 : IF( ( hLsSetUpConversion->targetEnergyPrev_fx[chIdx] = (Word32 *) malloc( hLsSetUpConversion->sfbCnt * sizeof( Word32 ) ) ) == NULL )
422 : {
423 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
424 : }
425 658 : IF( ( hLsSetUpConversion->dmxEnergyPrev_fx[chIdx] = (Word32 *) malloc( hLsSetUpConversion->sfbCnt * sizeof( Word32 ) ) ) == NULL )
426 : {
427 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
428 : }
429 658 : set32_fx( hLsSetUpConversion->targetEnergyPrev_fx[chIdx], 0, hLsSetUpConversion->sfbCnt );
430 658 : hLsSetUpConversion->te_prev_exp[chIdx] = 0;
431 658 : move16();
432 658 : set32_fx( hLsSetUpConversion->dmxEnergyPrev_fx[chIdx], 0, hLsSetUpConversion->sfbCnt );
433 658 : hLsSetUpConversion->dmx_prev_exp[chIdx] = 0;
434 658 : move16();
435 : }
436 311 : FOR( ; chIdx < MAX_CICP_CHANNELS; chIdx++ )
437 : {
438 254 : hLsSetUpConversion->targetEnergyPrev_fx[chIdx] = NULL;
439 254 : hLsSetUpConversion->dmxEnergyPrev_fx[chIdx] = NULL;
440 : }
441 : }
442 : ELSE
443 : {
444 69 : test();
445 69 : IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) )
446 : {
447 1 : IF( EQ_16( paramUpmixMonoStereo, TRUE ) )
448 : {
449 1 : inChannels = audioCfg2channels( IVAS_AUDIO_CONFIG_5_1_2 );
450 : }
451 : ELSE
452 : {
453 0 : inChannels = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe );
454 : }
455 : }
456 : ELSE
457 : {
458 68 : inChannels = st_ivas->nchan_transport;
459 68 : move16();
460 : }
461 :
462 : /*Initialization of MDCT bands with TCX20 resolution */
463 69 : ivas_lssetupconversion_mdct_init_bands_fx( output_frame, TCX_20_CORE, &hLsSetUpConversion->sfbOffset[0], &hLsSetUpConversion->sfbCnt );
464 69 : IF( ( hLsSetUpConversion->targetEnergyPrev_fx[0] = (Word32 *) malloc( ( MAX_SFB + 2 ) * sizeof( Word32 ) ) ) == NULL )
465 : {
466 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
467 : }
468 69 : IF( ( hLsSetUpConversion->dmxEnergyPrev_fx[0] = (Word32 *) malloc( ( MAX_SFB + 2 ) * sizeof( Word32 ) ) ) == NULL )
469 : {
470 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
471 : }
472 :
473 1104 : FOR( chIdx = 1; chIdx < MAX_CICP_CHANNELS; chIdx++ )
474 : {
475 1035 : hLsSetUpConversion->targetEnergyPrev_fx[chIdx] = NULL;
476 1035 : hLsSetUpConversion->dmxEnergyPrev_fx[chIdx] = NULL;
477 : }
478 69 : set32_fx( hLsSetUpConversion->targetEnergyPrev_fx[0], 0, MAX_SFB + 2 );
479 69 : set32_fx( hLsSetUpConversion->dmxEnergyPrev_fx[0], 0, MAX_SFB + 2 );
480 :
481 69 : hLsSetUpConversion->te_prev_exp[0] = 0;
482 69 : hLsSetUpConversion->dmx_prev_exp[0] = 0;
483 69 : move16();
484 69 : move16();
485 : }
486 :
487 : /* Initialize the DMX conversion matrix */
488 910 : FOR( chIdx = 0; chIdx < inChannels; chIdx++ )
489 : {
490 : /* Allocate memory depending on the number of output channels */
491 784 : IF( ( hLsSetUpConversion->dmxMtx_fx[chIdx] = (Word32 *) malloc( outChannels * sizeof( Word32 ) ) ) == NULL )
492 : {
493 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for temp dmx matrix \n" ) );
494 : }
495 784 : set32_fx( hLsSetUpConversion->dmxMtx_fx[chIdx], 0, outChannels );
496 : }
497 :
498 1358 : FOR( ; chIdx < MAX_CICP_CHANNELS; chIdx++ )
499 : {
500 1232 : hLsSetUpConversion->dmxMtx_fx[chIdx] = NULL;
501 : }
502 :
503 126 : IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
504 : {
505 1 : get_custom_ls_conversion_matrix_fx( st_ivas->hEFAPdata, st_ivas->hTransSetup, st_ivas->hLsSetupCustom, hLsSetUpConversion );
506 : }
507 : ELSE
508 : {
509 125 : IF( NE_32( st_ivas->transport_config, IVAS_AUDIO_CONFIG_INVALID ) )
510 : {
511 125 : IF( EQ_16( paramUpmixMonoStereo, TRUE ) )
512 : {
513 : #ifdef FIX_1052_EXT_OUTPUT
514 1 : IF( ( error = get_ls_conversion_matrix_fx( hLsSetUpConversion, IVAS_AUDIO_CONFIG_5_1_2, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
515 : {
516 0 : return error;
517 : }
518 : #else
519 : get_ls_conversion_matrix_fx( hLsSetUpConversion, IVAS_AUDIO_CONFIG_5_1_2, st_ivas->hDecoderConfig->output_config );
520 : #endif
521 : }
522 : ELSE
523 : {
524 : #ifdef FIX_1052_EXT_OUTPUT
525 124 : IF( ( error = get_ls_conversion_matrix_fx( hLsSetUpConversion, st_ivas->transport_config, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
526 : {
527 0 : return error;
528 : }
529 : #else
530 : get_ls_conversion_matrix_fx( hLsSetUpConversion, st_ivas->transport_config, st_ivas->hDecoderConfig->output_config );
531 : #endif
532 : }
533 : }
534 : ELSE
535 : {
536 : #ifdef FIX_1052_EXT_OUTPUT
537 0 : IF( ( error = get_ls_conversion_matrix_fx( hLsSetUpConversion, st_ivas->intern_config, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
538 : {
539 0 : return error;
540 : }
541 : #else
542 : get_ls_conversion_matrix_fx( hLsSetUpConversion, st_ivas->intern_config, st_ivas->hDecoderConfig->output_config );
543 : #endif
544 : }
545 : }
546 :
547 126 : st_ivas->hLsSetUpConversion = hLsSetUpConversion;
548 :
549 126 : return IVAS_ERR_OK;
550 : }
551 :
552 : /*-------------------------------------------------------------------------
553 : * ivas_ls_setup_conversion_close()
554 : *
555 : * Close the LS configuration Conversion Module
556 : *-------------------------------------------------------------------------*/
557 :
558 869 : void ivas_ls_setup_conversion_close_fx(
559 : LSSETUP_CONVERSION_HANDLE *hLsSetUpConversion /* i/o: LS converter handle */
560 : )
561 : {
562 : Word16 idx;
563 869 : test();
564 869 : IF( hLsSetUpConversion == NULL || *hLsSetUpConversion == NULL )
565 : {
566 743 : return;
567 : }
568 :
569 2142 : FOR( idx = 0; idx < MAX_CICP_CHANNELS; idx++ )
570 : {
571 2016 : IF( ( *hLsSetUpConversion )->dmxMtx_fx[idx] != NULL )
572 : {
573 784 : free( ( *hLsSetUpConversion )->dmxMtx_fx[idx] );
574 784 : ( *hLsSetUpConversion )->dmxMtx_fx[idx] = NULL;
575 : }
576 :
577 2016 : IF( ( *hLsSetUpConversion )->targetEnergyPrev_fx[idx] != NULL )
578 : {
579 727 : free( ( *hLsSetUpConversion )->targetEnergyPrev_fx[idx] );
580 727 : ( *hLsSetUpConversion )->targetEnergyPrev_fx[idx] = NULL;
581 : }
582 :
583 2016 : IF( ( *hLsSetUpConversion )->dmxEnergyPrev_fx[idx] != NULL )
584 : {
585 727 : free( ( *hLsSetUpConversion )->dmxEnergyPrev_fx[idx] );
586 727 : ( *hLsSetUpConversion )->dmxEnergyPrev_fx[idx] = NULL;
587 : }
588 : }
589 :
590 126 : free( *hLsSetUpConversion );
591 126 : *hLsSetUpConversion = NULL;
592 :
593 126 : return;
594 : }
595 :
596 : /*-------------------------------------------------------------------------
597 : * ivas_ls_setup_conversion()
598 : *
599 : * Convert (downmix or upmix) the input LS configuration
600 : * to output LS configuration in time domain
601 : *-------------------------------------------------------------------------*/
602 :
603 7464 : void ivas_ls_setup_conversion_fx(
604 : Decoder_Struct *st_ivas, /* i : IVAS decoder structure */
605 : const Word16 input_chans, /* i : number of input channels to the renderer */
606 : const Word16 output_frame, /* i : frame length */
607 : Word32 *input[], /* i : LS input/output synthesis signal Qx*/
608 : Word32 *output[] /* i/o: LS input/output synthesis signal Qx*/
609 : )
610 : {
611 : Word16 chInIdx, chOutIdx, idx;
612 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
613 : Word32 dmxCoeff, tmpVal;
614 : Word32 output_tmp[MAX_OUTPUT_CHANNELS][L_FRAME48k]; // Qx
615 :
616 7464 : push_wmops( "LS_Renderer" );
617 :
618 7464 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
619 :
620 69432 : FOR( chOutIdx = 0; chOutIdx < st_ivas->hDecoderConfig->nchan_out; chOutIdx++ )
621 : {
622 61968 : set32_fx( output_tmp[chOutIdx], 0, output_frame );
623 434056 : FOR( chInIdx = 0; chInIdx < input_chans; chInIdx++ )
624 : {
625 372088 : dmxCoeff = hLsSetUpConversion->dmxMtx_fx[chInIdx][chOutIdx];
626 372088 : move32();
627 :
628 372088 : IF( dmxCoeff == 0 )
629 : {
630 306064 : CONTINUE;
631 : }
632 66024 : ELSE IF( EQ_32( dmxCoeff, ONE_IN_Q30 ) )
633 : {
634 21983384 : FOR( idx = 0; idx < output_frame; idx++ )
635 : {
636 21954840 : output_tmp[chOutIdx][idx] = L_add( output_tmp[chOutIdx][idx], input[chInIdx][idx] );
637 21954840 : move32();
638 : }
639 : }
640 : ELSE
641 : {
642 35864680 : FOR( idx = 0; idx < output_frame; idx++ )
643 : {
644 35827200 : tmpVal = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), input[chInIdx][idx] );
645 35827200 : output_tmp[chOutIdx][idx] = L_add( output_tmp[chOutIdx][idx], tmpVal );
646 35827200 : move32();
647 : }
648 : }
649 : }
650 : }
651 :
652 : /* Copy to output buffer */
653 69432 : FOR( chOutIdx = 0; chOutIdx < st_ivas->hDecoderConfig->nchan_out; chOutIdx++ )
654 : {
655 61968 : Copy32( output_tmp[chOutIdx], output[chOutIdx], output_frame );
656 : }
657 :
658 7464 : pop_wmops();
659 :
660 7464 : return;
661 : }
662 :
663 : /*-------------------------------------------------------------------------
664 : * ivas_ls_setup_conversion_process_mdct()
665 : *
666 : * Equalization in MDCT Domain
667 : *-------------------------------------------------------------------------*/
668 :
669 6504 : void ivas_ls_setup_conversion_process_mdct_fx(
670 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
671 : Word32 *output[] /* i/o: output synthesis signal */
672 : )
673 : {
674 : /* Declaration of all required variables */
675 : Word16 i, bandIdx, chInIdx, chOutIdx, cpe_idx, subFrameIdx, binIdx, idx, j;
676 : Word16 inChannels, outChannels, num_CPE;
677 : Word16 transform_type[MAX_CICP_CHANNELS][2];
678 : Word16 frameSize;
679 : Word32 targetEnergy[MAX_SFB + 2], dmxEnergy[MAX_SFB + 2];
680 : Word16 dmxEnergy_exp[MAX_SFB + 2], dmxEnergy_exp_temp;
681 : Word32 dmxCoeff;
682 : Word32 dmxSignalReal[L_FRAME48k], dmxSignalImag[L_FRAME48k];
683 : Word32 eqGain;
684 : Word32 *sig[NB_DIV], *pTmp[NB_DIV], *x[MAX_CICP_CHANNELS][NB_DIV];
685 : Word32 mdst[L_FRAME48k];
686 : Word32 convertRes[L_FRAME48k];
687 : Word16 start, stop, start_tcx5, stop_tcx5;
688 : Word16 mct_chan_mode[MAX_CICP_CHANNELS];
689 :
690 : /* Declare all handles */
691 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
692 : CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS];
693 :
694 6504 : push_wmops( "LS_Renderer_MDCT" );
695 :
696 : /* Assign all the declared variables */
697 6504 : inChannels = st_ivas->nchan_transport;
698 6504 : move16();
699 6504 : outChannels = st_ivas->hDecoderConfig->nchan_out;
700 6504 : move16();
701 6504 : num_CPE = st_ivas->nCPE;
702 6504 : move16();
703 :
704 : /* Assign output pointer to variable x */
705 :
706 : // Scale the array
707 6504 : Word16 q_output = 31;
708 6504 : move16();
709 45728 : FOR( i = 0; i < inChannels; ++i )
710 : {
711 39224 : q_output = s_min( q_output, L_norm_arr( output[i], L_FRAME48k ) );
712 : }
713 :
714 6504 : Word16 tmp_sub = sub( st_ivas->hLsSetUpConversion->sfbOffset[st_ivas->hLsSetUpConversion->sfbCnt], st_ivas->hLsSetUpConversion->sfbOffset[st_ivas->hLsSetUpConversion->sfbCnt - 1] );
715 6504 : Word16 guard_1 = shr( add( find_guarded_bits_fx( tmp_sub ), 1 ), 1 );
716 6504 : Word16 guard_2 = find_guarded_bits_fx( L_mult0( outChannels, inChannels ) );
717 6504 : q_output = sub( q_output, s_max( guard_1, guard_2 ) );
718 : /* Increase the guard bit by 1 to avoid overflow only if q_output is positive */
719 6504 : if ( q_output > 0 )
720 : {
721 4724 : q_output = sub( q_output, 1 );
722 : }
723 :
724 45728 : FOR( i = 0; i < inChannels; ++i )
725 : {
726 37694264 : FOR( j = 0; j < L_FRAME48k; ++j )
727 : {
728 37655040 : output[i][j] = L_shl( output[i][j], q_output );
729 : }
730 : }
731 :
732 45728 : FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
733 : {
734 39224 : x[chInIdx][0] = output[chInIdx]; // Q(q_output)
735 39224 : x[chInIdx][1] = output[chInIdx] + L_FRAME48k / 2; // Q(q_output)
736 : }
737 :
738 : /* Assign all the declared handles*/
739 6504 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
740 26116 : FOR( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
741 : {
742 19612 : hCPE[cpe_idx] = st_ivas->hCPE[cpe_idx];
743 : }
744 :
745 : /* Get the core type */
746 26116 : FOR( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
747 : {
748 58836 : FOR( idx = 0; idx < CPE_CHANNELS; idx++ )
749 : {
750 : /* get the channel index */
751 39224 : chInIdx = add( imult1616( cpe_idx, CPE_CHANNELS ), idx );
752 39224 : assert( LE_16( chInIdx, inChannels ) );
753 39224 : transform_type[chInIdx][0] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[0];
754 39224 : move16();
755 39224 : transform_type[chInIdx][1] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[1];
756 39224 : move16();
757 39224 : mct_chan_mode[chInIdx] = hCPE[cpe_idx]->hCoreCoder[idx]->mct_chan_mode;
758 39224 : move16();
759 : }
760 : }
761 :
762 : /* set overall frequency resolution of (sub)frame to maximum of (sub)frame, requires conversion if both channels are not the same */
763 6504 : frameSize = hLsSetUpConversion->sfbOffset[hLsSetUpConversion->sfbCnt];
764 6504 : move16();
765 :
766 6504 : set32_fx( targetEnergy, 0, MAX_SFB + 2 );
767 6504 : set32_fx( dmxEnergy, 0, MAX_SFB + 2 );
768 6504 : set16_fx( dmxEnergy_exp, 0, MAX_SFB + 2 );
769 6504 : dmxEnergy_exp_temp = 0;
770 6504 : move16();
771 :
772 57152 : FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
773 : {
774 : /* Step 0: Set the buffers to zero */
775 50648 : set32_fx( dmxSignalReal, 0, frameSize );
776 50648 : set32_fx( dmxSignalImag, 0, frameSize );
777 :
778 354936 : FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
779 : {
780 304288 : dmxCoeff = hLsSetUpConversion->dmxMtx_fx[chInIdx][chOutIdx]; // Q30
781 304288 : move32();
782 :
783 304288 : test();
784 304288 : IF( NE_16( chInIdx, LFE_CHANNEL ) && NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
785 : {
786 : /* Step 1: Compute the target energy and DMX signal (possible since we have all signals in TCX20 resolution) */
787 199937 : IF( dmxCoeff )
788 : {
789 : Word32 tmpDMXSig, targetEne;
790 :
791 : /* Convert the signal resolution to TCX20 */
792 : /* initially, set pointers to input; if conversion occurs in (sub)frame, set to convertRes */
793 28824 : pTmp[0] = x[chInIdx][0]; // Q(q_output)
794 28824 : sig[0] = pTmp[0];
795 28824 : pTmp[1] = x[chInIdx][1];
796 28824 : sig[1] = pTmp[1]; // Q(q_output)
797 :
798 : /* convert (sub)frames to higher frequency resolution */
799 28824 : IF( NE_16( transform_type[chInIdx][0], TCX_20 ) )
800 : {
801 1545 : FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
802 : {
803 1030 : IF( EQ_16( transform_type[chInIdx][subFrameIdx], TCX_5 ) )
804 : {
805 : /* subframe is TCX5, but TCX10 or TCX20 in other channel -> convert channel with TCX5 to TCX10 resolution */
806 544 : sig[subFrameIdx] = convertRes + L_shr( L_mult0( subFrameIdx, frameSize ), 1 );
807 544 : pTmp[subFrameIdx] = sig[subFrameIdx];
808 544 : convert_coeffs_to_higher_res_fx( x[chInIdx][subFrameIdx], x[chInIdx][subFrameIdx] + shr( frameSize, 2 ), pTmp[subFrameIdx], shr( frameSize, 2 ) );
809 : }
810 : }
811 :
812 : /* convert channel with TCX10 to TCX20 resolution */
813 515 : sig[0] = convertRes;
814 515 : convert_coeffs_to_higher_res_fx( pTmp[0], pTmp[1], sig[0], frameSize / 2 );
815 : }
816 :
817 : /* MDST estimate */
818 28824 : mdst[0] = mdst[frameSize - 1] = 0;
819 28824 : move32();
820 28824 : move32();
821 27514216 : FOR( i = 1; i < frameSize - 1; i++ )
822 : {
823 27485392 : mdst[i] = L_sub( sig[0][i + 1], sig[0][i - 1] ); // Q(q_output)
824 : }
825 :
826 1901984 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
827 : {
828 1873160 : start = hLsSetUpConversion->sfbOffset[bandIdx];
829 1873160 : move16();
830 1873160 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
831 1873160 : move16();
832 :
833 1873160 : targetEne = 0;
834 1873160 : move32();
835 :
836 : /* Loop over all the bins in the band */
837 29416200 : FOR( binIdx = start; binIdx < stop; binIdx++ )
838 : {
839 27543040 : tmpDMXSig = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), sig[0][binIdx] );
840 27543040 : dmxSignalReal[binIdx] = L_add( dmxSignalReal[binIdx], tmpDMXSig );
841 27543040 : move32();
842 27543040 : targetEne = L_add( targetEne, Mpy_32_32( tmpDMXSig, tmpDMXSig ) );
843 :
844 27543040 : tmpDMXSig = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), mdst[binIdx] );
845 27543040 : dmxSignalImag[binIdx] = L_add( dmxSignalImag[binIdx], tmpDMXSig );
846 27543040 : move32();
847 27543040 : targetEne = L_add( targetEne, Mpy_32_32( tmpDMXSig, tmpDMXSig ) );
848 : }
849 1873160 : targetEnergy[bandIdx] = L_add( targetEnergy[bandIdx], targetEne );
850 1873160 : move32();
851 : } /* end of band loop */
852 : }
853 : }
854 : } /* end of chInIdx loop */
855 :
856 3342688 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
857 : {
858 : Word32 tmpReal, tmpImag, DMXEne;
859 : Word16 DMXEne_exp;
860 :
861 3292040 : start = hLsSetUpConversion->sfbOffset[bandIdx];
862 3292040 : move16();
863 3292040 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
864 3292040 : move16();
865 :
866 : /* Loop over all the bins in the band */
867 3292040 : DMXEne = 0;
868 3292040 : move32();
869 3292040 : DMXEne_exp = 0;
870 3292040 : move16();
871 51888520 : FOR( binIdx = start; binIdx < stop; binIdx++ )
872 : {
873 48596480 : tmpReal = dmxSignalReal[binIdx];
874 48596480 : move32();
875 48596480 : tmpImag = dmxSignalImag[binIdx];
876 48596480 : move32();
877 :
878 48596480 : DMXEne = BASOP_Util_Add_Mant32Exp( DMXEne, DMXEne_exp, L_add( Mpy_32_32( tmpReal, tmpReal ), Mpy_32_32( tmpImag, tmpImag ) ), sub( 40, shl( q_output, 1 ) ), &DMXEne_exp );
879 : }
880 3292040 : dmxEnergy[bandIdx] = BASOP_Util_Add_Mant32Exp( dmxEnergy[bandIdx], dmxEnergy_exp[bandIdx], DMXEne, DMXEne_exp, &dmxEnergy_exp[bandIdx] );
881 3292040 : move32();
882 3292040 : dmxEnergy_exp_temp = s_max( dmxEnergy_exp_temp, dmxEnergy_exp[bandIdx] );
883 : }
884 : } /* end of out channel loop */
885 :
886 : /* Scaling to common exponent */
887 474792 : FOR( bandIdx = 0; bandIdx < MAX_SFB + 2; bandIdx++ )
888 : {
889 468288 : dmxEnergy[bandIdx] = L_shl( dmxEnergy[bandIdx], sub( dmxEnergy_exp[bandIdx], dmxEnergy_exp_temp ) );
890 468288 : move32();
891 : }
892 : /* Step 3: Peform energy smoothing */
893 :
894 6504 : Word16 te_scale = getScaleFactor32( hLsSetUpConversion->targetEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt );
895 6504 : scale_sig32( hLsSetUpConversion->targetEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt, te_scale );
896 6504 : Word16 dmx_sacle = getScaleFactor32( hLsSetUpConversion->dmxEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt );
897 6504 : scale_sig32( hLsSetUpConversion->dmxEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt, dmx_sacle );
898 :
899 6504 : Word16 te_max_e = s_max( sub( 40, shl( q_output, 1 ) ), sub( hLsSetUpConversion->te_prev_exp[0], te_scale ) );
900 6504 : Word16 dmx_max_e = s_max( dmxEnergy_exp_temp, sub( hLsSetUpConversion->dmx_prev_exp[0], dmx_sacle ) );
901 :
902 429224 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
903 : {
904 422720 : targetEnergy[bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( targetEnergy[bandIdx], sub( te_max_e, sub( 40, shl( q_output, 1 ) ) ) ) ), Mpy_32_32( ( ONE_IN_Q31 - LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx], sub( te_max_e, sub( hLsSetUpConversion->te_prev_exp[0], te_scale ) ) ) ) );
905 422720 : move32();
906 422720 : dmxEnergy[bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( dmxEnergy[bandIdx], sub( dmx_max_e, dmxEnergy_exp_temp ) ) ), Mpy_32_32( ( ONE_IN_Q31 - LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx], sub( dmx_max_e, sub( hLsSetUpConversion->dmx_prev_exp[0], dmx_sacle ) ) ) ) );
907 422720 : move32();
908 422720 : hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx] = targetEnergy[bandIdx]; /* te_prev_exp = 40 - 2*q_output */
909 422720 : move32();
910 422720 : hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx] = dmxEnergy[bandIdx]; /* dmx_prev_exp = 40 - 2*q_output */
911 422720 : move32();
912 : }
913 :
914 6504 : hLsSetUpConversion->te_prev_exp[0] = te_max_e; /* te_prev_exp = 40 - 2*q_output */
915 6504 : move16();
916 6504 : hLsSetUpConversion->dmx_prev_exp[0] = dmx_max_e; /* dmx_prev_exp = 40 - 2*q_output */
917 6504 : move16();
918 :
919 45728 : FOR( i = 0; i < inChannels; ++i )
920 : {
921 37694264 : FOR( j = 0; j < L_FRAME48k; ++j )
922 : {
923 37655040 : output[i][j] = L_shr( output[i][j], q_output );
924 37655040 : move32();
925 : }
926 : }
927 :
928 : /* Step 4: Perform equalization */
929 45728 : FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
930 : {
931 39224 : test();
932 39224 : IF( NE_16( chInIdx, LFE_CHANNEL ) && NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
933 : {
934 25825 : IF( EQ_16( transform_type[chInIdx][0], TCX_20 ) )
935 : {
936 : /* TCX20 */
937 1671980 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
938 : {
939 1646642 : start = hLsSetUpConversion->sfbOffset[bandIdx];
940 1646642 : move16();
941 1646642 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
942 1646642 : move16();
943 :
944 : /* Compute Eq gains */
945 1646642 : ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain ); // Q(eqGain) = 30
946 25866162 : FOR( binIdx = start; binIdx < stop; binIdx++ )
947 : {
948 24219520 : x[chInIdx][0][binIdx] = Mpy_32_32( L_shl( x[chInIdx][0][binIdx], 1 ), eqGain ); // Q - 1
949 24219520 : move32();
950 : }
951 : }
952 : }
953 : ELSE
954 : {
955 487 : stop_tcx5 = 0;
956 487 : move16();
957 32110 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
958 : {
959 31623 : start = shr( hLsSetUpConversion->sfbOffset[bandIdx], 1 );
960 31623 : move16();
961 31623 : stop = shr( hLsSetUpConversion->sfbOffset[bandIdx + 1], 1 );
962 31623 : move16();
963 :
964 : /* Compute Eq gains */
965 31623 : ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain );
966 :
967 94869 : FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
968 : {
969 63246 : IF( EQ_16( transform_type[chInIdx][subFrameIdx], TCX_10 ) )
970 : {
971 : /* TCX10 */
972 246093 : FOR( binIdx = start; binIdx < stop; binIdx++ )
973 : {
974 216160 : x[chInIdx][subFrameIdx][binIdx] = Mpy_32_32( L_shl( x[chInIdx][subFrameIdx][binIdx], 1 ), eqGain );
975 216160 : move32();
976 : }
977 : }
978 : ELSE
979 : {
980 : /* TCX5*/
981 33313 : start_tcx5 = stop_tcx5;
982 33313 : move16();
983 33313 : stop_tcx5 = shr( add( stop, 1 ), 1 );
984 :
985 147633 : FOR( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
986 : {
987 114320 : x[chInIdx][subFrameIdx][binIdx] = Mpy_32_32( L_shl( x[chInIdx][subFrameIdx][binIdx], 1 ), eqGain );
988 114320 : move32();
989 114320 : x[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )] = Mpy_32_32( L_shl( x[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )], 1 ), eqGain );
990 114320 : move32();
991 : }
992 : }
993 : }
994 : }
995 : }
996 : }
997 : }
998 :
999 6504 : pop_wmops();
1000 6504 : return;
1001 : }
1002 :
1003 :
1004 : /*-------------------------------------------------------------------------
1005 : * ivas_ls_setup_conversion_process_mdct_param_mc()
1006 : *
1007 : * Equalization in MDCT Domain
1008 : *-------------------------------------------------------------------------*/
1009 :
1010 20 : void ivas_ls_setup_conversion_process_mdct_param_mc_fx(
1011 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
1012 : Word32 *x_fx[][NB_DIV],
1013 : Word16 x_e[CPE_CHANNELS][NB_DIV] /* i/o: Exponent for output synthesis signal */
1014 : )
1015 : {
1016 : Word32 targetEnergy_fx[MAX_SFB + 2], dmxEnergy_fx[MAX_SFB + 2];
1017 : Word32 eqGain_fx;
1018 : Word32 *sig_fx[MAX_CICP_CHANNELS][NB_DIV], *pTmp_fx[NB_DIV];
1019 : Word32 mdst_fx[MAX_CICP_CHANNELS][L_FRAME48k];
1020 : Word32 convertRes_fx[MAX_CICP_CHANNELS][L_FRAME48k];
1021 : Word32 cx_fx[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
1022 : Word32 cx_imag_fx[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
1023 : Word32 cy_fx[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS];
1024 : Word32 real_in_buffer_fx[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS];
1025 : Word32 imag_in_buffer_fx[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS];
1026 : Word32 real_buffer_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
1027 : Word32 imag_buffer_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
1028 : Word32 Nrqq_fx[MAX_OUTPUT_CHANNELS];
1029 : Word32 target_ch_ener_fx[MAX_OUTPUT_CHANNELS];
1030 : Word16 *ild_q_fx;
1031 :
1032 : Word32 DMXEne_fx;
1033 : Word32 dmxCoeff_fx;
1034 : Word32 dmxSignalReal_fx[L_FRAME48k], dmxSignalImag_fx[L_FRAME48k];
1035 :
1036 : Word32 tmpReal_fx, tmpImag_fx;
1037 : Word32 tmpDMXSig_fx;
1038 :
1039 : /* Declaration of all required variables */
1040 : Word16 i;
1041 : Word16 idx;
1042 : Word16 nchan_transport, nchan_out, nchan_transport_format;
1043 : Word16 chInIdx, chOutIdx, cpe_idx, subFrameIdx, binIdx;
1044 : Word16 band, bandIdx, num_bands;
1045 :
1046 : Word16 num_CPE;
1047 : Word16 transform_type[MAX_CICP_CHANNELS][2];
1048 : Word16 frameSize;
1049 :
1050 : Word16 start, stop, start_tcx5, stop_tcx5;
1051 : Word16 mct_chan_mode[MAX_CICP_CHANNELS];
1052 : Word16 all_ch_ignored; // Flag for checking if all channels are ignored
1053 :
1054 : /* Declare all handles */
1055 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
1056 : CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS];
1057 : PARAM_MC_DEC_HANDLE hParamMC;
1058 :
1059 : /* Step 0: Set the buffers to zero */
1060 20 : set_zero_fx( dmxSignalReal_fx, L_FRAME48k );
1061 20 : set_zero_fx( dmxSignalImag_fx, L_FRAME48k );
1062 :
1063 : /* Assign all the declared variables */
1064 20 : nchan_transport = st_ivas->nchan_transport;
1065 20 : nchan_out = st_ivas->hDecoderConfig->nchan_out;
1066 20 : num_CPE = st_ivas->nCPE;
1067 20 : nchan_transport_format = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe );
1068 20 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
1069 : /* Assign all the declared handles*/
1070 60 : FOR( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
1071 : {
1072 40 : hCPE[cpe_idx] = st_ivas->hCPE[cpe_idx];
1073 : }
1074 20 : hParamMC = st_ivas->hParamMC;
1075 :
1076 : /* Get the core type */
1077 60 : FOR( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
1078 : {
1079 120 : FOR( idx = 0; idx < CPE_CHANNELS; idx++ )
1080 : {
1081 : /* get the channel index */
1082 80 : chInIdx = add( cpe_idx * CPE_CHANNELS, idx );
1083 80 : assert( chInIdx <= nchan_transport );
1084 80 : transform_type[chInIdx][0] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[0];
1085 80 : move16();
1086 80 : transform_type[chInIdx][1] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[1];
1087 80 : move16();
1088 80 : mct_chan_mode[chInIdx] = hCPE[cpe_idx]->hCoreCoder[idx]->mct_chan_mode;
1089 80 : move16();
1090 : }
1091 : }
1092 :
1093 : /* set overall frequency resolution of (sub)frame to maximum of (sub)frame, requires conversion if both channels are not the same */
1094 20 : frameSize = hLsSetUpConversion->sfbOffset[hLsSetUpConversion->sfbCnt];
1095 20 : move16();
1096 20 : set_zero_fx( targetEnergy_fx, MAX_SFB + 2 );
1097 20 : set_zero_fx( dmxEnergy_fx, MAX_SFB + 2 );
1098 :
1099 80 : FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
1100 : {
1101 60 : IF( NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
1102 : {
1103 : /* initially, set pointers to input; if conversion occurs in (sub)frame, set to convertRes */
1104 60 : sig_fx[chInIdx][0] = pTmp_fx[0] = x_fx[chInIdx][0]; /*Q=31-x_e[chInIdx][0]*/
1105 60 : sig_fx[chInIdx][1] = pTmp_fx[1] = x_fx[chInIdx][1]; /*Q=31-x_e[chInIdx][1]*/
1106 : /* convert (sub)frames to higher frequency resolution */
1107 60 : IF( NE_16( transform_type[chInIdx][0], TCX_20 ) )
1108 : {
1109 21 : FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
1110 : {
1111 14 : IF( EQ_16( transform_type[chInIdx][subFrameIdx], TCX_5 ) )
1112 : {
1113 : /* subframe is TCX5, but TCX10 or TCX20 in other channel -> convert channel with TCX5 to TCX10 resolution */
1114 7 : pTmp_fx[subFrameIdx] = sig_fx[chInIdx][subFrameIdx] = convertRes_fx[chInIdx] + L_mult0( subFrameIdx, frameSize ) / 2;
1115 7 : convert_coeffs_to_higher_res_fx( x_fx[chInIdx][subFrameIdx], x_fx[chInIdx][subFrameIdx] + frameSize / 4, pTmp_fx[subFrameIdx], frameSize / 4 ); /*Q=31-x_e[chInIdx][subFrameIdx]*/
1116 : }
1117 : }
1118 :
1119 : /* convert channel with TCX10 to TCX20 resolution */
1120 7 : sig_fx[chInIdx][0] = convertRes_fx[chInIdx];
1121 :
1122 : // Scale_sig32(pTmp_fx_1_0, frameSize / 2, x_e[chInIdx][1] - x_e[chInIdx][0] ); /*Scaling down the Q from 31-x_e[chInIdx][1] to 31-x_e[chInIdx][0]*/
1123 7 : convert_coeffs_to_higher_res_fx( pTmp_fx[0], pTmp_fx[1], sig_fx[chInIdx][0], frameSize / 2 ); /*Q=31-x_e[chInIdx][0]*/
1124 : }
1125 : }
1126 : }
1127 20 : Word16 input_exp, output_exp = 0;
1128 20 : move16();
1129 :
1130 : /* precalculate MDST estimate */
1131 80 : FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
1132 : {
1133 60 : IF( NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
1134 : {
1135 60 : mdst_fx[chInIdx][0] = mdst_fx[chInIdx][frameSize - 1] = 0;
1136 60 : move32();
1137 38340 : FOR( i = 1; i < frameSize - 1; i++ )
1138 : {
1139 38280 : mdst_fx[chInIdx][i] = L_sub( sig_fx[chInIdx][0][i + 1], sig_fx[chInIdx][0][i - 1] ); /*Q=31-x_e[chInIdx][0]*/
1140 38280 : move32();
1141 : }
1142 : }
1143 : }
1144 :
1145 : /* Step 1.1, calculate Cx from MDST estimate */
1146 420 : FOR( bandIdx = 0; bandIdx < PARAM_MC_MAX_PARAMETER_BANDS; bandIdx++ )
1147 : {
1148 400 : set_zero_fx( cx_fx[bandIdx], PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
1149 400 : set_zero_fx( cx_imag_fx[bandIdx], PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
1150 : }
1151 20 : set_zero_fx( Nrqq_fx, MAX_OUTPUT_CHANNELS );
1152 20 : set_zero_fx( target_ch_ener_fx, MAX_OUTPUT_CHANNELS );
1153 20 : Word16 max_e = 0;
1154 20 : move16();
1155 20 : all_ch_ignored = 1;
1156 20 : move16();
1157 80 : FOR( idx = 0; idx < nchan_transport; idx++ )
1158 : {
1159 60 : IF( NE_16( mct_chan_mode[idx], MCT_CHAN_MODE_IGNORE ) )
1160 : {
1161 60 : max_e = s_max( max_e, x_e[idx][0] );
1162 60 : all_ch_ignored = 0;
1163 60 : move16();
1164 : }
1165 : }
1166 20 : if ( all_ch_ignored )
1167 : {
1168 0 : max_e = 31;
1169 0 : move16();
1170 : }
1171 280 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1172 : {
1173 260 : set_zero_fx( real_in_buffer_fx, PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS );
1174 260 : set_zero_fx( imag_in_buffer_fx, PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS );
1175 260 : set_zero_fx( real_buffer_fx, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
1176 260 : set_zero_fx( imag_buffer_fx, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
1177 :
1178 260 : start = hLsSetUpConversion->sfbOffset[bandIdx];
1179 260 : move16();
1180 260 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
1181 260 : move16();
1182 260 : num_bands = sub( stop, start );
1183 :
1184 13060 : FOR( i = 0; i < num_bands; i++ )
1185 : {
1186 12800 : band = add( start, i );
1187 51200 : FOR( idx = 0; idx < nchan_transport; idx++ )
1188 : {
1189 38400 : IF( NE_16( mct_chan_mode[idx], MCT_CHAN_MODE_IGNORE ) )
1190 : {
1191 38400 : real_in_buffer_fx[i + ( num_bands * idx )] = L_shr( sig_fx[idx][0][band], sub( max_e, x_e[idx][0] ) ); /*Setting the exponent to max_e*/
1192 38400 : imag_in_buffer_fx[i + ( num_bands * idx )] = L_shr( mdst_fx[idx][band], sub( max_e, x_e[idx][0] ) ); /*Setting the exponent to max_e*/
1193 38400 : move32();
1194 38400 : move32();
1195 : }
1196 : }
1197 : }
1198 260 : input_exp = max_e;
1199 260 : move16();
1200 260 : IF( all_ch_ignored == 0 )
1201 : {
1202 260 : Word16 shift = 1;
1203 260 : move16();
1204 38660 : FOR( i = 0; i < num_bands * nchan_transport; ++i )
1205 : {
1206 38400 : real_in_buffer_fx[i] = L_shr( real_in_buffer_fx[i], shift );
1207 38400 : move32();
1208 38400 : imag_in_buffer_fx[i] = L_shr( imag_in_buffer_fx[i], shift );
1209 38400 : move32();
1210 : }
1211 260 : input_exp = add( input_exp, shift );
1212 : }
1213 :
1214 260 : cmplx_matrix_square_fx( real_in_buffer_fx, imag_in_buffer_fx, num_bands, nchan_transport, real_buffer_fx, imag_buffer_fx, input_exp, &output_exp );
1215 260 : v_add_32( cx_fx[bandIdx], real_buffer_fx, cx_fx[bandIdx], i_mult( nchan_transport, nchan_transport ) ); /*Q=Q_real_buffer=Q_imag_buffer=output_exp*/
1216 260 : v_add_32( cx_imag_fx[bandIdx], imag_buffer_fx, cx_imag_fx[bandIdx], i_mult( nchan_transport, nchan_transport ) ); /*Q=Q_real_buffer=Q_imag_buffer=output_exp*/
1217 : }
1218 20 : if ( all_ch_ignored )
1219 : {
1220 0 : output_exp = 29;
1221 0 : move16();
1222 : }
1223 :
1224 20 : Word16 exp_in = 10, exp_out = 0;
1225 20 : move16();
1226 20 : move16();
1227 280 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1228 : {
1229 260 : DMXEne_fx = 0;
1230 260 : move16();
1231 260 : set_zero_fx( cy_fx, MAX_CICP_CHANNELS * MAX_CICP_CHANNELS );
1232 260 : set_zero_fx( Nrqq_fx, MAX_OUTPUT_CHANNELS );
1233 260 : set_zero_fx( target_ch_ener_fx, MAX_OUTPUT_CHANNELS );
1234 : /* Step 1.2, get target channel energies for the transported format, Nrqq calculation */
1235 260 : ild_q_fx = hParamMC->icld_q_fx + imult1616( bandIdx, hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe );
1236 260 : move16();
1237 3380 : FOR( chInIdx = 0; chInIdx < nchan_transport_format; chInIdx++ )
1238 : {
1239 3120 : Word32 ref_ener_fx = 0;
1240 3120 : move32();
1241 : Word16 ref_channel_cnt;
1242 : Word16 ref_channel_idx;
1243 :
1244 6240 : FOR( ref_channel_cnt = 0; ref_channel_cnt < hParamMC->hMetadataPMC->ild_mapping_conf->num_ref_channels[chInIdx]; ref_channel_cnt++ )
1245 : {
1246 3120 : ref_channel_idx = hParamMC->hMetadataPMC->ild_mapping_conf->ref_channel_idx[chInIdx][ref_channel_cnt];
1247 3120 : move16();
1248 3120 : ref_ener_fx = L_add( ref_ener_fx, cx_fx[bandIdx][ref_channel_idx + ( ref_channel_idx * nchan_transport )] ); /*Exponent=output_exp*/
1249 : }
1250 : Word32 temp;
1251 3120 : temp = BASOP_util_Pow2( L_mult0( ild_q_fx[chInIdx], 2721 /*log2(10)*(2^13)/10*/ ), exp_in, &exp_out );
1252 3120 : Nrqq_fx[hParamMC->hMetadataPMC->ild_mapping_conf->ild_index[chInIdx]] = L_shr( Mpy_32_16_1( ref_ener_fx, extract_l( Mpy_32_32( temp, hParamMC->hMetadataPMC->ild_factors_fx[chInIdx] ) ) ), sub( 2, exp_out ) ); /*exp=output_exp*/
1253 3120 : move32();
1254 : }
1255 :
1256 : /* Step 1.3 get target Cy () (with dmx matrix from CICPX to MONO/STEREO saved in hParamMC) */
1257 780 : FOR( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
1258 : {
1259 6760 : FOR( i = 0; i < nchan_transport_format; i++ )
1260 : {
1261 6240 : target_ch_ener_fx[chOutIdx] = L_add( target_ch_ener_fx[chOutIdx], L_shl( Mpy_32_32( Nrqq_fx[i], hParamMC->ls_conv_dmx_matrix_fx[chOutIdx + ( i * nchan_out )] ), 1 ) ); /*output_exp + 2*/
1262 6240 : move32();
1263 : }
1264 520 : cy_fx[chOutIdx + ( nchan_out * chOutIdx )] = target_ch_ener_fx[chOutIdx];
1265 520 : move32();
1266 : }
1267 :
1268 : /* Step 1.4 final target energy for the band would then be the sum over the diagonal of Cy*/
1269 780 : FOR( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
1270 : {
1271 520 : targetEnergy_fx[bandIdx] = L_add( targetEnergy_fx[bandIdx], cy_fx[chOutIdx + ( nchan_out * chOutIdx )] ); /*exp=output_exp+2*/
1272 520 : move32();
1273 : }
1274 :
1275 : /* Step 2: Calculate DMX ener */
1276 260 : start = hLsSetUpConversion->sfbOffset[bandIdx];
1277 260 : move16();
1278 260 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
1279 260 : move16();
1280 :
1281 780 : FOR( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
1282 : {
1283 2080 : FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
1284 : {
1285 1560 : IF( mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
1286 : {
1287 1560 : dmxCoeff_fx = hLsSetUpConversion->dmxMtx_fx[chInIdx][chOutIdx];
1288 :
1289 : /* Step 1: Compute the target energy and DMX signal (possible since we have all signals in TCX20 resolution) */
1290 1560 : IF( dmxCoeff_fx )
1291 : {
1292 : /* Loop over all the bins in the band */
1293 52240 : FOR( binIdx = start; binIdx < stop; binIdx++ )
1294 : {
1295 51200 : tmpDMXSig_fx = Mult_32_32( dmxCoeff_fx, L_shr( sig_fx[chInIdx][0][binIdx], sub( max_e, x_e[chInIdx][0] ) ) ); /*max_e+1*/
1296 51200 : dmxSignalReal_fx[binIdx] = L_add( dmxSignalReal_fx[binIdx], tmpDMXSig_fx );
1297 51200 : move32();
1298 :
1299 51200 : tmpDMXSig_fx = Mult_32_32( dmxCoeff_fx, L_shr( mdst_fx[chInIdx][binIdx], sub( max_e, x_e[chInIdx][0] ) ) ); /*max_e+1*/
1300 51200 : dmxSignalImag_fx[binIdx] = L_add( dmxSignalImag_fx[binIdx], tmpDMXSig_fx );
1301 51200 : move32();
1302 : }
1303 : }
1304 : }
1305 : }
1306 : /* Loop over all the bins in the band */
1307 520 : DMXEne_fx = 0;
1308 520 : move32();
1309 26120 : FOR( binIdx = start; binIdx < stop; binIdx++ )
1310 : {
1311 25600 : tmpReal_fx = L_shr( dmxSignalReal_fx[binIdx], 1 );
1312 25600 : tmpImag_fx = L_shr( dmxSignalImag_fx[binIdx], 1 );
1313 :
1314 25600 : DMXEne_fx = L_add( DMXEne_fx, Mult_32_32( tmpReal_fx, tmpReal_fx ) + Mult_32_32( tmpImag_fx, tmpImag_fx ) ); /*2*(max_e + 2)*/
1315 : }
1316 : }
1317 :
1318 260 : dmxEnergy_fx[bandIdx] = DMXEne_fx; /*2*(max_e+2)*/
1319 260 : move32();
1320 : }
1321 :
1322 : /* Step 3: Peform energy smoothing */
1323 280 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1324 : {
1325 260 : targetEnergy_fx[bandIdx] = L_add( Mult_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, targetEnergy_fx[bandIdx] ), Mult_32_32( L_sub( MAX_32, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx], add( output_exp, sub( 2, hLsSetUpConversion->te_prev_exp[0] ) ) ) ) ); /*output_exp + 2*/
1326 260 : move32();
1327 260 : dmxEnergy_fx[bandIdx] = L_add( Mult_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, dmxEnergy_fx[bandIdx] ), Mult_32_32( L_sub( MAX_32, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx], sub( shl( add( max_e, 2 ), 1 ), hLsSetUpConversion->dmx_prev_exp[0] ) ) ) ); /*2 * (max_e + 2)*/
1328 260 : move32();
1329 260 : hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx] = targetEnergy_fx[bandIdx];
1330 260 : move32();
1331 260 : hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx] = dmxEnergy_fx[bandIdx];
1332 260 : move32();
1333 : }
1334 20 : hLsSetUpConversion->te_prev_exp[0] = add( output_exp, 2 );
1335 20 : move16();
1336 20 : hLsSetUpConversion->dmx_prev_exp[0] = shl( add( max_e, 2 ), 1 );
1337 20 : move16();
1338 : /* Step 4: Perform equalization */
1339 80 : FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
1340 : {
1341 60 : IF( NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
1342 : {
1343 60 : IF( EQ_16( transform_type[chInIdx][0], TCX_20 ) )
1344 : {
1345 : /*TCX20*/
1346 742 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1347 : {
1348 689 : start = hLsSetUpConversion->sfbOffset[bandIdx];
1349 689 : move16();
1350 689 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
1351 689 : move16();
1352 :
1353 : /*Compute Eq gains */
1354 689 : ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy_fx[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy_fx[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain_fx );
1355 :
1356 34609 : FOR( binIdx = start; binIdx < stop; binIdx++ )
1357 : {
1358 33920 : x_fx[chInIdx][0][binIdx] = L_shl( Mult_32_32( x_fx[chInIdx][0][binIdx], eqGain_fx ), 1 );
1359 : }
1360 : }
1361 : }
1362 : ELSE
1363 : {
1364 7 : stop_tcx5 = 0;
1365 7 : move16();
1366 98 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1367 : {
1368 91 : start = shr( hLsSetUpConversion->sfbOffset[bandIdx], 1 );
1369 91 : stop = shr( hLsSetUpConversion->sfbOffset[bandIdx + 1], 1 );
1370 :
1371 : /*Compute Eq gains */
1372 91 : ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy_fx[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy_fx[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain_fx );
1373 :
1374 :
1375 273 : FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
1376 : {
1377 182 : IF( EQ_16( transform_type[chInIdx][subFrameIdx], TCX_10 ) )
1378 : {
1379 : /*TCX10*/
1380 2331 : FOR( binIdx = start; binIdx < stop; binIdx++ )
1381 : {
1382 2240 : x_fx[chInIdx][subFrameIdx][binIdx] = L_shl( Mult_32_32( x_fx[chInIdx][subFrameIdx][binIdx], eqGain_fx ), 1 );
1383 2240 : move32();
1384 : }
1385 : }
1386 : ELSE
1387 : {
1388 : /* TCX5*/
1389 91 : start_tcx5 = stop_tcx5;
1390 91 : move16();
1391 91 : stop_tcx5 = shr( add( stop, 1 ), 1 );
1392 1211 : FOR( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
1393 : {
1394 1120 : x_fx[chInIdx][subFrameIdx][binIdx] = L_shl( Mult_32_32( x_fx[chInIdx][subFrameIdx][binIdx], eqGain_fx ), 1 );
1395 1120 : move32();
1396 : }
1397 :
1398 1211 : FOR( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
1399 : {
1400 1120 : x_fx[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )] = L_shl( Mult_32_32( x_fx[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )], eqGain_fx ), 1 );
1401 1120 : move32();
1402 : }
1403 : }
1404 : }
1405 : }
1406 : }
1407 : }
1408 : }
1409 20 : return;
1410 : }
1411 :
1412 :
1413 : /*-------------------------------------------------------------------------
1414 : * ivas_ls_setup_conversion_process_param_mc()
1415 : *
1416 : * LS setup conversion in the CLDFB domain for Parametric MC
1417 : *-------------------------------------------------------------------------*/
1418 :
1419 1360 : void ivas_lssetupconversion_process_param_mc_fx(
1420 : Decoder_Struct *st_ivas, /* i/o: LS setup conversion renderer handle */
1421 : const Word16 num_timeslots,
1422 : Word32 Cldfb_RealBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals Q6*/
1423 : Word32 Cldfb_ImagBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals Q6*/
1424 : Word16 channel_active[MAX_CICP_CHANNELS] /* i : bitmap indicating which output channels are active */
1425 : )
1426 : {
1427 : Word16 slotIdx, chOutIdx, chInIdx, bandIdx;
1428 : Word16 inChannels, outChannels;
1429 : Word32 targetEnergy[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1430 : Word32 dmxEnergy[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1431 : Word32 tmpDMXSig, dmxCoeff, tmpReal, tmpImag;
1432 : Word32 EQ;
1433 : Word32 Cldfb_RealBuffer_tmp[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1434 : Word32 Cldfb_ImagBuffer_tmp[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1435 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
1436 : Word16 i, k;
1437 :
1438 1360 : push_wmops( "LS_Renderer_Process_Param_MC" );
1439 : /* inits */
1440 1360 : inChannels = add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe );
1441 1360 : move16();
1442 1360 : outChannels = add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe );
1443 1360 : move16();
1444 :
1445 1360 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
1446 1360 : EQ = 0;
1447 1360 : move32();
1448 :
1449 1360 : set16_fx( channel_active, 0, outChannels );
1450 :
1451 : /* Loop over each time slots and compute dmx for each time slot */
1452 6800 : FOR( slotIdx = 0; slotIdx < num_timeslots; slotIdx++ )
1453 : {
1454 : // Scale the array
1455 5440 : Word16 q_output = 31;
1456 38080 : FOR( i = 0; i < inChannels; ++i )
1457 : {
1458 32640 : q_output = s_min( q_output, L_norm_arr( Cldfb_RealBuffer_InOut[i][slotIdx], hLsSetUpConversion->sfbCnt ) );
1459 32640 : q_output = s_min( q_output, L_norm_arr( Cldfb_ImagBuffer_InOut[i][slotIdx], hLsSetUpConversion->sfbCnt ) );
1460 : }
1461 :
1462 5440 : Word16 guard_1 = find_guarded_bits_fx( inChannels );
1463 5440 : q_output = sub( q_output, guard_1 );
1464 :
1465 38080 : FOR( i = 0; i < inChannels; ++i )
1466 : {
1467 1991040 : FOR( k = 0; k < hLsSetUpConversion->sfbCnt; ++k )
1468 : {
1469 1958400 : Cldfb_RealBuffer_InOut[i][slotIdx][k] = L_shl( Cldfb_RealBuffer_InOut[i][slotIdx][k], q_output ); // Q(6 + q_output)
1470 1958400 : Cldfb_ImagBuffer_InOut[i][slotIdx][k] = L_shl( Cldfb_ImagBuffer_InOut[i][slotIdx][k], q_output ); // Q(6 + q_output)
1471 : }
1472 : }
1473 : /* copy buffers */
1474 38080 : FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
1475 : {
1476 32640 : Copy32( Cldfb_RealBuffer_InOut[chInIdx][slotIdx], Cldfb_RealBuffer_tmp[chInIdx], CLDFB_NO_CHANNELS_MAX ); // Q(6 + q_output)
1477 32640 : Copy32( Cldfb_ImagBuffer_InOut[chInIdx][slotIdx], Cldfb_ImagBuffer_tmp[chInIdx], CLDFB_NO_CHANNELS_MAX ); // Q(6 + q_output)
1478 : }
1479 : /* set the buffers to zero */
1480 70720 : FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1481 : {
1482 65280 : set32_fx( Cldfb_RealBuffer_InOut[chOutIdx][slotIdx], 0, CLDFB_NO_CHANNELS_MAX );
1483 65280 : set32_fx( Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx], 0, CLDFB_NO_CHANNELS_MAX );
1484 :
1485 65280 : set32_fx( dmxEnergy[chOutIdx], 0, CLDFB_NO_CHANNELS_MAX );
1486 65280 : set32_fx( targetEnergy[chOutIdx], 0, CLDFB_NO_CHANNELS_MAX );
1487 : }
1488 :
1489 : /* Compute the target energy and DMX signal */
1490 70720 : FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1491 : {
1492 456960 : FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
1493 : {
1494 391680 : dmxCoeff = hLsSetUpConversion->dmxMtx_fx[chInIdx][chOutIdx]; // Q30
1495 391680 : move32();
1496 391680 : IF( dmxCoeff == 0 )
1497 : {
1498 359040 : CONTINUE;
1499 : }
1500 : ELSE
1501 : {
1502 32640 : channel_active[chOutIdx] = s_or( 1, channel_active[chOutIdx] );
1503 32640 : move16();
1504 1991040 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1505 : {
1506 1958400 : tmpDMXSig = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), Cldfb_RealBuffer_tmp[chInIdx][bandIdx] ); // Q(6 + q_output)
1507 1958400 : Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx] = L_add( Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx], tmpDMXSig );
1508 1958400 : move32();
1509 1958400 : targetEnergy[chOutIdx][bandIdx] = L_add( targetEnergy[chOutIdx][bandIdx], Mpy_32_32( tmpDMXSig, tmpDMXSig ) ); // Q((6 + q_output)*2 - 31)
1510 1958400 : move32();
1511 :
1512 1958400 : tmpDMXSig = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), Cldfb_ImagBuffer_tmp[chInIdx][bandIdx] );
1513 1958400 : Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx] = L_add( Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx], tmpDMXSig );
1514 1958400 : move32();
1515 1958400 : targetEnergy[chOutIdx][bandIdx] = L_add( targetEnergy[chOutIdx][bandIdx], Mpy_32_32( tmpDMXSig, tmpDMXSig ) );
1516 1958400 : move32();
1517 : }
1518 : }
1519 : }
1520 : }
1521 :
1522 : /* Compute the DMX energy */
1523 70720 : FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1524 : {
1525 65280 : IF( channel_active[chOutIdx] )
1526 : {
1527 1991040 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1528 : {
1529 1958400 : tmpReal = Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx]; // Q(6 + q_output)
1530 1958400 : move32();
1531 1958400 : tmpImag = Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx]; // Q(6 + q_output)
1532 1958400 : move32();
1533 :
1534 1958400 : dmxEnergy[chOutIdx][bandIdx] = L_add( Mpy_32_32( tmpReal, tmpReal ), Mpy_32_32( tmpImag, tmpImag ) ); // Q((6 + q_output)*2 - 31)
1535 1958400 : move32();
1536 : }
1537 : }
1538 : }
1539 :
1540 : /* Peform energy smoothing */
1541 70720 : FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1542 : {
1543 65280 : IF( channel_active[chOutIdx] )
1544 : {
1545 32640 : Word16 te_scale = getScaleFactor32( hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt );
1546 32640 : scale_sig32( hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt, te_scale );
1547 32640 : Word16 dmx_sacle = getScaleFactor32( hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt );
1548 32640 : scale_sig32( hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt, dmx_sacle );
1549 :
1550 32640 : Word16 te_max_e = s_max( sub( 50, shl( q_output, 1 ) ), sub( hLsSetUpConversion->te_prev_exp[chOutIdx], te_scale ) );
1551 32640 : Word16 dmx_max_e = s_max( sub( 50, shl( q_output, 1 ) ), sub( hLsSetUpConversion->dmx_prev_exp[chOutIdx], dmx_sacle ) );
1552 :
1553 1991040 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1554 : {
1555 1958400 : targetEnergy[chOutIdx][bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( targetEnergy[chOutIdx][bandIdx], sub( te_max_e, sub( 50, shl( q_output, 1 ) ) ) ) ), Mpy_32_32( L_sub( ONE_IN_Q31, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx][bandIdx], sub( te_max_e, sub( hLsSetUpConversion->te_prev_exp[chOutIdx], te_scale ) ) ) ) );
1556 1958400 : move32();
1557 1958400 : dmxEnergy[chOutIdx][bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( dmxEnergy[chOutIdx][bandIdx], sub( dmx_max_e, sub( 50, shl( q_output, 1 ) ) ) ) ), Mpy_32_32( L_sub( ONE_IN_Q31, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx][bandIdx], sub( dmx_max_e, sub( hLsSetUpConversion->dmx_prev_exp[chOutIdx], dmx_sacle ) ) ) ) );
1558 1958400 : move32();
1559 1958400 : hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx][bandIdx] = targetEnergy[chOutIdx][bandIdx]; // Q0
1560 1958400 : move32();
1561 1958400 : hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx][bandIdx] = dmxEnergy[chOutIdx][bandIdx]; // Q0
1562 1958400 : move32();
1563 : }
1564 :
1565 32640 : hLsSetUpConversion->te_prev_exp[chOutIdx] = te_max_e; /* te_prev_exp = 50 - 2*q_output */
1566 32640 : move16();
1567 32640 : hLsSetUpConversion->dmx_prev_exp[chOutIdx] = dmx_max_e; /* dmx_prev_exp = 50 - 2*q_output */
1568 32640 : move16();
1569 : }
1570 : }
1571 :
1572 70720 : FOR( i = 0; i < outChannels; ++i )
1573 : {
1574 3982080 : FOR( k = 0; k < hLsSetUpConversion->sfbCnt; ++k )
1575 : {
1576 3916800 : Cldfb_RealBuffer_InOut[i][slotIdx][k] = L_shr( Cldfb_RealBuffer_InOut[i][slotIdx][k], q_output ); // Q6
1577 3916800 : move32();
1578 3916800 : Cldfb_ImagBuffer_InOut[i][slotIdx][k] = L_shr( Cldfb_ImagBuffer_InOut[i][slotIdx][k], q_output ); // Q6
1579 3916800 : move32();
1580 : }
1581 : }
1582 :
1583 : /* Compute and perform equalization */
1584 70720 : FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1585 : {
1586 65280 : IF( channel_active[chOutIdx] )
1587 : {
1588 1991040 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1589 : {
1590 1958400 : ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[chOutIdx][bandIdx], hLsSetUpConversion->te_prev_exp[chOutIdx], &dmxEnergy[chOutIdx][bandIdx], hLsSetUpConversion->dmx_prev_exp[chOutIdx], &EQ ); // Q(EQ) = Q30
1591 1958400 : Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx] = Mpy_32_32( L_shl( Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx], 1 ), EQ );
1592 1958400 : move32();
1593 1958400 : Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx] = Mpy_32_32( L_shl( Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx], 1 ), EQ );
1594 1958400 : move32();
1595 : }
1596 : }
1597 : }
1598 : }
1599 :
1600 1360 : pop_wmops();
1601 1360 : return;
1602 : }
|