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.h"
38 : #include "ivas_prot.h"
39 : #include "ivas_prot_rend.h"
40 : #include "ivas_rom_com.h"
41 : #include "ivas_rom_rend.h"
42 : #ifdef DEBUGGING
43 : #include "debug.h"
44 : #endif
45 : #include "wmc_auto.h"
46 :
47 :
48 : /*----------------------------------------------------------------------------------*
49 : * Local constants
50 : *----------------------------------------------------------------------------------*/
51 :
52 : #define LS_OUT_CONV_SMOOTHING_FACTOR 0.0435f
53 : #define LS_OUT_CONV_CLIP_FACTOR_MAX 2.0f
54 : #define LS_OUT_CONV_CLIP_FACTOR_MIN 0.3f
55 :
56 :
57 : /*----------------------------------------------------------------------------------*
58 : * Local functions
59 : *----------------------------------------------------------------------------------*/
60 :
61 10911750 : static void ivas_lssetupconversion_computeEQFactor(
62 : float *outputEnergy,
63 : float *inputEnergy,
64 : float *EQ )
65 : {
66 : /* Compute the Equalization Gain */
67 10911750 : *EQ = sqrtf( *outputEnergy / ( EPSILON + *inputEnergy ) );
68 :
69 : /* Limit the Equalization Gain */
70 10911750 : *EQ = min( *EQ, LS_OUT_CONV_CLIP_FACTOR_MAX );
71 10911750 : *EQ = max( *EQ, LS_OUT_CONV_CLIP_FACTOR_MIN );
72 :
73 10911750 : return;
74 : }
75 :
76 :
77 207 : static void ivas_lssetupconversion_mdct_init_bands(
78 : const int16_t output_frame, /* i : output frame length */
79 : const int16_t tcx_mode, /* i : tcx mode (TCX10, TCX 20) */
80 : int16_t *sfbOffset, /* o : sfb offset table */
81 : int16_t *sfbCnt /* o : number of sfbs */
82 : )
83 : {
84 : SpectrumWarping const *lpcBndsParam;
85 : int16_t i, cnt, specStartOffset, L_frameTCX;
86 : const unsigned char *sfbWidths;
87 :
88 207 : L_frameTCX = ( tcx_mode == TCX_20_CORE ) ? output_frame : ( output_frame / 2 );
89 :
90 207 : switch ( output_frame )
91 : {
92 207 : case L_FRAME48k:
93 : case L_FRAME32k:
94 207 : lpcBndsParam = sw32000Hz;
95 207 : break;
96 0 : case L_FRAME25_6k:
97 0 : lpcBndsParam = sw25600Hz;
98 0 : break;
99 0 : case L_FRAME16k:
100 0 : lpcBndsParam = sw16000Hz;
101 0 : break;
102 0 : default:
103 0 : assert( !"Subband division not defined for this frame size" );
104 : return;
105 : }
106 :
107 207 : sfbWidths = ( tcx_mode == TCX_20_CORE ? lpcBndsParam->bandLengthsTCX20 : lpcBndsParam->bandLengthsTCX10 );
108 207 : cnt = ( tcx_mode == TCX_20_CORE ? 64 : 32 );
109 :
110 : /* calc sfb offsets */
111 207 : specStartOffset = 0;
112 :
113 13455 : for ( i = 0; i < cnt; i++ )
114 : {
115 13248 : sfbOffset[i] = min( specStartOffset, L_frameTCX );
116 13248 : specStartOffset += sfbWidths[i];
117 :
118 13248 : if ( sfbOffset[i] >= L_frameTCX )
119 : {
120 0 : break;
121 : }
122 : }
123 :
124 207 : *sfbCnt = i;
125 207 : sfbOffset[*sfbCnt] = min( specStartOffset, L_frameTCX );
126 :
127 207 : if ( sfbOffset[*sfbCnt] < L_frameTCX )
128 : {
129 198 : int16_t nMissingBins = L_frameTCX - sfbOffset[*sfbCnt];
130 :
131 198 : if ( sfbWidths[i] / 2 < nMissingBins )
132 : {
133 198 : ( *sfbCnt )++;
134 : }
135 198 : sfbOffset[*sfbCnt] = L_frameTCX;
136 : }
137 :
138 207 : return;
139 : }
140 :
141 :
142 3 : static void get_custom_ls_conversion_matrix(
143 : const EFAP_HANDLE hEFAPdata, /* i : EFAP handle */
144 : const IVAS_OUTPUT_SETUP hTransSetup, /* i : Transport channel configuration handle */
145 : const LSSETUP_CUSTOM_HANDLE hLsSetupCustom, /* i : Custom LS Setup handle */
146 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion /* o : LS Setup Conversion Handle */
147 : )
148 : {
149 : int16_t ch_in, ch_in_woLFE;
150 : int16_t ch_out, ch_out_woLFE;
151 : int16_t nchan_in, nchan_out;
152 : int16_t lfe_in_idx, lfe_out_idx;
153 :
154 : float dmxCoeff_LFE;
155 : float tmp_gains[MAX_OUTPUT_CHANNELS];
156 :
157 3 : lfe_in_idx = -1;
158 3 : lfe_out_idx = -1;
159 :
160 3 : nchan_in = hTransSetup.nchan_out_woLFE + hTransSetup.num_lfe;
161 3 : nchan_out = hLsSetupCustom->num_spk + hLsSetupCustom->num_lfe;
162 :
163 : /* The below code will need to be restructured in case additional LFEs must be supported */
164 3 : if ( hTransSetup.num_lfe > 0 )
165 : {
166 3 : lfe_in_idx = hTransSetup.index_lfe[0];
167 : }
168 3 : if ( hLsSetupCustom->num_lfe > 0 )
169 : {
170 0 : lfe_out_idx = hLsSetupCustom->lfe_idx[0];
171 : }
172 :
173 3 : dmxCoeff_LFE = 1.f / hTransSetup.nchan_out_woLFE;
174 :
175 21 : for ( ch_in = 0, ch_in_woLFE = 0; ch_in < nchan_in; ch_in++, ch_in_woLFE++ )
176 : {
177 18 : if ( lfe_in_idx == ch_in )
178 : {
179 3 : if ( lfe_out_idx >= 0 )
180 : {
181 : /* re-route LFE */
182 0 : hLsSetUpConversion->dmxMtx[ch_in][lfe_out_idx] = 1.0f;
183 : }
184 : else
185 : {
186 : /* mix the LFE to all channels */
187 3 : set_f( hLsSetUpConversion->dmxMtx[ch_in], dmxCoeff_LFE, nchan_out );
188 : }
189 :
190 3 : ch_in_woLFE--;
191 : }
192 15 : else if ( lfe_out_idx != ch_in )
193 : {
194 : /* Set the values of hLsSetUpConversion->dmxMtx to EFAP gains, skipping LFE */
195 15 : efap_determine_gains( hEFAPdata, tmp_gains, hTransSetup.ls_azimuth[ch_in_woLFE], hTransSetup.ls_elevation[ch_in_woLFE], EFAP_MODE_EFAP );
196 :
197 255 : for ( ch_out = 0, ch_out_woLFE = 0; ch_out < nchan_out; ch_out++, ch_out_woLFE++ )
198 : {
199 240 : if ( lfe_out_idx == ch_out )
200 : {
201 0 : ch_out_woLFE--;
202 : }
203 : else
204 : {
205 240 : hLsSetUpConversion->dmxMtx[ch_in][ch_out] = tmp_gains[ch_out_woLFE];
206 : }
207 : }
208 : }
209 : }
210 :
211 3 : return;
212 : }
213 :
214 :
215 375 : static ivas_error get_ls_conversion_matrix(
216 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion,
217 : const AUDIO_CONFIG input_config,
218 : const AUDIO_CONFIG output_config )
219 : {
220 : int16_t i, k;
221 : int16_t ch_in, ch_out;
222 : int16_t nchan_in, nchan_out;
223 : int16_t index;
224 : float value;
225 : const LS_CONVERSION_MATRIX *conversion_matrix;
226 :
227 375 : conversion_matrix = NULL;
228 :
229 375 : nchan_in = audioCfg2channels( input_config );
230 375 : nchan_out = audioCfg2channels( output_config );
231 :
232 : /* Search the table for a mapping */
233 10311 : for ( i = 0; i < LS_SETUP_CONVERSION_NUM_MAPPINGS; i++ )
234 : {
235 10311 : if ( ( input_config == ls_conversion_mapping[i].input_config ) && ( output_config == ls_conversion_mapping[i].output_config ) )
236 : {
237 : /* Special handling for MONO and STEREO downmix */
238 375 : if ( output_config == IVAS_AUDIO_CONFIG_MONO || output_config == IVAS_AUDIO_CONFIG_STEREO )
239 : {
240 246 : for ( ch_in = 0, k = 0; ch_in < nchan_in; ch_in++, k++ )
241 : {
242 : /* Skip two rows in the matrix for 5.1.x formats */
243 222 : if ( ch_in == 6 && ( input_config == IVAS_AUDIO_CONFIG_5_1_2 || input_config == IVAS_AUDIO_CONFIG_5_1_4 ) )
244 : {
245 3 : k += 2;
246 : }
247 :
248 648 : for ( ch_out = 0; ch_out < nchan_out; ch_out++ )
249 : {
250 426 : if ( output_config == IVAS_AUDIO_CONFIG_MONO )
251 : {
252 18 : hLsSetUpConversion->dmxMtx[ch_in][ch_out] = ls_conversion_cicpX_mono[k][ch_out];
253 : }
254 : else
255 : {
256 408 : hLsSetUpConversion->dmxMtx[ch_in][ch_out] = ls_conversion_cicpX_stereo[k][ch_out];
257 : }
258 : }
259 : }
260 24 : return IVAS_ERR_OK;
261 : }
262 : else
263 : {
264 351 : conversion_matrix = ls_conversion_mapping[i].conversion_matrix;
265 :
266 : /* If a mapping is defined with a NULL matrix, 1:1 upmix of input channels */
267 351 : if ( conversion_matrix == NULL )
268 : {
269 2436 : for ( k = 0; k < nchan_in; k++ )
270 : {
271 2088 : hLsSetUpConversion->dmxMtx[k][k] = 1.0f;
272 : }
273 348 : return IVAS_ERR_OK;
274 : }
275 : else
276 : {
277 27 : for ( k = 1; k < ( conversion_matrix[0].index + 1 ); k++ )
278 : {
279 24 : index = conversion_matrix[k].index;
280 24 : value = conversion_matrix[k].value;
281 :
282 24 : ch_in = index / nchan_out;
283 24 : ch_out = index % nchan_out;
284 :
285 24 : hLsSetUpConversion->dmxMtx[ch_in][ch_out] = value;
286 : }
287 : }
288 3 : return IVAS_ERR_OK;
289 : }
290 : }
291 : }
292 :
293 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "The conversion matrix between these formats is not defined!\n" );
294 : }
295 :
296 :
297 : /*-------------------------------------------------------------------------
298 : * ivas_ls_setup_conversion_open()
299 : *
300 : * Open the LS configuration Conversion Module
301 : *-------------------------------------------------------------------------*/
302 :
303 378 : ivas_error ivas_ls_setup_conversion_open(
304 : Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
305 : )
306 : {
307 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
308 : int16_t chIdx, inChannels, outChannels;
309 : int16_t output_frame;
310 : int32_t output_Fs;
311 : int16_t paramUpmixMonoStereo;
312 : ivas_error error;
313 :
314 378 : if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMUPMIX && ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_MONO || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_STEREO ) )
315 : {
316 3 : paramUpmixMonoStereo = TRUE;
317 : }
318 : else
319 : {
320 375 : paramUpmixMonoStereo = FALSE;
321 : }
322 378 : output_Fs = st_ivas->hDecoderConfig->output_Fs;
323 378 : outChannels = st_ivas->hDecoderConfig->nchan_out;
324 378 : output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC );
325 :
326 : /* Allocate memory to the handle */
327 378 : if ( ( hLsSetUpConversion = (LSSETUP_CONVERSION_HANDLE) malloc( sizeof( LSSETUP_CONVERSION_STRUCT ) ) ) == NULL )
328 : {
329 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
330 : }
331 :
332 378 : assert( outChannels <= MAX_OUTPUT_CHANNELS );
333 :
334 378 : if ( st_ivas->renderer_type == RENDERER_MC_PARAMMC )
335 : {
336 171 : inChannels = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe;
337 171 : hLsSetUpConversion->sfbCnt = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f );
338 2145 : for ( chIdx = 0; chIdx < outChannels; chIdx++ )
339 : {
340 1974 : if ( ( hLsSetUpConversion->targetEnergyPrev[chIdx] = (float *) malloc( ( hLsSetUpConversion->sfbCnt ) * sizeof( float ) ) ) == NULL )
341 : {
342 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
343 : }
344 1974 : if ( ( hLsSetUpConversion->dmxEnergyPrev[chIdx] = (float *) malloc( ( hLsSetUpConversion->sfbCnt ) * sizeof( float ) ) ) == NULL )
345 : {
346 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
347 : }
348 1974 : set_f( hLsSetUpConversion->targetEnergyPrev[chIdx], 0.0f, hLsSetUpConversion->sfbCnt );
349 1974 : set_f( hLsSetUpConversion->dmxEnergyPrev[chIdx], 0.0f, hLsSetUpConversion->sfbCnt );
350 : }
351 933 : for ( ; chIdx < MAX_LS_CHANNELS; chIdx++ )
352 : {
353 762 : hLsSetUpConversion->targetEnergyPrev[chIdx] = NULL;
354 762 : hLsSetUpConversion->dmxEnergyPrev[chIdx] = NULL;
355 : }
356 : }
357 : else
358 : {
359 207 : if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
360 : {
361 3 : if ( paramUpmixMonoStereo == TRUE )
362 : {
363 3 : inChannels = audioCfg2channels( IVAS_AUDIO_CONFIG_5_1_2 );
364 : }
365 : else
366 : {
367 0 : inChannels = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe;
368 : }
369 : }
370 : else
371 : {
372 204 : inChannels = st_ivas->nchan_transport;
373 : }
374 :
375 : /*Initialization of MDCT bands with TCX20 resolution */
376 207 : ivas_lssetupconversion_mdct_init_bands( output_frame, TCX_20_CORE, &hLsSetUpConversion->sfbOffset[0], &hLsSetUpConversion->sfbCnt );
377 207 : if ( ( hLsSetUpConversion->targetEnergyPrev[0] = (float *) malloc( ( MAX_SFB + 2 ) * sizeof( float ) ) ) == NULL )
378 : {
379 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
380 : }
381 207 : if ( ( hLsSetUpConversion->dmxEnergyPrev[0] = (float *) malloc( ( MAX_SFB + 2 ) * sizeof( float ) ) ) == NULL )
382 : {
383 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
384 : }
385 :
386 3312 : for ( chIdx = 1; chIdx < MAX_LS_CHANNELS; chIdx++ )
387 : {
388 3105 : hLsSetUpConversion->targetEnergyPrev[chIdx] = NULL;
389 3105 : hLsSetUpConversion->dmxEnergyPrev[chIdx] = NULL;
390 : }
391 207 : set_f( hLsSetUpConversion->targetEnergyPrev[0], 0.0f, MAX_SFB + 2 );
392 207 : set_f( hLsSetUpConversion->dmxEnergyPrev[0], 0.0f, MAX_SFB + 2 );
393 : }
394 :
395 :
396 : /* Initialize the DMX conversion matrix */
397 2730 : for ( chIdx = 0; chIdx < inChannels; chIdx++ )
398 : {
399 : /* Allocate memory depending on the number of output channels */
400 2352 : if ( ( hLsSetUpConversion->dmxMtx[chIdx] = (float *) malloc( outChannels * sizeof( float ) ) ) == NULL )
401 : {
402 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for temp dmx matrix \n" ) );
403 : }
404 2352 : set_zero( hLsSetUpConversion->dmxMtx[chIdx], outChannels );
405 : }
406 :
407 4074 : for ( ; chIdx < MAX_LS_CHANNELS; chIdx++ )
408 : {
409 3696 : hLsSetUpConversion->dmxMtx[chIdx] = NULL;
410 : }
411 :
412 378 : if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM )
413 : {
414 3 : get_custom_ls_conversion_matrix( st_ivas->hEFAPdata, st_ivas->hTransSetup, st_ivas->hLsSetupCustom, hLsSetUpConversion );
415 : }
416 : else
417 : {
418 375 : if ( st_ivas->transport_config != IVAS_AUDIO_CONFIG_INVALID )
419 : {
420 375 : if ( paramUpmixMonoStereo == TRUE )
421 : {
422 3 : if ( ( error = get_ls_conversion_matrix( hLsSetUpConversion, IVAS_AUDIO_CONFIG_5_1_2, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
423 : {
424 0 : return error;
425 : }
426 : }
427 : else
428 : {
429 372 : if ( ( error = get_ls_conversion_matrix( hLsSetUpConversion, st_ivas->transport_config, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
430 : {
431 0 : return error;
432 : }
433 : }
434 : }
435 : else
436 : {
437 0 : if ( ( error = get_ls_conversion_matrix( hLsSetUpConversion, st_ivas->intern_config, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
438 : {
439 0 : return error;
440 : }
441 : }
442 : }
443 :
444 378 : st_ivas->hLsSetUpConversion = hLsSetUpConversion;
445 :
446 378 : return IVAS_ERR_OK;
447 : }
448 :
449 :
450 : /*-------------------------------------------------------------------------
451 : * ivas_ls_setup_conversion_close()
452 : *
453 : * Close the LS configuration Conversion Module
454 : *-------------------------------------------------------------------------*/
455 :
456 2649 : void ivas_ls_setup_conversion_close(
457 : LSSETUP_CONVERSION_HANDLE *hLsSetUpConversion /* i/o: LS converter handle */
458 : )
459 : {
460 : int16_t idx;
461 :
462 2649 : if ( hLsSetUpConversion == NULL || *hLsSetUpConversion == NULL )
463 : {
464 2271 : return;
465 : }
466 :
467 6426 : for ( idx = 0; idx < MAX_LS_CHANNELS; idx++ )
468 : {
469 6048 : if ( ( *hLsSetUpConversion )->dmxMtx[idx] != NULL )
470 : {
471 2352 : free( ( *hLsSetUpConversion )->dmxMtx[idx] );
472 2352 : ( *hLsSetUpConversion )->dmxMtx[idx] = NULL;
473 : }
474 :
475 6048 : if ( ( *hLsSetUpConversion )->targetEnergyPrev[idx] != NULL )
476 : {
477 2181 : free( ( *hLsSetUpConversion )->targetEnergyPrev[idx] );
478 2181 : ( *hLsSetUpConversion )->targetEnergyPrev[idx] = NULL;
479 : }
480 :
481 6048 : if ( ( *hLsSetUpConversion )->dmxEnergyPrev[idx] != NULL )
482 : {
483 2181 : free( ( *hLsSetUpConversion )->dmxEnergyPrev[idx] );
484 2181 : ( *hLsSetUpConversion )->dmxEnergyPrev[idx] = NULL;
485 : }
486 : }
487 :
488 378 : free( *hLsSetUpConversion );
489 378 : *hLsSetUpConversion = NULL;
490 :
491 378 : return;
492 : }
493 :
494 :
495 : /*-------------------------------------------------------------------------
496 : * ivas_ls_setup_conversion()
497 : *
498 : * Convert (downmix or upmix) the input LS configuration
499 : * to output LS configuration in time domain
500 : *-------------------------------------------------------------------------*/
501 :
502 36242 : void ivas_ls_setup_conversion(
503 : Decoder_Struct *st_ivas, /* i : IVAS decoder structure */
504 : const int16_t input_chans, /* i : number of input channels to the renderer */
505 : const int16_t output_frame, /* i : frame length */
506 : float *input[], /* i : LS input/output synthesis signal */
507 : float *output[] /* i/o: LS input/output synthesis signal */
508 : )
509 : {
510 : int16_t chInIdx, chOutIdx, idx;
511 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
512 : float dmxCoeff, tmpVal;
513 : float output_tmp[MAX_OUTPUT_CHANNELS][L_FRAME48k];
514 :
515 36242 : push_wmops( "LS_Renderer" );
516 :
517 36242 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
518 :
519 404376 : for ( chOutIdx = 0; chOutIdx < st_ivas->hDecoderConfig->nchan_out; chOutIdx++ )
520 : {
521 368134 : set_zero( output_tmp[chOutIdx], output_frame );
522 2577778 : for ( chInIdx = 0; chInIdx < input_chans; chInIdx++ )
523 : {
524 2209644 : dmxCoeff = hLsSetUpConversion->dmxMtx[chInIdx][chOutIdx];
525 :
526 2209644 : if ( dmxCoeff == 0.f )
527 : {
528 1860478 : continue;
529 : }
530 349166 : else if ( dmxCoeff == 1.f )
531 : {
532 74664504 : for ( idx = 0; idx < output_frame; idx++ )
533 : {
534 74498760 : output_tmp[chOutIdx][idx] += input[chInIdx][idx];
535 : }
536 : }
537 : else
538 : {
539 99007742 : for ( idx = 0; idx < output_frame; idx++ )
540 : {
541 98824320 : tmpVal = dmxCoeff * input[chInIdx][idx];
542 98824320 : output_tmp[chOutIdx][idx] += tmpVal;
543 : }
544 : }
545 : }
546 : }
547 :
548 : /* Copy to output buffer */
549 404376 : for ( chOutIdx = 0; chOutIdx < st_ivas->hDecoderConfig->nchan_out; chOutIdx++ )
550 : {
551 368134 : mvr2r( output_tmp[chOutIdx], output[chOutIdx], output_frame );
552 : }
553 :
554 36242 : pop_wmops();
555 :
556 36242 : return;
557 : }
558 :
559 :
560 : /*-------------------------------------------------------------------------
561 : * ivas_ls_setup_conversion_process_mdct()
562 : *
563 : * Equalization in MDCT Domain
564 : *-------------------------------------------------------------------------*/
565 :
566 19509 : void ivas_ls_setup_conversion_process_mdct(
567 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
568 : float *output[] /* i/o: output synthesis signal */
569 : )
570 : {
571 : /* Declaration of all required variables */
572 : int16_t i, bandIdx, chInIdx, chOutIdx, cpe_idx, subFrameIdx, binIdx, idx;
573 : int16_t inChannels, outChannels, num_CPE;
574 : int16_t transform_type[MAX_LS_CHANNELS][2];
575 : int16_t frameSize;
576 : float targetEnergy[MAX_SFB + 2], dmxEnergy[MAX_SFB + 2];
577 : float dmxCoeff;
578 : float dmxSignalReal[L_FRAME48k], dmxSignalImag[L_FRAME48k];
579 : float eqGain;
580 : float *sig[NB_DIV], *pTmp[NB_DIV], *x[MAX_LS_CHANNELS][NB_DIV];
581 : float mdst[L_FRAME48k];
582 : float convertRes[L_FRAME48k];
583 : int16_t start, stop, start_tcx5, stop_tcx5;
584 : int16_t mct_chan_mode[MAX_LS_CHANNELS];
585 :
586 : /* Declare all handles */
587 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
588 : CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS];
589 :
590 19509 : push_wmops( "LS_Renderer_MDCT" );
591 :
592 : /* Assign all the declared variables */
593 19509 : inChannels = st_ivas->nchan_transport;
594 19509 : outChannels = st_ivas->hDecoderConfig->nchan_out;
595 19509 : num_CPE = st_ivas->nCPE;
596 :
597 : /* Assign output pointer to variable x */
598 137163 : for ( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
599 : {
600 117654 : x[chInIdx][0] = output[chInIdx];
601 117654 : x[chInIdx][1] = output[chInIdx] + ( L_FRAME48k / 2 );
602 : }
603 :
604 : /* Assign all the declared handles*/
605 19509 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
606 78336 : for ( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
607 : {
608 58827 : hCPE[cpe_idx] = st_ivas->hCPE[cpe_idx];
609 : }
610 :
611 : /* Get the core type */
612 78336 : for ( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
613 : {
614 176481 : for ( idx = 0; idx < CPE_CHANNELS; idx++ )
615 : {
616 : /* get the channel index */
617 117654 : chInIdx = cpe_idx * CPE_CHANNELS + idx;
618 117654 : assert( chInIdx <= inChannels );
619 117654 : transform_type[chInIdx][0] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[0];
620 117654 : transform_type[chInIdx][1] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[1];
621 117654 : mct_chan_mode[chInIdx] = hCPE[cpe_idx]->hCoreCoder[idx]->mct_chan_mode;
622 : }
623 : }
624 :
625 : /* set overall frequency resolution of (sub)frame to maximum of (sub)frame, requires conversion if both channels are not the same */
626 19509 : frameSize = hLsSetUpConversion->sfbOffset[hLsSetUpConversion->sfbCnt];
627 :
628 19509 : set_zero( targetEnergy, MAX_SFB + 2 );
629 19509 : set_zero( dmxEnergy, MAX_SFB + 2 );
630 :
631 171447 : for ( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
632 : {
633 : /* Step 0: Set the buffers to zero */
634 151938 : set_zero( dmxSignalReal, frameSize );
635 151938 : set_zero( dmxSignalImag, frameSize );
636 :
637 1064766 : for ( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
638 : {
639 912828 : dmxCoeff = hLsSetUpConversion->dmxMtx[chInIdx][chOutIdx];
640 :
641 912828 : if ( chInIdx != LFE_CHANNEL && mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
642 : {
643 : /* Step 1: Compute the target energy and DMX signal (possible since we have all signals in TCX20 resolution) */
644 599793 : if ( dmxCoeff )
645 : {
646 : float tmpDMXSig, targetEne;
647 :
648 : /* Convert the signal resolution to TCX20 */
649 : /* initially, set pointers to input; if conversion occurs in (sub)frame, set to convertRes */
650 86460 : sig[0] = pTmp[0] = x[chInIdx][0];
651 86460 : sig[1] = pTmp[1] = x[chInIdx][1];
652 :
653 : /* convert (sub)frames to higher frequency resolution */
654 86460 : if ( transform_type[chInIdx][0] != TCX_20 )
655 : {
656 4545 : for ( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
657 : {
658 3030 : if ( transform_type[chInIdx][subFrameIdx] == TCX_5 )
659 : {
660 : /* subframe is TCX5, but TCX10 or TCX20 in other channel -> convert channel with TCX5 to TCX10 resolution */
661 1602 : pTmp[subFrameIdx] = sig[subFrameIdx] = convertRes + subFrameIdx * frameSize / 2;
662 1602 : convert_coeffs_to_higher_res( x[chInIdx][subFrameIdx], x[chInIdx][subFrameIdx] + frameSize / 4, pTmp[subFrameIdx], frameSize / 4 );
663 : }
664 : }
665 :
666 : /* convert channel with TCX10 to TCX20 resolution */
667 1515 : sig[0] = convertRes;
668 1515 : convert_coeffs_to_higher_res( pTmp[0], pTmp[1], sig[0], frameSize / 2 );
669 : }
670 :
671 : /* MDST estimate */
672 86460 : mdst[0] = mdst[frameSize - 1] = 0.f;
673 82531140 : for ( i = 1; i < frameSize - 1; i++ )
674 : {
675 82444680 : mdst[i] = sig[0][i + 1] - sig[0][i - 1];
676 : }
677 :
678 5705160 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
679 : {
680 5618700 : start = hLsSetUpConversion->sfbOffset[bandIdx];
681 5618700 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
682 :
683 5618700 : targetEne = 0.0f;
684 :
685 : /* Loop over all the bins in the band */
686 88236300 : for ( binIdx = start; binIdx < stop; binIdx++ )
687 : {
688 82617600 : tmpDMXSig = dmxCoeff * sig[0][binIdx];
689 82617600 : dmxSignalReal[binIdx] += tmpDMXSig;
690 82617600 : targetEne += tmpDMXSig * tmpDMXSig;
691 :
692 82617600 : tmpDMXSig = dmxCoeff * mdst[binIdx];
693 82617600 : dmxSignalImag[binIdx] += tmpDMXSig;
694 82617600 : targetEne += tmpDMXSig * tmpDMXSig;
695 : }
696 5618700 : targetEnergy[bandIdx] += targetEne;
697 : } /* end of band loop */
698 : }
699 : }
700 : } /* end of chInIdx loop */
701 :
702 10027668 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
703 : {
704 : float tmpReal, tmpImag, DMXEne;
705 :
706 9875730 : start = hLsSetUpConversion->sfbOffset[bandIdx];
707 9875730 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
708 :
709 : /* Loop over all the bins in the band */
710 9875730 : DMXEne = 0.0f;
711 155659410 : for ( binIdx = start; binIdx < stop; binIdx++ )
712 : {
713 145783680 : tmpReal = dmxSignalReal[binIdx];
714 145783680 : tmpImag = dmxSignalImag[binIdx];
715 :
716 145783680 : DMXEne += tmpReal * tmpReal + tmpImag * tmpImag;
717 : }
718 9875730 : dmxEnergy[bandIdx] += DMXEne;
719 : }
720 : } /* end of out channel loop */
721 :
722 : /* Step 3: Peform energy smoothing */
723 1287474 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
724 : {
725 1267965 : targetEnergy[bandIdx] = LS_OUT_CONV_SMOOTHING_FACTOR * targetEnergy[bandIdx] + ( 1.0f - LS_OUT_CONV_SMOOTHING_FACTOR ) * hLsSetUpConversion->targetEnergyPrev[0][bandIdx];
726 1267965 : dmxEnergy[bandIdx] = LS_OUT_CONV_SMOOTHING_FACTOR * dmxEnergy[bandIdx] + ( 1.0f - LS_OUT_CONV_SMOOTHING_FACTOR ) * hLsSetUpConversion->dmxEnergyPrev[0][bandIdx];
727 1267965 : hLsSetUpConversion->targetEnergyPrev[0][bandIdx] = targetEnergy[bandIdx];
728 1267965 : hLsSetUpConversion->dmxEnergyPrev[0][bandIdx] = dmxEnergy[bandIdx];
729 : }
730 :
731 : /* Step 4: Perform equalization */
732 137163 : for ( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
733 : {
734 117654 : if ( chInIdx != LFE_CHANNEL && mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
735 : {
736 77466 : if ( transform_type[chInIdx][0] == TCX_20 )
737 : {
738 : /* TCX20 */
739 5017128 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
740 : {
741 4941096 : start = hLsSetUpConversion->sfbOffset[bandIdx];
742 4941096 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
743 :
744 : /* Compute Eq gains */
745 4941096 : ivas_lssetupconversion_computeEQFactor( &targetEnergy[bandIdx], &dmxEnergy[bandIdx], &eqGain );
746 77616936 : for ( binIdx = start; binIdx < stop; binIdx++ )
747 : {
748 72675840 : x[chInIdx][0][binIdx] *= eqGain;
749 : }
750 : }
751 : }
752 : else
753 : {
754 1434 : stop_tcx5 = 0;
755 94548 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
756 : {
757 93114 : start = hLsSetUpConversion->sfbOffset[bandIdx] / 2;
758 93114 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1] / 2;
759 :
760 : /* Compute Eq gains */
761 93114 : ivas_lssetupconversion_computeEQFactor( &targetEnergy[bandIdx], &dmxEnergy[bandIdx], &eqGain );
762 :
763 279342 : for ( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
764 : {
765 186228 : if ( transform_type[chInIdx][subFrameIdx] == TCX_10 )
766 : {
767 : /* TCX10 */
768 723564 : for ( binIdx = start; binIdx < stop; binIdx++ )
769 : {
770 635520 : x[chInIdx][subFrameIdx][binIdx] *= eqGain;
771 : }
772 : }
773 : else
774 : {
775 : /* TCX5*/
776 98184 : start_tcx5 = stop_tcx5;
777 98184 : stop_tcx5 = ( stop + 1 ) / 2;
778 :
779 434664 : for ( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
780 : {
781 336480 : x[chInIdx][subFrameIdx][binIdx] *= eqGain;
782 336480 : x[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )] *= eqGain;
783 : }
784 : }
785 : }
786 : }
787 : }
788 : }
789 : }
790 :
791 19509 : pop_wmops();
792 19509 : return;
793 : }
794 :
795 :
796 : /*-------------------------------------------------------------------------
797 : * ivas_ls_setup_conversion_process_mdct_param_mc()
798 : *
799 : * Equalization in MDCT Domain
800 : *-------------------------------------------------------------------------*/
801 :
802 60 : void ivas_ls_setup_conversion_process_mdct_param_mc(
803 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
804 : float *x[][NB_DIV] /* i/o: output synthesis signal */
805 : )
806 : {
807 : /* Declaration of all required variables */
808 : int16_t i;
809 : int16_t idx;
810 : int16_t nchan_transport, nchan_out, nchan_transport_format;
811 : int16_t chInIdx, chOutIdx, cpe_idx, subFrameIdx, binIdx;
812 : int16_t band, bandIdx, num_bands;
813 :
814 : int16_t num_CPE;
815 : int16_t transform_type[MAX_LS_CHANNELS][2];
816 : int16_t frameSize;
817 :
818 : float targetEnergy[MAX_SFB + 2], dmxEnergy[MAX_SFB + 2];
819 : float eqGain;
820 : float *sig[MAX_LS_CHANNELS][NB_DIV], *pTmp[NB_DIV];
821 : float mdst[MAX_LS_CHANNELS][L_FRAME48k];
822 : float convertRes[MAX_LS_CHANNELS][L_FRAME48k];
823 : int16_t start, stop, start_tcx5, stop_tcx5;
824 : int16_t mct_chan_mode[MAX_LS_CHANNELS];
825 :
826 : float cx[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
827 : float cx_imag[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
828 : float cy[MAX_LS_CHANNELS * MAX_LS_CHANNELS];
829 : float real_in_buffer[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS];
830 : float imag_in_buffer[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS];
831 : float real_buffer[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
832 : float imag_buffer[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
833 :
834 : float Nrqq[MAX_OUTPUT_CHANNELS];
835 : float target_ch_ener[MAX_OUTPUT_CHANNELS];
836 : float *ild_q;
837 :
838 : float DMXEne;
839 : float dmxCoeff;
840 : float dmxSignalReal[L_FRAME48k], dmxSignalImag[L_FRAME48k];
841 :
842 : float tmpReal, tmpImag;
843 : float tmpDMXSig;
844 :
845 : /* Declare all handles */
846 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
847 : CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS];
848 : PARAM_MC_DEC_HANDLE hParamMC;
849 :
850 : /* Step 0: Set the buffers to zero */
851 60 : set_zero( dmxSignalReal, L_FRAME48k );
852 60 : set_zero( dmxSignalImag, L_FRAME48k );
853 :
854 : /* Assign all the declared variables */
855 60 : nchan_transport = st_ivas->nchan_transport;
856 60 : nchan_out = st_ivas->hDecoderConfig->nchan_out;
857 60 : num_CPE = st_ivas->nCPE;
858 60 : nchan_transport_format = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe;
859 :
860 : /* Assign all the declared handles*/
861 60 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
862 180 : for ( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
863 : {
864 120 : hCPE[cpe_idx] = st_ivas->hCPE[cpe_idx];
865 : }
866 60 : hParamMC = st_ivas->hParamMC;
867 :
868 : /* Get the core type */
869 180 : for ( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
870 : {
871 360 : for ( idx = 0; idx < CPE_CHANNELS; idx++ )
872 : {
873 : /* get the channel index */
874 240 : chInIdx = cpe_idx * CPE_CHANNELS + idx;
875 240 : assert( chInIdx <= nchan_transport );
876 240 : transform_type[chInIdx][0] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[0];
877 240 : transform_type[chInIdx][1] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[1];
878 240 : mct_chan_mode[chInIdx] = hCPE[cpe_idx]->hCoreCoder[idx]->mct_chan_mode;
879 : }
880 : }
881 :
882 : /* set overall frequency resolution of (sub)frame to maximum of (sub)frame, requires conversion if both channels are not the same */
883 60 : frameSize = hLsSetUpConversion->sfbOffset[hLsSetUpConversion->sfbCnt];
884 :
885 60 : set_zero( targetEnergy, MAX_SFB + 2 );
886 60 : set_zero( dmxEnergy, MAX_SFB + 2 );
887 :
888 240 : for ( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
889 : {
890 180 : if ( mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
891 : {
892 : /* initially, set pointers to input; if conversion occurs in (sub)frame, set to convertRes */
893 180 : sig[chInIdx][0] = pTmp[0] = x[chInIdx][0];
894 180 : sig[chInIdx][1] = pTmp[1] = x[chInIdx][1];
895 :
896 : /* convert (sub)frames to higher frequency resolution */
897 180 : if ( transform_type[chInIdx][0] != TCX_20 )
898 : {
899 63 : for ( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
900 : {
901 42 : if ( transform_type[chInIdx][subFrameIdx] == TCX_5 )
902 : {
903 : /* subframe is TCX5, but TCX10 or TCX20 in other channel -> convert channel with TCX5 to TCX10 resolution */
904 21 : pTmp[subFrameIdx] = sig[chInIdx][subFrameIdx] = convertRes[chInIdx] + subFrameIdx * frameSize / 2;
905 21 : convert_coeffs_to_higher_res( x[chInIdx][subFrameIdx], x[chInIdx][subFrameIdx] + frameSize / 4, pTmp[subFrameIdx], frameSize / 4 );
906 : }
907 : }
908 :
909 : /* convert channel with TCX10 to TCX20 resolution */
910 21 : sig[chInIdx][0] = convertRes[chInIdx];
911 21 : convert_coeffs_to_higher_res( pTmp[0], pTmp[1], sig[chInIdx][0], frameSize / 2 );
912 : }
913 : }
914 : }
915 :
916 : /* precalculate MDST estimate */
917 240 : for ( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
918 : {
919 180 : if ( mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
920 : {
921 180 : mdst[chInIdx][0] = mdst[chInIdx][frameSize - 1] = 0.f;
922 115020 : for ( i = 1; i < frameSize - 1; i++ )
923 : {
924 114840 : mdst[chInIdx][i] = sig[chInIdx][0][i + 1] - sig[chInIdx][0][i - 1];
925 : }
926 : }
927 : }
928 :
929 : /* Step 1.1, calculate Cx from MDST estimate */
930 1260 : for ( bandIdx = 0; bandIdx < PARAM_MC_MAX_PARAMETER_BANDS; bandIdx++ )
931 : {
932 1200 : set_zero( cx[bandIdx], PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
933 1200 : set_zero( cx_imag[bandIdx], PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
934 : }
935 :
936 60 : set_zero( Nrqq, MAX_OUTPUT_CHANNELS );
937 60 : set_zero( target_ch_ener, MAX_OUTPUT_CHANNELS );
938 :
939 840 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
940 : {
941 780 : set_zero( real_in_buffer, PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS );
942 780 : set_zero( imag_in_buffer, PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS );
943 780 : set_zero( real_buffer, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
944 780 : set_zero( imag_buffer, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
945 :
946 780 : start = hLsSetUpConversion->sfbOffset[bandIdx];
947 780 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
948 780 : num_bands = stop - start;
949 :
950 39180 : for ( i = 0; i < num_bands; i++ )
951 : {
952 38400 : band = start + i;
953 153600 : for ( idx = 0; idx < nchan_transport; idx++ )
954 : {
955 115200 : if ( mct_chan_mode[idx] != MCT_CHAN_MODE_IGNORE )
956 : {
957 115200 : real_in_buffer[i + num_bands * idx] = sig[idx][0][band];
958 115200 : imag_in_buffer[i + num_bands * idx] = mdst[idx][band];
959 : }
960 : }
961 : }
962 :
963 780 : cmplx_matrix_square( real_in_buffer, imag_in_buffer, num_bands, nchan_transport, real_buffer, imag_buffer );
964 :
965 780 : v_add( cx[bandIdx], real_buffer, cx[bandIdx], nchan_transport * nchan_transport );
966 :
967 780 : v_add( cx_imag[bandIdx], imag_buffer, cx_imag[bandIdx], nchan_transport * nchan_transport );
968 : }
969 :
970 840 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
971 : {
972 780 : DMXEne = 0.0f;
973 780 : set_zero( cy, MAX_LS_CHANNELS * MAX_LS_CHANNELS );
974 780 : set_zero( Nrqq, MAX_OUTPUT_CHANNELS );
975 780 : set_zero( target_ch_ener, MAX_OUTPUT_CHANNELS );
976 :
977 : /* Step 1.2, get target channel energies for the transported format, Nrqq calculation */
978 780 : ild_q = hParamMC->icld_q + bandIdx * hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe;
979 :
980 10140 : for ( chInIdx = 0; chInIdx < nchan_transport_format; chInIdx++ )
981 : {
982 9360 : float ref_ener = 0.0f;
983 : int16_t ref_channel_cnt;
984 : int16_t ref_channel_idx;
985 :
986 18720 : for ( ref_channel_cnt = 0; ref_channel_cnt < hParamMC->hMetadataPMC->ild_mapping_conf->num_ref_channels[chInIdx]; ref_channel_cnt++ )
987 : {
988 9360 : ref_channel_idx = hParamMC->hMetadataPMC->ild_mapping_conf->ref_channel_idx[chInIdx][ref_channel_cnt];
989 9360 : ref_ener += cx[bandIdx][ref_channel_idx + ref_channel_idx * nchan_transport];
990 : }
991 :
992 9360 : Nrqq[hParamMC->hMetadataPMC->ild_mapping_conf->ild_index[chInIdx]] = powf( 10.0f, ild_q[chInIdx] / 10.0f ) * hParamMC->hMetadataPMC->ild_factors[chInIdx] * ref_ener;
993 : }
994 :
995 : /* Step 1.3 get target Cy (with dmx matrix from CICPX to MONO/STEREO saved in hParamMC) */
996 2340 : for ( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
997 : {
998 20280 : for ( i = 0; i < nchan_transport_format; i++ )
999 : {
1000 18720 : target_ch_ener[chOutIdx] += hParamMC->ls_conv_dmx_matrix[chOutIdx + i * nchan_out] * Nrqq[i];
1001 : }
1002 1560 : cy[chOutIdx + nchan_out * chOutIdx] = target_ch_ener[chOutIdx];
1003 : }
1004 :
1005 : /* Step 1.4 final target energy for the band would then be the sum over the diagonal of Cy*/
1006 2340 : for ( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
1007 : {
1008 1560 : targetEnergy[bandIdx] += cy[chOutIdx + nchan_out * chOutIdx];
1009 : }
1010 :
1011 : /* Step 2: Calculate DMX ener */
1012 780 : start = hLsSetUpConversion->sfbOffset[bandIdx];
1013 780 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
1014 :
1015 2340 : for ( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
1016 : {
1017 6240 : for ( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
1018 : {
1019 4680 : if ( mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
1020 : {
1021 4680 : dmxCoeff = hLsSetUpConversion->dmxMtx[chInIdx][chOutIdx];
1022 :
1023 : /* Step 1: Compute the target energy and DMX signal (possible since we have all signals in TCX20 resolution) */
1024 4680 : if ( dmxCoeff )
1025 : {
1026 : /* Loop over all the bins in the band */
1027 156720 : for ( binIdx = start; binIdx < stop; binIdx++ )
1028 : {
1029 153600 : tmpDMXSig = dmxCoeff * sig[chInIdx][0][binIdx];
1030 153600 : dmxSignalReal[binIdx] += tmpDMXSig;
1031 :
1032 153600 : tmpDMXSig = dmxCoeff * mdst[chInIdx][binIdx];
1033 153600 : dmxSignalImag[binIdx] += tmpDMXSig;
1034 : }
1035 : }
1036 : }
1037 : }
1038 :
1039 : /* Loop over all the bins in the band */
1040 1560 : DMXEne = 0.0f;
1041 78360 : for ( binIdx = start; binIdx < stop; binIdx++ )
1042 : {
1043 76800 : tmpReal = dmxSignalReal[binIdx];
1044 76800 : tmpImag = dmxSignalImag[binIdx];
1045 :
1046 76800 : DMXEne += tmpReal * tmpReal + tmpImag * tmpImag;
1047 : }
1048 : }
1049 :
1050 780 : dmxEnergy[bandIdx] = DMXEne;
1051 : }
1052 :
1053 : /* Step 3: Peform energy smoothing */
1054 840 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1055 : {
1056 780 : targetEnergy[bandIdx] = LS_OUT_CONV_SMOOTHING_FACTOR * targetEnergy[bandIdx] + ( 1.0f - LS_OUT_CONV_SMOOTHING_FACTOR ) * hLsSetUpConversion->targetEnergyPrev[0][bandIdx];
1057 780 : dmxEnergy[bandIdx] = LS_OUT_CONV_SMOOTHING_FACTOR * dmxEnergy[bandIdx] + ( 1.0f - LS_OUT_CONV_SMOOTHING_FACTOR ) * hLsSetUpConversion->dmxEnergyPrev[0][bandIdx];
1058 780 : hLsSetUpConversion->targetEnergyPrev[0][bandIdx] = targetEnergy[bandIdx];
1059 780 : hLsSetUpConversion->dmxEnergyPrev[0][bandIdx] = dmxEnergy[bandIdx];
1060 : }
1061 :
1062 : /* Step 4: Perform equalization */
1063 240 : for ( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
1064 : {
1065 180 : if ( mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
1066 : {
1067 180 : if ( transform_type[chInIdx][0] == TCX_20 )
1068 : {
1069 : /*TCX20*/
1070 2226 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1071 : {
1072 2067 : start = hLsSetUpConversion->sfbOffset[bandIdx];
1073 2067 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
1074 :
1075 : /*Compute Eq gains */
1076 2067 : ivas_lssetupconversion_computeEQFactor( &targetEnergy[bandIdx], &dmxEnergy[bandIdx], &eqGain );
1077 103827 : for ( binIdx = start; binIdx < stop; binIdx++ )
1078 : {
1079 101760 : x[chInIdx][0][binIdx] *= eqGain;
1080 : }
1081 : }
1082 : }
1083 : else
1084 : {
1085 21 : stop_tcx5 = 0;
1086 294 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1087 : {
1088 273 : start = hLsSetUpConversion->sfbOffset[bandIdx] / 2;
1089 273 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1] / 2;
1090 :
1091 : /*Compute Eq gains */
1092 273 : ivas_lssetupconversion_computeEQFactor( &targetEnergy[bandIdx], &dmxEnergy[bandIdx], &eqGain );
1093 :
1094 819 : for ( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
1095 : {
1096 546 : if ( transform_type[chInIdx][subFrameIdx] == TCX_10 )
1097 : {
1098 : /*TCX10*/
1099 6993 : for ( binIdx = start; binIdx < stop; binIdx++ )
1100 : {
1101 6720 : x[chInIdx][subFrameIdx][binIdx] *= eqGain;
1102 : }
1103 : }
1104 : else
1105 : {
1106 : /* TCX5*/
1107 273 : start_tcx5 = stop_tcx5;
1108 273 : stop_tcx5 = ( stop + 1 ) / 2;
1109 3633 : for ( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
1110 : {
1111 3360 : x[chInIdx][subFrameIdx][binIdx] *= eqGain;
1112 : }
1113 :
1114 3633 : for ( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
1115 : {
1116 3360 : x[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )] *= eqGain;
1117 : }
1118 : }
1119 : }
1120 : }
1121 : }
1122 : }
1123 : }
1124 :
1125 60 : return;
1126 : }
1127 :
1128 :
1129 : /*-------------------------------------------------------------------------
1130 : * ivas_ls_setup_conversion_process_param_mc()
1131 : *
1132 : * LS setup conversion in the CLDFB domain for Parametric MC
1133 : *-------------------------------------------------------------------------*/
1134 :
1135 4080 : void ivas_lssetupconversion_process_param_mc(
1136 : Decoder_Struct *st_ivas, /* i/o: LS setup conversion renderer handle */
1137 : const int16_t num_timeslots,
1138 : float Cldfb_RealBuffer_InOut[MAX_LS_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals */
1139 : float Cldfb_ImagBuffer_InOut[MAX_LS_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals */
1140 : int16_t channel_active[MAX_LS_CHANNELS] /* i : bitmap indicating which output channels are active */
1141 : )
1142 : {
1143 : int16_t slotIdx, chOutIdx, chInIdx, bandIdx;
1144 : int16_t inChannels, outChannels;
1145 : float targetEnergy[MAX_LS_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1146 : float dmxEnergy[MAX_LS_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1147 : float tmpDMXSig, dmxCoeff, tmpReal, tmpImag;
1148 : float EQ;
1149 : float Cldfb_RealBuffer_tmp[MAX_LS_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1150 : float Cldfb_ImagBuffer_tmp[MAX_LS_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1151 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
1152 :
1153 4080 : push_wmops( "LS_Renderer_Process_Param_MC" );
1154 : /* inits */
1155 4080 : inChannels = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe;
1156 4080 : outChannels = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe;
1157 :
1158 4080 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
1159 4080 : EQ = 0.0f;
1160 :
1161 4080 : set_s( channel_active, 0, outChannels );
1162 :
1163 : /* Loop over each time slots and compute dmx for each time slot */
1164 20400 : for ( slotIdx = 0; slotIdx < num_timeslots; slotIdx++ )
1165 : {
1166 : /* copy buffers */
1167 114240 : for ( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
1168 : {
1169 97920 : mvr2r( Cldfb_RealBuffer_InOut[chInIdx][slotIdx], Cldfb_RealBuffer_tmp[chInIdx], CLDFB_NO_CHANNELS_MAX );
1170 97920 : mvr2r( Cldfb_ImagBuffer_InOut[chInIdx][slotIdx], Cldfb_ImagBuffer_tmp[chInIdx], CLDFB_NO_CHANNELS_MAX );
1171 : }
1172 : /* set the buffers to zero */
1173 212160 : for ( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1174 : {
1175 195840 : set_f( Cldfb_RealBuffer_InOut[chOutIdx][slotIdx], 0.0f, CLDFB_NO_CHANNELS_MAX );
1176 195840 : set_f( Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx], 0.0f, CLDFB_NO_CHANNELS_MAX );
1177 :
1178 195840 : set_f( dmxEnergy[chOutIdx], 0.0f, CLDFB_NO_CHANNELS_MAX );
1179 195840 : set_f( targetEnergy[chOutIdx], 0.0f, CLDFB_NO_CHANNELS_MAX );
1180 : }
1181 :
1182 : /* Compute the target energy and DMX signal */
1183 212160 : for ( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1184 : {
1185 1370880 : for ( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
1186 : {
1187 1175040 : dmxCoeff = hLsSetUpConversion->dmxMtx[chInIdx][chOutIdx];
1188 1175040 : if ( dmxCoeff == 0.0f )
1189 : {
1190 1077120 : continue;
1191 : }
1192 : else
1193 : {
1194 97920 : channel_active[chOutIdx] |= 1;
1195 5973120 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1196 : {
1197 5875200 : tmpDMXSig = dmxCoeff * Cldfb_RealBuffer_tmp[chInIdx][bandIdx];
1198 5875200 : Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx] += tmpDMXSig;
1199 5875200 : targetEnergy[chOutIdx][bandIdx] += tmpDMXSig * tmpDMXSig;
1200 :
1201 5875200 : tmpDMXSig = dmxCoeff * Cldfb_ImagBuffer_tmp[chInIdx][bandIdx];
1202 5875200 : Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx] += tmpDMXSig;
1203 5875200 : targetEnergy[chOutIdx][bandIdx] += tmpDMXSig * tmpDMXSig;
1204 : }
1205 : }
1206 : }
1207 : }
1208 :
1209 : /* Compute the DMX energy */
1210 212160 : for ( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1211 : {
1212 195840 : if ( channel_active[chOutIdx] )
1213 : {
1214 5973120 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1215 : {
1216 5875200 : tmpReal = Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx];
1217 5875200 : tmpImag = Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx];
1218 :
1219 5875200 : dmxEnergy[chOutIdx][bandIdx] = tmpReal * tmpReal + tmpImag * tmpImag;
1220 : }
1221 : }
1222 : }
1223 :
1224 : /* Peform energy smoothing */
1225 212160 : for ( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1226 : {
1227 195840 : if ( channel_active[chOutIdx] )
1228 : {
1229 5973120 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1230 : {
1231 5875200 : targetEnergy[chOutIdx][bandIdx] = LS_OUT_CONV_SMOOTHING_FACTOR * targetEnergy[chOutIdx][bandIdx] + ( 1 - LS_OUT_CONV_SMOOTHING_FACTOR ) * hLsSetUpConversion->targetEnergyPrev[chOutIdx][bandIdx];
1232 5875200 : dmxEnergy[chOutIdx][bandIdx] = LS_OUT_CONV_SMOOTHING_FACTOR * dmxEnergy[chOutIdx][bandIdx] + ( 1 - LS_OUT_CONV_SMOOTHING_FACTOR ) * hLsSetUpConversion->dmxEnergyPrev[chOutIdx][bandIdx];
1233 5875200 : hLsSetUpConversion->targetEnergyPrev[chOutIdx][bandIdx] = targetEnergy[chOutIdx][bandIdx];
1234 5875200 : hLsSetUpConversion->dmxEnergyPrev[chOutIdx][bandIdx] = dmxEnergy[chOutIdx][bandIdx];
1235 : }
1236 : }
1237 : }
1238 :
1239 : /* Compute and perform equalization */
1240 212160 : for ( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1241 : {
1242 195840 : if ( channel_active[chOutIdx] )
1243 : {
1244 5973120 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1245 : {
1246 5875200 : ivas_lssetupconversion_computeEQFactor( &targetEnergy[chOutIdx][bandIdx], &dmxEnergy[chOutIdx][bandIdx], &EQ );
1247 5875200 : Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx] *= EQ;
1248 5875200 : Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx] *= EQ;
1249 : }
1250 : }
1251 : }
1252 : }
1253 :
1254 4080 : pop_wmops();
1255 4080 : return;
1256 : }
|