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 870908 : *EQ = ONE_IN_Q30; // Q30
71 870908 : move32();
72 870908 : return;
73 : }
74 : /* Compute the Equalization Gain */
75 : Word16 tmp_e;
76 2766537 : Word16 tmp = BASOP_Util_Divide3232_Scale( *outputEnergy, L_add( EPSILON_FX, *inputEnergy ), &tmp_e );
77 2766537 : tmp_e = add( tmp_e, sub( output_exp, input_exp ) );
78 2766537 : Word32 tmp_32 = L_deposit_h( tmp );
79 2766537 : tmp_32 = Sqrt32( tmp_32, &tmp_e );
80 2766537 : *EQ = L_shr_sat( tmp_32, sub( 1, tmp_e ) ); // range of EQ in float 0.3 - 2.0
81 2766537 : move32();
82 :
83 2766537 : *EQ = L_min( *EQ, LS_OUT_CONV_CLIP_FACTOR_MAX_Q30 );
84 2766537 : *EQ = L_max( *EQ, LS_OUT_CONV_CLIP_FACTOR_MIN_Q30 );
85 2766537 : move32();
86 2766537 : move32();
87 :
88 2766537 : 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 : ivas_error error;
385 :
386 126 : test();
387 126 : test();
388 126 : test();
389 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 ) ) )
390 : {
391 1 : paramUpmixMonoStereo = TRUE;
392 1 : move16();
393 : }
394 : ELSE
395 : {
396 125 : paramUpmixMonoStereo = FALSE;
397 125 : move16();
398 : }
399 126 : output_Fs = st_ivas->hDecoderConfig->output_Fs;
400 126 : move32();
401 126 : outChannels = st_ivas->hDecoderConfig->nchan_out;
402 126 : move16();
403 126 : output_frame = (Word16) ( output_Fs / FRAMES_PER_SEC );
404 :
405 : /* Allocate memory to the handle */
406 126 : IF( ( hLsSetUpConversion = (LSSETUP_CONVERSION_HANDLE) malloc( sizeof( LSSETUP_CONVERSION_STRUCT ) ) ) == NULL )
407 : {
408 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
409 : }
410 :
411 126 : assert( LE_16( outChannels, MAX_OUTPUT_CHANNELS ) );
412 :
413 126 : IF( EQ_32( st_ivas->renderer_type, RENDERER_MC_PARAMMC ) )
414 : {
415 57 : inChannels = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe );
416 57 : hLsSetUpConversion->sfbCnt = (Word16) ( L_add( output_Fs, 400 ) / CLDFB_BANDWIDTH );
417 715 : FOR( chIdx = 0; chIdx < outChannels; chIdx++ )
418 : {
419 658 : IF( ( hLsSetUpConversion->targetEnergyPrev_fx[chIdx] = (Word32 *) malloc( hLsSetUpConversion->sfbCnt * sizeof( Word32 ) ) ) == NULL )
420 : {
421 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
422 : }
423 658 : IF( ( hLsSetUpConversion->dmxEnergyPrev_fx[chIdx] = (Word32 *) malloc( hLsSetUpConversion->sfbCnt * sizeof( Word32 ) ) ) == NULL )
424 : {
425 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
426 : }
427 658 : set32_fx( hLsSetUpConversion->targetEnergyPrev_fx[chIdx], 0, hLsSetUpConversion->sfbCnt );
428 658 : hLsSetUpConversion->te_prev_exp[chIdx] = 0;
429 658 : move16();
430 658 : set32_fx( hLsSetUpConversion->dmxEnergyPrev_fx[chIdx], 0, hLsSetUpConversion->sfbCnt );
431 658 : hLsSetUpConversion->dmx_prev_exp[chIdx] = 0;
432 658 : move16();
433 : }
434 311 : FOR( ; chIdx < MAX_CICP_CHANNELS; chIdx++ )
435 : {
436 254 : hLsSetUpConversion->targetEnergyPrev_fx[chIdx] = NULL;
437 254 : hLsSetUpConversion->dmxEnergyPrev_fx[chIdx] = NULL;
438 : }
439 : }
440 : ELSE
441 : {
442 69 : test();
443 69 : IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) )
444 : {
445 1 : IF( EQ_16( paramUpmixMonoStereo, TRUE ) )
446 : {
447 1 : inChannels = audioCfg2channels( IVAS_AUDIO_CONFIG_5_1_2 );
448 : }
449 : ELSE
450 : {
451 0 : inChannels = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe );
452 : }
453 : }
454 : ELSE
455 : {
456 68 : inChannels = st_ivas->nchan_transport;
457 68 : move16();
458 : }
459 :
460 : /*Initialization of MDCT bands with TCX20 resolution */
461 69 : ivas_lssetupconversion_mdct_init_bands_fx( output_frame, TCX_20_CORE, &hLsSetUpConversion->sfbOffset[0], &hLsSetUpConversion->sfbCnt );
462 69 : IF( ( hLsSetUpConversion->targetEnergyPrev_fx[0] = (Word32 *) malloc( ( MAX_SFB + 2 ) * sizeof( Word32 ) ) ) == NULL )
463 : {
464 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
465 : }
466 69 : IF( ( hLsSetUpConversion->dmxEnergyPrev_fx[0] = (Word32 *) malloc( ( MAX_SFB + 2 ) * sizeof( Word32 ) ) ) == NULL )
467 : {
468 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
469 : }
470 :
471 1104 : FOR( chIdx = 1; chIdx < MAX_CICP_CHANNELS; chIdx++ )
472 : {
473 1035 : hLsSetUpConversion->targetEnergyPrev_fx[chIdx] = NULL;
474 1035 : hLsSetUpConversion->dmxEnergyPrev_fx[chIdx] = NULL;
475 : }
476 69 : set32_fx( hLsSetUpConversion->targetEnergyPrev_fx[0], 0, MAX_SFB + 2 );
477 69 : set32_fx( hLsSetUpConversion->dmxEnergyPrev_fx[0], 0, MAX_SFB + 2 );
478 :
479 69 : hLsSetUpConversion->te_prev_exp[0] = 0;
480 69 : hLsSetUpConversion->dmx_prev_exp[0] = 0;
481 69 : move16();
482 69 : move16();
483 : }
484 :
485 : /* Initialize the DMX conversion matrix */
486 910 : FOR( chIdx = 0; chIdx < inChannels; chIdx++ )
487 : {
488 : /* Allocate memory depending on the number of output channels */
489 784 : IF( ( hLsSetUpConversion->dmxMtx_fx[chIdx] = (Word32 *) malloc( outChannels * sizeof( Word32 ) ) ) == NULL )
490 : {
491 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for temp dmx matrix \n" ) );
492 : }
493 784 : set32_fx( hLsSetUpConversion->dmxMtx_fx[chIdx], 0, outChannels );
494 : }
495 :
496 1358 : FOR( ; chIdx < MAX_CICP_CHANNELS; chIdx++ )
497 : {
498 1232 : hLsSetUpConversion->dmxMtx_fx[chIdx] = NULL;
499 : }
500 :
501 126 : IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
502 : {
503 1 : get_custom_ls_conversion_matrix_fx( st_ivas->hEFAPdata, st_ivas->hTransSetup, st_ivas->hLsSetupCustom, hLsSetUpConversion );
504 : }
505 : ELSE
506 : {
507 125 : IF( NE_32( st_ivas->transport_config, IVAS_AUDIO_CONFIG_INVALID ) )
508 : {
509 125 : IF( EQ_16( paramUpmixMonoStereo, TRUE ) )
510 : {
511 1 : IF( ( error = get_ls_conversion_matrix_fx( hLsSetUpConversion, IVAS_AUDIO_CONFIG_5_1_2, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
512 : {
513 0 : return error;
514 : }
515 : }
516 : ELSE
517 : {
518 124 : IF( ( error = get_ls_conversion_matrix_fx( hLsSetUpConversion, st_ivas->transport_config, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
519 : {
520 0 : return error;
521 : }
522 : }
523 : }
524 : ELSE
525 : {
526 0 : IF( ( error = get_ls_conversion_matrix_fx( hLsSetUpConversion, st_ivas->intern_config, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
527 : {
528 0 : return error;
529 : }
530 : }
531 : }
532 :
533 126 : st_ivas->hLsSetUpConversion = hLsSetUpConversion;
534 :
535 126 : return IVAS_ERR_OK;
536 : }
537 :
538 : /*-------------------------------------------------------------------------
539 : * ivas_ls_setup_conversion_close()
540 : *
541 : * Close the LS configuration Conversion Module
542 : *-------------------------------------------------------------------------*/
543 :
544 870 : void ivas_ls_setup_conversion_close_fx(
545 : LSSETUP_CONVERSION_HANDLE *hLsSetUpConversion /* i/o: LS converter handle */
546 : )
547 : {
548 : Word16 idx;
549 870 : test();
550 870 : IF( hLsSetUpConversion == NULL || *hLsSetUpConversion == NULL )
551 : {
552 744 : return;
553 : }
554 :
555 2142 : FOR( idx = 0; idx < MAX_CICP_CHANNELS; idx++ )
556 : {
557 2016 : IF( ( *hLsSetUpConversion )->dmxMtx_fx[idx] != NULL )
558 : {
559 784 : free( ( *hLsSetUpConversion )->dmxMtx_fx[idx] );
560 784 : ( *hLsSetUpConversion )->dmxMtx_fx[idx] = NULL;
561 : }
562 :
563 2016 : IF( ( *hLsSetUpConversion )->targetEnergyPrev_fx[idx] != NULL )
564 : {
565 727 : free( ( *hLsSetUpConversion )->targetEnergyPrev_fx[idx] );
566 727 : ( *hLsSetUpConversion )->targetEnergyPrev_fx[idx] = NULL;
567 : }
568 :
569 2016 : IF( ( *hLsSetUpConversion )->dmxEnergyPrev_fx[idx] != NULL )
570 : {
571 727 : free( ( *hLsSetUpConversion )->dmxEnergyPrev_fx[idx] );
572 727 : ( *hLsSetUpConversion )->dmxEnergyPrev_fx[idx] = NULL;
573 : }
574 : }
575 :
576 126 : free( *hLsSetUpConversion );
577 126 : *hLsSetUpConversion = NULL;
578 :
579 126 : return;
580 : }
581 :
582 : /*-------------------------------------------------------------------------
583 : * ivas_ls_setup_conversion()
584 : *
585 : * Convert (downmix or upmix) the input LS configuration
586 : * to output LS configuration in time domain
587 : *-------------------------------------------------------------------------*/
588 :
589 7457 : void ivas_ls_setup_conversion_fx(
590 : Decoder_Struct *st_ivas, /* i : IVAS decoder structure */
591 : const Word16 input_chans, /* i : number of input channels to the renderer */
592 : const Word16 output_frame, /* i : frame length */
593 : Word32 *input[], /* i : LS input/output synthesis signal Qx*/
594 : Word32 *output[] /* i/o: LS input/output synthesis signal Qx*/
595 : )
596 : {
597 : Word16 chInIdx, chOutIdx, idx;
598 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
599 : Word32 dmxCoeff, tmpVal;
600 : Word32 output_tmp[MAX_OUTPUT_CHANNELS][L_FRAME48k]; // Qx
601 :
602 7457 : push_wmops( "LS_Renderer" );
603 :
604 7457 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
605 :
606 69341 : FOR( chOutIdx = 0; chOutIdx < st_ivas->hDecoderConfig->nchan_out; chOutIdx++ )
607 : {
608 61884 : set32_fx( output_tmp[chOutIdx], 0, output_frame );
609 433468 : FOR( chInIdx = 0; chInIdx < input_chans; chInIdx++ )
610 : {
611 371584 : dmxCoeff = hLsSetUpConversion->dmxMtx_fx[chInIdx][chOutIdx];
612 371584 : move32();
613 :
614 371584 : IF( dmxCoeff == 0 )
615 : {
616 305602 : CONTINUE;
617 : }
618 65982 : ELSE IF( EQ_32( dmxCoeff, ONE_IN_Q30 ) )
619 : {
620 21981902 : FOR( idx = 0; idx < output_frame; idx++ )
621 : {
622 21953400 : output_tmp[chOutIdx][idx] = L_add( output_tmp[chOutIdx][idx], input[chInIdx][idx] );
623 21953400 : move32();
624 : }
625 : }
626 : ELSE
627 : {
628 35864680 : FOR( idx = 0; idx < output_frame; idx++ )
629 : {
630 35827200 : tmpVal = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), input[chInIdx][idx] );
631 35827200 : output_tmp[chOutIdx][idx] = L_add( output_tmp[chOutIdx][idx], tmpVal );
632 35827200 : move32();
633 : }
634 : }
635 : }
636 : }
637 :
638 : /* Copy to output buffer */
639 69341 : FOR( chOutIdx = 0; chOutIdx < st_ivas->hDecoderConfig->nchan_out; chOutIdx++ )
640 : {
641 61884 : Copy32( output_tmp[chOutIdx], output[chOutIdx], output_frame );
642 : }
643 :
644 7457 : pop_wmops();
645 :
646 7457 : return;
647 : }
648 :
649 : /*-------------------------------------------------------------------------
650 : * ivas_ls_setup_conversion_process_mdct()
651 : *
652 : * Equalization in MDCT Domain
653 : *-------------------------------------------------------------------------*/
654 :
655 6504 : void ivas_ls_setup_conversion_process_mdct_fx(
656 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
657 : Word32 *output[] /* i/o: output synthesis signal */
658 : )
659 : {
660 : /* Declaration of all required variables */
661 : Word16 i, bandIdx, chInIdx, chOutIdx, cpe_idx, subFrameIdx, binIdx, idx, j;
662 : Word16 inChannels, outChannels, num_CPE;
663 : Word16 transform_type[MAX_CICP_CHANNELS][2];
664 : Word16 frameSize;
665 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
666 : Word64 targetEnergy64[MAX_SFB + 2], dmxEnergy64[MAX_SFB + 2];
667 : Word16 scf1, scf2;
668 : #else
669 : Word32 targetEnergy[MAX_SFB + 2], dmxEnergy[MAX_SFB + 2];
670 : Word16 dmxEnergy_exp[MAX_SFB + 2], dmxEnergy_exp_temp;
671 : #endif
672 : Word32 dmxCoeff;
673 : Word32 dmxSignalReal[L_FRAME48k], dmxSignalImag[L_FRAME48k];
674 : Word32 eqGain;
675 : Word32 *sig[NB_DIV], *pTmp[NB_DIV], *x[MAX_CICP_CHANNELS][NB_DIV];
676 : Word32 mdst[L_FRAME48k];
677 : Word32 convertRes[L_FRAME48k];
678 : Word16 start, stop, start_tcx5, stop_tcx5;
679 : Word16 mct_chan_mode[MAX_CICP_CHANNELS];
680 :
681 : /* Declare all handles */
682 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
683 : CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS];
684 :
685 6504 : push_wmops( "LS_Renderer_MDCT" );
686 :
687 : /* Assign all the declared variables */
688 6504 : inChannels = st_ivas->nchan_transport;
689 6504 : move16();
690 6504 : outChannels = st_ivas->hDecoderConfig->nchan_out;
691 6504 : move16();
692 6504 : num_CPE = st_ivas->nCPE;
693 6504 : move16();
694 :
695 : /* Assign output pointer to variable x */
696 :
697 : // Scale the array
698 6504 : Word16 q_output = 31;
699 6504 : move16();
700 45728 : FOR( i = 0; i < inChannels; ++i )
701 : {
702 39224 : q_output = s_min( q_output, L_norm_arr( output[i], L_FRAME48k ) );
703 : }
704 :
705 6504 : Word16 tmp_sub = sub( st_ivas->hLsSetUpConversion->sfbOffset[st_ivas->hLsSetUpConversion->sfbCnt], st_ivas->hLsSetUpConversion->sfbOffset[st_ivas->hLsSetUpConversion->sfbCnt - 1] );
706 6504 : Word16 guard_1 = shr( add( find_guarded_bits_fx( tmp_sub ), 1 ), 1 );
707 6504 : Word16 guard_2 = find_guarded_bits_fx( L_mult0( outChannels, inChannels ) );
708 6504 : q_output = sub( q_output, s_max( guard_1, guard_2 ) );
709 : /* Increase the guard bit by 1 to avoid overflow only if q_output is positive */
710 6504 : if ( q_output > 0 )
711 : {
712 4727 : q_output = sub( q_output, 1 );
713 : }
714 :
715 45728 : FOR( i = 0; i < inChannels; ++i )
716 : {
717 37694264 : FOR( j = 0; j < L_FRAME48k; ++j )
718 : {
719 37655040 : output[i][j] = L_shl( output[i][j], q_output );
720 : }
721 : }
722 :
723 45728 : FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
724 : {
725 39224 : x[chInIdx][0] = output[chInIdx]; // Q(q_output)
726 39224 : x[chInIdx][1] = output[chInIdx] + L_FRAME48k / 2; // Q(q_output)
727 : }
728 :
729 : /* Assign all the declared handles*/
730 6504 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
731 26116 : FOR( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
732 : {
733 19612 : hCPE[cpe_idx] = st_ivas->hCPE[cpe_idx];
734 : }
735 :
736 : /* Get the core type */
737 26116 : FOR( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
738 : {
739 58836 : FOR( idx = 0; idx < CPE_CHANNELS; idx++ )
740 : {
741 : /* get the channel index */
742 39224 : chInIdx = add( imult1616( cpe_idx, CPE_CHANNELS ), idx );
743 39224 : assert( LE_16( chInIdx, inChannels ) );
744 39224 : transform_type[chInIdx][0] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[0];
745 39224 : move16();
746 39224 : transform_type[chInIdx][1] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[1];
747 39224 : move16();
748 39224 : mct_chan_mode[chInIdx] = hCPE[cpe_idx]->hCoreCoder[idx]->mct_chan_mode;
749 39224 : move16();
750 : }
751 : }
752 :
753 : /* set overall frequency resolution of (sub)frame to maximum of (sub)frame, requires conversion if both channels are not the same */
754 6504 : frameSize = hLsSetUpConversion->sfbOffset[hLsSetUpConversion->sfbCnt];
755 6504 : move16();
756 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
757 6504 : set64_fx( targetEnergy64, 0, MAX_SFB + 2 );
758 6504 : set64_fx( dmxEnergy64, 0, MAX_SFB + 2 );
759 6504 : scf1 = 63;
760 6504 : scf2 = 63;
761 6504 : move16();
762 6504 : move16();
763 : #else
764 : set32_fx( targetEnergy, 0, MAX_SFB + 2 );
765 : set32_fx( dmxEnergy, 0, MAX_SFB + 2 );
766 : set16_fx( dmxEnergy_exp, 0, MAX_SFB + 2 );
767 : dmxEnergy_exp_temp = 0;
768 : move16();
769 : #endif
770 :
771 57152 : FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
772 : {
773 : /* Step 0: Set the buffers to zero */
774 50648 : set32_fx( dmxSignalReal, 0, frameSize );
775 50648 : set32_fx( dmxSignalImag, 0, frameSize );
776 :
777 354936 : FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
778 : {
779 304288 : dmxCoeff = hLsSetUpConversion->dmxMtx_fx[chInIdx][chOutIdx]; // Q30
780 304288 : move32();
781 :
782 304288 : test();
783 304288 : IF( NE_16( chInIdx, LFE_CHANNEL ) && NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
784 : {
785 : /* Step 1: Compute the target energy and DMX signal (possible since we have all signals in TCX20 resolution) */
786 199937 : IF( dmxCoeff )
787 : {
788 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
789 : Word64 targetEne64;
790 : Word32 tmpDMXSig;
791 : #else
792 : Word32 tmpDMXSig, targetEne;
793 : #endif
794 : /* Convert the signal resolution to TCX20 */
795 : /* initially, set pointers to input; if conversion occurs in (sub)frame, set to convertRes */
796 28824 : pTmp[0] = x[chInIdx][0]; // Q(q_output)
797 28824 : sig[0] = pTmp[0];
798 28824 : pTmp[1] = x[chInIdx][1];
799 28824 : sig[1] = pTmp[1]; // Q(q_output)
800 :
801 : /* convert (sub)frames to higher frequency resolution */
802 28824 : IF( NE_16( transform_type[chInIdx][0], TCX_20 ) )
803 : {
804 1521 : FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
805 : {
806 1014 : IF( EQ_16( transform_type[chInIdx][subFrameIdx], TCX_5 ) )
807 : {
808 : /* subframe is TCX5, but TCX10 or TCX20 in other channel -> convert channel with TCX5 to TCX10 resolution */
809 536 : sig[subFrameIdx] = convertRes + L_shr( L_mult0( subFrameIdx, frameSize ), 1 );
810 536 : pTmp[subFrameIdx] = sig[subFrameIdx];
811 536 : convert_coeffs_to_higher_res_fx( x[chInIdx][subFrameIdx], x[chInIdx][subFrameIdx] + shr( frameSize, 2 ), pTmp[subFrameIdx], shr( frameSize, 2 ) );
812 : }
813 : }
814 :
815 : /* convert channel with TCX10 to TCX20 resolution */
816 507 : sig[0] = convertRes;
817 507 : convert_coeffs_to_higher_res_fx( pTmp[0], pTmp[1], sig[0], frameSize / 2 );
818 : }
819 :
820 : /* MDST estimate */
821 28824 : mdst[0] = mdst[frameSize - 1] = 0;
822 28824 : move32();
823 28824 : move32();
824 27514216 : FOR( i = 1; i < frameSize - 1; i++ )
825 : {
826 27485392 : mdst[i] = L_sub( sig[0][i + 1], sig[0][i - 1] ); // Q(q_output)
827 : }
828 :
829 1901984 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
830 : {
831 1873160 : start = hLsSetUpConversion->sfbOffset[bandIdx];
832 1873160 : move16();
833 1873160 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
834 1873160 : move16();
835 :
836 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
837 1873160 : targetEne64 = 0;
838 1873160 : move64();
839 : #else
840 : targetEne = 0;
841 : move32();
842 : #endif
843 :
844 : /* Loop over all the bins in the band */
845 29416200 : FOR( binIdx = start; binIdx < stop; binIdx++ )
846 : {
847 27543040 : tmpDMXSig = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), sig[0][binIdx] );
848 27543040 : dmxSignalReal[binIdx] = L_add( dmxSignalReal[binIdx], tmpDMXSig );
849 27543040 : move32();
850 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
851 27543040 : targetEne64 = W_mac_32_32( targetEne64, tmpDMXSig, tmpDMXSig );
852 : #else
853 : targetEne = L_add( targetEne, Mpy_32_32( tmpDMXSig, tmpDMXSig ) );
854 : #endif
855 27543040 : tmpDMXSig = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), mdst[binIdx] );
856 27543040 : dmxSignalImag[binIdx] = L_add( dmxSignalImag[binIdx], tmpDMXSig );
857 27543040 : move32();
858 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
859 27543040 : targetEne64 = W_mac_32_32( targetEne64, tmpDMXSig, tmpDMXSig );
860 : #else
861 : targetEne = L_add( targetEne, Mpy_32_32( tmpDMXSig, tmpDMXSig ) );
862 : #endif
863 : }
864 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
865 1873160 : targetEnergy64[bandIdx] = W_add( targetEnergy64[bandIdx], W_shr( targetEne64, 1 ) );
866 1873160 : if ( NE_64( targetEnergy64[bandIdx], 0 ) )
867 : {
868 1863990 : scf1 = s_min( scf1, W_norm( targetEnergy64[bandIdx] ) );
869 : }
870 : #else
871 : targetEnergy[bandIdx] = L_add( targetEnergy[bandIdx], targetEne );
872 : move32();
873 : #endif
874 : } /* end of band loop */
875 : }
876 : }
877 : } /* end of chInIdx loop */
878 :
879 3342688 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
880 : {
881 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
882 : Word32 tmpReal, tmpImag;
883 : Word64 DMXEne64;
884 : #else
885 : Word32 tmpReal, tmpImag, DMXEne;
886 : Word16 DMXEne_exp;
887 : #endif
888 3292040 : start = hLsSetUpConversion->sfbOffset[bandIdx];
889 3292040 : move16();
890 3292040 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
891 3292040 : move16();
892 :
893 : /* Loop over all the bins in the band */
894 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
895 3292040 : DMXEne64 = 0;
896 3292040 : move64();
897 : #else
898 : DMXEne = 0;
899 : move32();
900 : DMXEne_exp = 0;
901 : move16();
902 : #endif
903 :
904 51888520 : FOR( binIdx = start; binIdx < stop; binIdx++ )
905 : {
906 48596480 : tmpReal = dmxSignalReal[binIdx];
907 48596480 : move32();
908 48596480 : tmpImag = dmxSignalImag[binIdx];
909 48596480 : move32();
910 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
911 48596480 : DMXEne64 = W_mac_32_32( DMXEne64, tmpReal, tmpReal );
912 48596480 : DMXEne64 = W_mac_32_32( DMXEne64, tmpImag, tmpImag );
913 : #else
914 : 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 );
915 : #endif
916 : }
917 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
918 3292040 : dmxEnergy64[bandIdx] = W_add( dmxEnergy64[bandIdx], W_shr( DMXEne64, 1 ) );
919 3292040 : if ( NE_64( dmxEnergy64[bandIdx], 0 ) )
920 : {
921 3234911 : scf2 = s_min( scf2, W_norm( dmxEnergy64[bandIdx] ) );
922 : }
923 : #else
924 : dmxEnergy[bandIdx] = BASOP_Util_Add_Mant32Exp( dmxEnergy[bandIdx], dmxEnergy_exp[bandIdx], DMXEne, DMXEne_exp, &dmxEnergy_exp[bandIdx] );
925 : move32();
926 : dmxEnergy_exp_temp = s_max( dmxEnergy_exp_temp, dmxEnergy_exp[bandIdx] );
927 : #endif
928 : }
929 : } /* end of out channel loop */
930 : #ifndef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
931 : /* Scaling to common exponent */
932 : FOR( bandIdx = 0; bandIdx < MAX_SFB + 2; bandIdx++ )
933 : {
934 : dmxEnergy[bandIdx] = L_shl( dmxEnergy[bandIdx], sub( dmxEnergy_exp[bandIdx], dmxEnergy_exp_temp ) );
935 : move32();
936 : }
937 : #endif
938 : /* Step 3: Peform energy smoothing */
939 6504 : Word16 te_scale = getScaleFactor32( hLsSetUpConversion->targetEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt );
940 6504 : scale_sig32( hLsSetUpConversion->targetEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt, te_scale );
941 :
942 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
943 6504 : Word16 dmx_scale = getScaleFactor32( hLsSetUpConversion->dmxEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt );
944 6504 : scale_sig32( hLsSetUpConversion->dmxEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt, dmx_scale );
945 :
946 6504 : Word16 targetEnergy_e = sub( add( sub( 40, shl( q_output, 1 ) ), 1 ), scf1 );
947 6504 : Word16 te_max_e = s_max( targetEnergy_e, sub( hLsSetUpConversion->te_prev_exp[0], te_scale ) );
948 :
949 6504 : Word16 dmxEnergy_e = sub( add( sub( 40, shl( q_output, 1 ) ), 1 ), scf2 );
950 6504 : Word16 dmx_max_e = s_max( dmxEnergy_e, sub( hLsSetUpConversion->dmx_prev_exp[0], dmx_scale ) );
951 : #else
952 : Word16 dmx_sacle = getScaleFactor32( hLsSetUpConversion->dmxEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt );
953 : scale_sig32( hLsSetUpConversion->dmxEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt, dmx_sacle );
954 :
955 : Word16 te_max_e = s_max( sub( 40, shl( q_output, 1 ) ), sub( hLsSetUpConversion->te_prev_exp[0], te_scale ) );
956 : Word16 dmx_max_e = s_max( dmxEnergy_exp_temp, sub( hLsSetUpConversion->dmx_prev_exp[0], dmx_sacle ) );
957 : #endif
958 :
959 429224 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
960 : {
961 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
962 : Word32 targetEnergy, dmxEnergy;
963 :
964 422720 : targetEnergy = W_extract_h( W_shl( targetEnergy64[bandIdx], scf1 ) );
965 422720 : targetEnergy = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( targetEnergy, sub( te_max_e, targetEnergy_e ) ) ), 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 ) ) ) ) );
966 422720 : move32();
967 422720 : hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx] = targetEnergy;
968 422720 : move32();
969 :
970 422720 : dmxEnergy = W_extract_h( W_shl( dmxEnergy64[bandIdx], scf2 ) );
971 422720 : dmxEnergy = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( dmxEnergy, sub( dmx_max_e, dmxEnergy_e ) ) ), 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_scale ) ) ) ) );
972 422720 : move32();
973 422720 : hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx] = dmxEnergy;
974 422720 : move32();
975 : #else
976 : 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 ) ) ) ) );
977 : move32();
978 : 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 ) ) ) ) );
979 : move32();
980 : hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx] = targetEnergy[bandIdx]; /* te_prev_exp = 40 - 2*q_output */
981 : move32();
982 : hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx] = dmxEnergy[bandIdx]; /* dmx_prev_exp = 40 - 2*q_output */
983 : move32();
984 : #endif
985 : }
986 :
987 6504 : hLsSetUpConversion->te_prev_exp[0] = te_max_e; /* te_prev_exp = 40 - 2*q_output */
988 6504 : move16();
989 6504 : hLsSetUpConversion->dmx_prev_exp[0] = dmx_max_e; /* dmx_prev_exp = 40 - 2*q_output */
990 6504 : move16();
991 :
992 45728 : FOR( i = 0; i < inChannels; ++i )
993 : {
994 37694264 : FOR( j = 0; j < L_FRAME48k; ++j )
995 : {
996 37655040 : output[i][j] = L_shr( output[i][j], q_output );
997 37655040 : move32();
998 : }
999 : }
1000 :
1001 : /* Step 4: Perform equalization */
1002 45728 : FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
1003 : {
1004 39224 : test();
1005 39224 : IF( NE_16( chInIdx, LFE_CHANNEL ) && NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
1006 : {
1007 25825 : IF( EQ_16( transform_type[chInIdx][0], TCX_20 ) )
1008 : {
1009 : /* TCX20 */
1010 1672376 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1011 : {
1012 1647032 : start = hLsSetUpConversion->sfbOffset[bandIdx];
1013 1647032 : move16();
1014 1647032 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
1015 1647032 : move16();
1016 :
1017 : /* Compute Eq gains */
1018 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
1019 1647032 : ivas_lssetupconversion_computeEQFactor_fx( &hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx], hLsSetUpConversion->te_prev_exp[0],
1020 1647032 : &hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx], hLsSetUpConversion->dmx_prev_exp[0],
1021 : &eqGain ); // Q(eqGain) = 30
1022 : #else
1023 : ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain ); // Q(eqGain) = 30
1024 : #endif
1025 25872312 : FOR( binIdx = start; binIdx < stop; binIdx++ )
1026 : {
1027 24225280 : x[chInIdx][0][binIdx] = Mpy_32_32( L_shl( x[chInIdx][0][binIdx], 1 ), eqGain ); // Q - 1
1028 24225280 : move32();
1029 : }
1030 : }
1031 : }
1032 : ELSE
1033 : {
1034 481 : stop_tcx5 = 0;
1035 481 : move16();
1036 31714 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1037 : {
1038 31233 : start = shr( hLsSetUpConversion->sfbOffset[bandIdx], 1 );
1039 31233 : move16();
1040 31233 : stop = shr( hLsSetUpConversion->sfbOffset[bandIdx + 1], 1 );
1041 31233 : move16();
1042 :
1043 : /* Compute Eq gains */
1044 : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
1045 31233 : ivas_lssetupconversion_computeEQFactor_fx( &hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx], hLsSetUpConversion->te_prev_exp[0],
1046 31233 : &hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx], hLsSetUpConversion->dmx_prev_exp[0],
1047 : &eqGain );
1048 : #else
1049 : ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain );
1050 : #endif
1051 93699 : FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
1052 : {
1053 62466 : IF( EQ_16( transform_type[chInIdx][subFrameIdx], TCX_10 ) )
1054 : {
1055 : /* TCX10 */
1056 242823 : FOR( binIdx = start; binIdx < stop; binIdx++ )
1057 : {
1058 213280 : x[chInIdx][subFrameIdx][binIdx] = Mpy_32_32( L_shl( x[chInIdx][subFrameIdx][binIdx], 1 ), eqGain );
1059 213280 : move32();
1060 : }
1061 : }
1062 : ELSE
1063 : {
1064 : /* TCX5*/
1065 32923 : start_tcx5 = stop_tcx5;
1066 32923 : move16();
1067 32923 : stop_tcx5 = shr( add( stop, 1 ), 1 );
1068 :
1069 145803 : FOR( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
1070 : {
1071 112880 : x[chInIdx][subFrameIdx][binIdx] = Mpy_32_32( L_shl( x[chInIdx][subFrameIdx][binIdx], 1 ), eqGain );
1072 112880 : move32();
1073 112880 : x[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )] = Mpy_32_32( L_shl( x[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )], 1 ), eqGain );
1074 112880 : move32();
1075 : }
1076 : }
1077 : }
1078 : }
1079 : }
1080 : }
1081 : }
1082 :
1083 6504 : pop_wmops();
1084 6504 : return;
1085 : }
1086 :
1087 :
1088 : /*-------------------------------------------------------------------------
1089 : * ivas_ls_setup_conversion_process_mdct_param_mc()
1090 : *
1091 : * Equalization in MDCT Domain
1092 : *-------------------------------------------------------------------------*/
1093 :
1094 20 : void ivas_ls_setup_conversion_process_mdct_param_mc_fx(
1095 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
1096 : Word32 *x_fx[][NB_DIV],
1097 : Word16 x_e[CPE_CHANNELS][NB_DIV] /* i/o: Exponent for output synthesis signal */
1098 : )
1099 : {
1100 : Word32 targetEnergy_fx[MAX_SFB + 2], dmxEnergy_fx[MAX_SFB + 2];
1101 : Word32 eqGain_fx;
1102 : Word32 *sig_fx[MAX_CICP_CHANNELS][NB_DIV], *pTmp_fx[NB_DIV];
1103 : Word32 mdst_fx[MAX_CICP_CHANNELS][L_FRAME48k];
1104 : Word32 convertRes_fx[MAX_CICP_CHANNELS][L_FRAME48k];
1105 : Word32 cx_fx[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
1106 : Word32 cx_imag_fx[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
1107 : Word32 cy_fx[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS];
1108 : Word32 real_in_buffer_fx[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS];
1109 : Word32 imag_in_buffer_fx[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS];
1110 : Word32 real_buffer_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
1111 : Word32 imag_buffer_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
1112 : Word32 Nrqq_fx[MAX_OUTPUT_CHANNELS];
1113 : Word32 target_ch_ener_fx[MAX_OUTPUT_CHANNELS];
1114 : Word16 *ild_q_fx;
1115 :
1116 : Word32 DMXEne_fx;
1117 : Word32 dmxCoeff_fx;
1118 : Word32 dmxSignalReal_fx[L_FRAME48k], dmxSignalImag_fx[L_FRAME48k];
1119 :
1120 : Word32 tmpReal_fx, tmpImag_fx;
1121 : Word32 tmpDMXSig_fx;
1122 :
1123 : /* Declaration of all required variables */
1124 : Word16 i;
1125 : Word16 idx;
1126 : Word16 nchan_transport, nchan_out, nchan_transport_format;
1127 : Word16 chInIdx, chOutIdx, cpe_idx, subFrameIdx, binIdx;
1128 : Word16 band, bandIdx, num_bands;
1129 :
1130 : Word16 num_CPE;
1131 : Word16 transform_type[MAX_CICP_CHANNELS][2];
1132 : Word16 frameSize;
1133 :
1134 : Word16 start, stop, start_tcx5, stop_tcx5;
1135 : Word16 mct_chan_mode[MAX_CICP_CHANNELS];
1136 : Word16 all_ch_ignored; // Flag for checking if all channels are ignored
1137 :
1138 : /* Declare all handles */
1139 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
1140 : CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS];
1141 : PARAM_MC_DEC_HANDLE hParamMC;
1142 :
1143 : /* Step 0: Set the buffers to zero */
1144 20 : set_zero_fx( dmxSignalReal_fx, L_FRAME48k );
1145 20 : set_zero_fx( dmxSignalImag_fx, L_FRAME48k );
1146 :
1147 : /* Assign all the declared variables */
1148 20 : nchan_transport = st_ivas->nchan_transport;
1149 20 : nchan_out = st_ivas->hDecoderConfig->nchan_out;
1150 20 : num_CPE = st_ivas->nCPE;
1151 20 : nchan_transport_format = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe );
1152 20 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
1153 : /* Assign all the declared handles*/
1154 60 : FOR( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
1155 : {
1156 40 : hCPE[cpe_idx] = st_ivas->hCPE[cpe_idx];
1157 : }
1158 20 : hParamMC = st_ivas->hParamMC;
1159 :
1160 : /* Get the core type */
1161 60 : FOR( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
1162 : {
1163 120 : FOR( idx = 0; idx < CPE_CHANNELS; idx++ )
1164 : {
1165 : /* get the channel index */
1166 80 : chInIdx = add( cpe_idx * CPE_CHANNELS, idx );
1167 80 : assert( chInIdx <= nchan_transport );
1168 80 : transform_type[chInIdx][0] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[0];
1169 80 : move16();
1170 80 : transform_type[chInIdx][1] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[1];
1171 80 : move16();
1172 80 : mct_chan_mode[chInIdx] = hCPE[cpe_idx]->hCoreCoder[idx]->mct_chan_mode;
1173 80 : move16();
1174 : }
1175 : }
1176 :
1177 : /* set overall frequency resolution of (sub)frame to maximum of (sub)frame, requires conversion if both channels are not the same */
1178 20 : frameSize = hLsSetUpConversion->sfbOffset[hLsSetUpConversion->sfbCnt];
1179 20 : move16();
1180 20 : set_zero_fx( targetEnergy_fx, MAX_SFB + 2 );
1181 20 : set_zero_fx( dmxEnergy_fx, MAX_SFB + 2 );
1182 :
1183 80 : FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
1184 : {
1185 60 : IF( NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
1186 : {
1187 : /* initially, set pointers to input; if conversion occurs in (sub)frame, set to convertRes */
1188 60 : sig_fx[chInIdx][0] = pTmp_fx[0] = x_fx[chInIdx][0]; /*Q=31-x_e[chInIdx][0]*/
1189 60 : sig_fx[chInIdx][1] = pTmp_fx[1] = x_fx[chInIdx][1]; /*Q=31-x_e[chInIdx][1]*/
1190 : /* convert (sub)frames to higher frequency resolution */
1191 60 : IF( NE_16( transform_type[chInIdx][0], TCX_20 ) )
1192 : {
1193 21 : FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
1194 : {
1195 14 : IF( EQ_16( transform_type[chInIdx][subFrameIdx], TCX_5 ) )
1196 : {
1197 : /* subframe is TCX5, but TCX10 or TCX20 in other channel -> convert channel with TCX5 to TCX10 resolution */
1198 7 : pTmp_fx[subFrameIdx] = sig_fx[chInIdx][subFrameIdx] = convertRes_fx[chInIdx] + L_mult0( subFrameIdx, frameSize ) / 2;
1199 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]*/
1200 : }
1201 : }
1202 :
1203 : /* convert channel with TCX10 to TCX20 resolution */
1204 7 : sig_fx[chInIdx][0] = convertRes_fx[chInIdx];
1205 :
1206 : // 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]*/
1207 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]*/
1208 : }
1209 : }
1210 : }
1211 20 : Word16 input_exp, output_exp = 0;
1212 20 : move16();
1213 :
1214 : /* precalculate MDST estimate */
1215 80 : FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
1216 : {
1217 60 : IF( NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
1218 : {
1219 60 : mdst_fx[chInIdx][0] = mdst_fx[chInIdx][frameSize - 1] = 0;
1220 60 : move32();
1221 38340 : FOR( i = 1; i < frameSize - 1; i++ )
1222 : {
1223 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]*/
1224 38280 : move32();
1225 : }
1226 : }
1227 : }
1228 :
1229 : /* Step 1.1, calculate Cx from MDST estimate */
1230 420 : FOR( bandIdx = 0; bandIdx < PARAM_MC_MAX_PARAMETER_BANDS; bandIdx++ )
1231 : {
1232 400 : set_zero_fx( cx_fx[bandIdx], PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
1233 400 : set_zero_fx( cx_imag_fx[bandIdx], PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
1234 : }
1235 20 : set_zero_fx( Nrqq_fx, MAX_OUTPUT_CHANNELS );
1236 20 : set_zero_fx( target_ch_ener_fx, MAX_OUTPUT_CHANNELS );
1237 20 : Word16 max_e = 0;
1238 20 : move16();
1239 20 : all_ch_ignored = 1;
1240 20 : move16();
1241 80 : FOR( idx = 0; idx < nchan_transport; idx++ )
1242 : {
1243 60 : IF( NE_16( mct_chan_mode[idx], MCT_CHAN_MODE_IGNORE ) )
1244 : {
1245 60 : max_e = s_max( max_e, x_e[idx][0] );
1246 60 : all_ch_ignored = 0;
1247 60 : move16();
1248 : }
1249 : }
1250 20 : if ( all_ch_ignored )
1251 : {
1252 0 : max_e = 31;
1253 0 : move16();
1254 : }
1255 280 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1256 : {
1257 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 );
1258 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 );
1259 260 : set_zero_fx( real_buffer_fx, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
1260 260 : set_zero_fx( imag_buffer_fx, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
1261 :
1262 260 : start = hLsSetUpConversion->sfbOffset[bandIdx];
1263 260 : move16();
1264 260 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
1265 260 : move16();
1266 260 : num_bands = sub( stop, start );
1267 :
1268 13060 : FOR( i = 0; i < num_bands; i++ )
1269 : {
1270 12800 : band = add( start, i );
1271 51200 : FOR( idx = 0; idx < nchan_transport; idx++ )
1272 : {
1273 38400 : IF( NE_16( mct_chan_mode[idx], MCT_CHAN_MODE_IGNORE ) )
1274 : {
1275 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*/
1276 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*/
1277 38400 : move32();
1278 38400 : move32();
1279 : }
1280 : }
1281 : }
1282 260 : input_exp = max_e;
1283 260 : move16();
1284 260 : IF( all_ch_ignored == 0 )
1285 : {
1286 260 : Word16 shift = 1;
1287 260 : move16();
1288 38660 : FOR( i = 0; i < num_bands * nchan_transport; ++i )
1289 : {
1290 38400 : real_in_buffer_fx[i] = L_shr( real_in_buffer_fx[i], shift );
1291 38400 : move32();
1292 38400 : imag_in_buffer_fx[i] = L_shr( imag_in_buffer_fx[i], shift );
1293 38400 : move32();
1294 : }
1295 260 : input_exp = add( input_exp, shift );
1296 : }
1297 :
1298 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 );
1299 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*/
1300 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*/
1301 : }
1302 20 : if ( all_ch_ignored )
1303 : {
1304 0 : output_exp = 29;
1305 0 : move16();
1306 : }
1307 :
1308 20 : Word16 exp_in = 10, exp_out = 0;
1309 20 : move16();
1310 20 : move16();
1311 280 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1312 : {
1313 260 : DMXEne_fx = 0;
1314 260 : move16();
1315 260 : set_zero_fx( cy_fx, MAX_CICP_CHANNELS * MAX_CICP_CHANNELS );
1316 260 : set_zero_fx( Nrqq_fx, MAX_OUTPUT_CHANNELS );
1317 260 : set_zero_fx( target_ch_ener_fx, MAX_OUTPUT_CHANNELS );
1318 : /* Step 1.2, get target channel energies for the transported format, Nrqq calculation */
1319 260 : ild_q_fx = hParamMC->icld_q_fx + imult1616( bandIdx, hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe );
1320 260 : move16();
1321 3380 : FOR( chInIdx = 0; chInIdx < nchan_transport_format; chInIdx++ )
1322 : {
1323 3120 : Word32 ref_ener_fx = 0;
1324 3120 : move32();
1325 : Word16 ref_channel_cnt;
1326 : Word16 ref_channel_idx;
1327 :
1328 6240 : FOR( ref_channel_cnt = 0; ref_channel_cnt < hParamMC->hMetadataPMC->ild_mapping_conf->num_ref_channels[chInIdx]; ref_channel_cnt++ )
1329 : {
1330 3120 : ref_channel_idx = hParamMC->hMetadataPMC->ild_mapping_conf->ref_channel_idx[chInIdx][ref_channel_cnt];
1331 3120 : move16();
1332 3120 : ref_ener_fx = L_add( ref_ener_fx, cx_fx[bandIdx][ref_channel_idx + ( ref_channel_idx * nchan_transport )] ); /*Exponent=output_exp*/
1333 : }
1334 : Word32 temp;
1335 3120 : temp = BASOP_util_Pow2( L_mult0( ild_q_fx[chInIdx], 2721 /*log2(10)*(2^13)/10*/ ), exp_in, &exp_out );
1336 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*/
1337 3120 : move32();
1338 : }
1339 :
1340 : /* Step 1.3 get target Cy () (with dmx matrix from CICPX to MONO/STEREO saved in hParamMC) */
1341 780 : FOR( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
1342 : {
1343 6760 : FOR( i = 0; i < nchan_transport_format; i++ )
1344 : {
1345 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*/
1346 6240 : move32();
1347 : }
1348 520 : cy_fx[chOutIdx + ( nchan_out * chOutIdx )] = target_ch_ener_fx[chOutIdx];
1349 520 : move32();
1350 : }
1351 :
1352 : /* Step 1.4 final target energy for the band would then be the sum over the diagonal of Cy*/
1353 780 : FOR( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
1354 : {
1355 520 : targetEnergy_fx[bandIdx] = L_add( targetEnergy_fx[bandIdx], cy_fx[chOutIdx + ( nchan_out * chOutIdx )] ); /*exp=output_exp+2*/
1356 520 : move32();
1357 : }
1358 :
1359 : /* Step 2: Calculate DMX ener */
1360 260 : start = hLsSetUpConversion->sfbOffset[bandIdx];
1361 260 : move16();
1362 260 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
1363 260 : move16();
1364 :
1365 780 : FOR( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
1366 : {
1367 2080 : FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
1368 : {
1369 1560 : IF( mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
1370 : {
1371 1560 : dmxCoeff_fx = hLsSetUpConversion->dmxMtx_fx[chInIdx][chOutIdx];
1372 :
1373 : /* Step 1: Compute the target energy and DMX signal (possible since we have all signals in TCX20 resolution) */
1374 1560 : IF( dmxCoeff_fx )
1375 : {
1376 : /* Loop over all the bins in the band */
1377 52240 : FOR( binIdx = start; binIdx < stop; binIdx++ )
1378 : {
1379 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*/
1380 51200 : dmxSignalReal_fx[binIdx] = L_add( dmxSignalReal_fx[binIdx], tmpDMXSig_fx );
1381 51200 : move32();
1382 :
1383 51200 : tmpDMXSig_fx = Mult_32_32( dmxCoeff_fx, L_shr( mdst_fx[chInIdx][binIdx], sub( max_e, x_e[chInIdx][0] ) ) ); /*max_e+1*/
1384 51200 : dmxSignalImag_fx[binIdx] = L_add( dmxSignalImag_fx[binIdx], tmpDMXSig_fx );
1385 51200 : move32();
1386 : }
1387 : }
1388 : }
1389 : }
1390 : /* Loop over all the bins in the band */
1391 520 : DMXEne_fx = 0;
1392 520 : move32();
1393 26120 : FOR( binIdx = start; binIdx < stop; binIdx++ )
1394 : {
1395 25600 : tmpReal_fx = L_shr( dmxSignalReal_fx[binIdx], 1 );
1396 25600 : tmpImag_fx = L_shr( dmxSignalImag_fx[binIdx], 1 );
1397 :
1398 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)*/
1399 : }
1400 : }
1401 :
1402 260 : dmxEnergy_fx[bandIdx] = DMXEne_fx; /*2*(max_e+2)*/
1403 260 : move32();
1404 : }
1405 :
1406 : /* Step 3: Peform energy smoothing */
1407 280 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1408 : {
1409 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*/
1410 260 : move32();
1411 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)*/
1412 260 : move32();
1413 260 : hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx] = targetEnergy_fx[bandIdx];
1414 260 : move32();
1415 260 : hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx] = dmxEnergy_fx[bandIdx];
1416 260 : move32();
1417 : }
1418 20 : hLsSetUpConversion->te_prev_exp[0] = add( output_exp, 2 );
1419 20 : move16();
1420 20 : hLsSetUpConversion->dmx_prev_exp[0] = shl( add( max_e, 2 ), 1 );
1421 20 : move16();
1422 : /* Step 4: Perform equalization */
1423 80 : FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
1424 : {
1425 60 : IF( NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
1426 : {
1427 60 : IF( EQ_16( transform_type[chInIdx][0], TCX_20 ) )
1428 : {
1429 : /*TCX20*/
1430 742 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1431 : {
1432 689 : start = hLsSetUpConversion->sfbOffset[bandIdx];
1433 689 : move16();
1434 689 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
1435 689 : move16();
1436 :
1437 : /*Compute Eq gains */
1438 689 : ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy_fx[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy_fx[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain_fx );
1439 :
1440 34609 : FOR( binIdx = start; binIdx < stop; binIdx++ )
1441 : {
1442 33920 : x_fx[chInIdx][0][binIdx] = L_shl( Mult_32_32( x_fx[chInIdx][0][binIdx], eqGain_fx ), 1 );
1443 : }
1444 : }
1445 : }
1446 : ELSE
1447 : {
1448 7 : stop_tcx5 = 0;
1449 7 : move16();
1450 98 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1451 : {
1452 91 : start = shr( hLsSetUpConversion->sfbOffset[bandIdx], 1 );
1453 91 : stop = shr( hLsSetUpConversion->sfbOffset[bandIdx + 1], 1 );
1454 :
1455 : /*Compute Eq gains */
1456 91 : ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy_fx[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy_fx[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain_fx );
1457 :
1458 :
1459 273 : FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
1460 : {
1461 182 : IF( EQ_16( transform_type[chInIdx][subFrameIdx], TCX_10 ) )
1462 : {
1463 : /*TCX10*/
1464 2331 : FOR( binIdx = start; binIdx < stop; binIdx++ )
1465 : {
1466 2240 : x_fx[chInIdx][subFrameIdx][binIdx] = L_shl( Mult_32_32( x_fx[chInIdx][subFrameIdx][binIdx], eqGain_fx ), 1 );
1467 2240 : move32();
1468 : }
1469 : }
1470 : ELSE
1471 : {
1472 : /* TCX5*/
1473 91 : start_tcx5 = stop_tcx5;
1474 91 : move16();
1475 91 : stop_tcx5 = shr( add( stop, 1 ), 1 );
1476 1211 : FOR( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
1477 : {
1478 1120 : x_fx[chInIdx][subFrameIdx][binIdx] = L_shl( Mult_32_32( x_fx[chInIdx][subFrameIdx][binIdx], eqGain_fx ), 1 );
1479 1120 : move32();
1480 : }
1481 :
1482 1211 : FOR( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
1483 : {
1484 1120 : x_fx[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )] = L_shl( Mult_32_32( x_fx[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )], eqGain_fx ), 1 );
1485 1120 : move32();
1486 : }
1487 : }
1488 : }
1489 : }
1490 : }
1491 : }
1492 : }
1493 20 : return;
1494 : }
1495 :
1496 :
1497 : /*-------------------------------------------------------------------------
1498 : * ivas_ls_setup_conversion_process_param_mc()
1499 : *
1500 : * LS setup conversion in the CLDFB domain for Parametric MC
1501 : *-------------------------------------------------------------------------*/
1502 :
1503 1360 : void ivas_lssetupconversion_process_param_mc_fx(
1504 : Decoder_Struct *st_ivas, /* i/o: LS setup conversion renderer handle */
1505 : const Word16 num_timeslots,
1506 : Word32 Cldfb_RealBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals Q6*/
1507 : Word32 Cldfb_ImagBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals Q6*/
1508 : Word16 channel_active[MAX_CICP_CHANNELS] /* i : bitmap indicating which output channels are active */
1509 : )
1510 : {
1511 : Word16 slotIdx, chOutIdx, chInIdx, bandIdx;
1512 : Word16 inChannels, outChannels;
1513 : Word32 targetEnergy[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1514 : Word32 dmxEnergy[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1515 : Word32 tmpDMXSig, dmxCoeff, tmpReal, tmpImag;
1516 : Word32 EQ;
1517 : Word32 Cldfb_RealBuffer_tmp[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1518 : Word32 Cldfb_ImagBuffer_tmp[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1519 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
1520 : Word16 i, k;
1521 :
1522 1360 : push_wmops( "LS_Renderer_Process_Param_MC" );
1523 : /* inits */
1524 1360 : inChannels = add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe );
1525 1360 : move16();
1526 1360 : outChannels = add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe );
1527 1360 : move16();
1528 :
1529 1360 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
1530 1360 : EQ = 0;
1531 1360 : move32();
1532 :
1533 1360 : set16_fx( channel_active, 0, outChannels );
1534 :
1535 : /* Loop over each time slots and compute dmx for each time slot */
1536 6800 : FOR( slotIdx = 0; slotIdx < num_timeslots; slotIdx++ )
1537 : {
1538 : // Scale the array
1539 5440 : Word16 q_output = 31;
1540 38080 : FOR( i = 0; i < inChannels; ++i )
1541 : {
1542 32640 : q_output = s_min( q_output, L_norm_arr( Cldfb_RealBuffer_InOut[i][slotIdx], hLsSetUpConversion->sfbCnt ) );
1543 32640 : q_output = s_min( q_output, L_norm_arr( Cldfb_ImagBuffer_InOut[i][slotIdx], hLsSetUpConversion->sfbCnt ) );
1544 : }
1545 :
1546 5440 : Word16 guard_1 = find_guarded_bits_fx( inChannels );
1547 5440 : q_output = sub( q_output, guard_1 );
1548 :
1549 38080 : FOR( i = 0; i < inChannels; ++i )
1550 : {
1551 1991040 : FOR( k = 0; k < hLsSetUpConversion->sfbCnt; ++k )
1552 : {
1553 1958400 : Cldfb_RealBuffer_InOut[i][slotIdx][k] = L_shl( Cldfb_RealBuffer_InOut[i][slotIdx][k], q_output ); // Q(6 + q_output)
1554 1958400 : Cldfb_ImagBuffer_InOut[i][slotIdx][k] = L_shl( Cldfb_ImagBuffer_InOut[i][slotIdx][k], q_output ); // Q(6 + q_output)
1555 : }
1556 : }
1557 : /* copy buffers */
1558 38080 : FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
1559 : {
1560 32640 : Copy32( Cldfb_RealBuffer_InOut[chInIdx][slotIdx], Cldfb_RealBuffer_tmp[chInIdx], CLDFB_NO_CHANNELS_MAX ); // Q(6 + q_output)
1561 32640 : Copy32( Cldfb_ImagBuffer_InOut[chInIdx][slotIdx], Cldfb_ImagBuffer_tmp[chInIdx], CLDFB_NO_CHANNELS_MAX ); // Q(6 + q_output)
1562 : }
1563 : /* set the buffers to zero */
1564 70720 : FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1565 : {
1566 65280 : set32_fx( Cldfb_RealBuffer_InOut[chOutIdx][slotIdx], 0, CLDFB_NO_CHANNELS_MAX );
1567 65280 : set32_fx( Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx], 0, CLDFB_NO_CHANNELS_MAX );
1568 :
1569 65280 : set32_fx( dmxEnergy[chOutIdx], 0, CLDFB_NO_CHANNELS_MAX );
1570 65280 : set32_fx( targetEnergy[chOutIdx], 0, CLDFB_NO_CHANNELS_MAX );
1571 : }
1572 :
1573 : /* Compute the target energy and DMX signal */
1574 70720 : FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1575 : {
1576 456960 : FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
1577 : {
1578 391680 : dmxCoeff = hLsSetUpConversion->dmxMtx_fx[chInIdx][chOutIdx]; // Q30
1579 391680 : move32();
1580 391680 : IF( dmxCoeff == 0 )
1581 : {
1582 359040 : CONTINUE;
1583 : }
1584 : ELSE
1585 : {
1586 32640 : channel_active[chOutIdx] = s_or( 1, channel_active[chOutIdx] );
1587 32640 : move16();
1588 1991040 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1589 : {
1590 1958400 : tmpDMXSig = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), Cldfb_RealBuffer_tmp[chInIdx][bandIdx] ); // Q(6 + q_output)
1591 1958400 : Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx] = L_add( Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx], tmpDMXSig );
1592 1958400 : move32();
1593 1958400 : targetEnergy[chOutIdx][bandIdx] = L_add( targetEnergy[chOutIdx][bandIdx], Mpy_32_32( tmpDMXSig, tmpDMXSig ) ); // Q((6 + q_output)*2 - 31)
1594 1958400 : move32();
1595 :
1596 1958400 : tmpDMXSig = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), Cldfb_ImagBuffer_tmp[chInIdx][bandIdx] );
1597 1958400 : Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx] = L_add( Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx], tmpDMXSig );
1598 1958400 : move32();
1599 1958400 : targetEnergy[chOutIdx][bandIdx] = L_add( targetEnergy[chOutIdx][bandIdx], Mpy_32_32( tmpDMXSig, tmpDMXSig ) );
1600 1958400 : move32();
1601 : }
1602 : }
1603 : }
1604 : }
1605 :
1606 : /* Compute the DMX energy */
1607 70720 : FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1608 : {
1609 65280 : IF( channel_active[chOutIdx] )
1610 : {
1611 1991040 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1612 : {
1613 1958400 : tmpReal = Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx]; // Q(6 + q_output)
1614 1958400 : move32();
1615 1958400 : tmpImag = Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx]; // Q(6 + q_output)
1616 1958400 : move32();
1617 :
1618 1958400 : dmxEnergy[chOutIdx][bandIdx] = L_add( Mpy_32_32( tmpReal, tmpReal ), Mpy_32_32( tmpImag, tmpImag ) ); // Q((6 + q_output)*2 - 31)
1619 1958400 : move32();
1620 : }
1621 : }
1622 : }
1623 :
1624 : /* Peform energy smoothing */
1625 70720 : FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1626 : {
1627 65280 : IF( channel_active[chOutIdx] )
1628 : {
1629 32640 : Word16 te_scale = getScaleFactor32( hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt );
1630 32640 : scale_sig32( hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt, te_scale );
1631 32640 : Word16 dmx_sacle = getScaleFactor32( hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt );
1632 32640 : scale_sig32( hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt, dmx_sacle );
1633 :
1634 32640 : Word16 te_max_e = s_max( sub( 50, shl( q_output, 1 ) ), sub( hLsSetUpConversion->te_prev_exp[chOutIdx], te_scale ) );
1635 32640 : Word16 dmx_max_e = s_max( sub( 50, shl( q_output, 1 ) ), sub( hLsSetUpConversion->dmx_prev_exp[chOutIdx], dmx_sacle ) );
1636 :
1637 1991040 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1638 : {
1639 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 ) ) ) ) );
1640 1958400 : move32();
1641 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 ) ) ) ) );
1642 1958400 : move32();
1643 1958400 : hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx][bandIdx] = targetEnergy[chOutIdx][bandIdx]; // Q0
1644 1958400 : move32();
1645 1958400 : hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx][bandIdx] = dmxEnergy[chOutIdx][bandIdx]; // Q0
1646 1958400 : move32();
1647 : }
1648 :
1649 32640 : hLsSetUpConversion->te_prev_exp[chOutIdx] = te_max_e; /* te_prev_exp = 50 - 2*q_output */
1650 32640 : move16();
1651 32640 : hLsSetUpConversion->dmx_prev_exp[chOutIdx] = dmx_max_e; /* dmx_prev_exp = 50 - 2*q_output */
1652 32640 : move16();
1653 : }
1654 : }
1655 :
1656 70720 : FOR( i = 0; i < outChannels; ++i )
1657 : {
1658 3982080 : FOR( k = 0; k < hLsSetUpConversion->sfbCnt; ++k )
1659 : {
1660 3916800 : Cldfb_RealBuffer_InOut[i][slotIdx][k] = L_shr( Cldfb_RealBuffer_InOut[i][slotIdx][k], q_output ); // Q6
1661 3916800 : move32();
1662 3916800 : Cldfb_ImagBuffer_InOut[i][slotIdx][k] = L_shr( Cldfb_ImagBuffer_InOut[i][slotIdx][k], q_output ); // Q6
1663 3916800 : move32();
1664 : }
1665 : }
1666 :
1667 : /* Compute and perform equalization */
1668 70720 : FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1669 : {
1670 65280 : IF( channel_active[chOutIdx] )
1671 : {
1672 1991040 : FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1673 : {
1674 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
1675 1958400 : Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx] = Mpy_32_32( L_shl( Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx], 1 ), EQ );
1676 1958400 : move32();
1677 1958400 : Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx] = Mpy_32_32( L_shl( Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx], 1 ), EQ );
1678 1958400 : move32();
1679 : }
1680 : }
1681 : }
1682 : }
1683 :
1684 1360 : pop_wmops();
1685 1360 : return;
1686 : }
|