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 : #ifdef FIX_1314_STEREO_TO_EXT
313 : ivas_error error;
314 : #endif
315 :
316 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 ) )
317 : {
318 3 : paramUpmixMonoStereo = TRUE;
319 : }
320 : else
321 : {
322 375 : paramUpmixMonoStereo = FALSE;
323 : }
324 378 : output_Fs = st_ivas->hDecoderConfig->output_Fs;
325 378 : outChannels = st_ivas->hDecoderConfig->nchan_out;
326 378 : output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC );
327 :
328 : /* Allocate memory to the handle */
329 378 : if ( ( hLsSetUpConversion = (LSSETUP_CONVERSION_HANDLE) malloc( sizeof( LSSETUP_CONVERSION_STRUCT ) ) ) == NULL )
330 : {
331 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
332 : }
333 :
334 378 : assert( outChannels <= MAX_OUTPUT_CHANNELS );
335 :
336 378 : if ( st_ivas->renderer_type == RENDERER_MC_PARAMMC )
337 : {
338 171 : inChannels = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe;
339 171 : hLsSetUpConversion->sfbCnt = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f );
340 2145 : for ( chIdx = 0; chIdx < outChannels; chIdx++ )
341 : {
342 1974 : if ( ( hLsSetUpConversion->targetEnergyPrev[chIdx] = (float *) malloc( ( hLsSetUpConversion->sfbCnt ) * sizeof( float ) ) ) == NULL )
343 : {
344 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
345 : }
346 1974 : if ( ( hLsSetUpConversion->dmxEnergyPrev[chIdx] = (float *) malloc( ( hLsSetUpConversion->sfbCnt ) * sizeof( float ) ) ) == NULL )
347 : {
348 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
349 : }
350 1974 : set_f( hLsSetUpConversion->targetEnergyPrev[chIdx], 0.0f, hLsSetUpConversion->sfbCnt );
351 1974 : set_f( hLsSetUpConversion->dmxEnergyPrev[chIdx], 0.0f, hLsSetUpConversion->sfbCnt );
352 : }
353 933 : for ( ; chIdx < MAX_CICP_CHANNELS; chIdx++ )
354 : {
355 762 : hLsSetUpConversion->targetEnergyPrev[chIdx] = NULL;
356 762 : hLsSetUpConversion->dmxEnergyPrev[chIdx] = NULL;
357 : }
358 : }
359 : else
360 : {
361 207 : if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
362 : {
363 3 : if ( paramUpmixMonoStereo == TRUE )
364 : {
365 3 : inChannels = audioCfg2channels( IVAS_AUDIO_CONFIG_5_1_2 );
366 : }
367 : else
368 : {
369 0 : inChannels = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe;
370 : }
371 : }
372 : else
373 : {
374 204 : inChannels = st_ivas->nchan_transport;
375 : }
376 :
377 : /*Initialization of MDCT bands with TCX20 resolution */
378 207 : ivas_lssetupconversion_mdct_init_bands( output_frame, TCX_20_CORE, &hLsSetUpConversion->sfbOffset[0], &hLsSetUpConversion->sfbCnt );
379 207 : if ( ( hLsSetUpConversion->targetEnergyPrev[0] = (float *) malloc( ( MAX_SFB + 2 ) * sizeof( float ) ) ) == NULL )
380 : {
381 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
382 : }
383 207 : if ( ( hLsSetUpConversion->dmxEnergyPrev[0] = (float *) malloc( ( MAX_SFB + 2 ) * sizeof( float ) ) ) == NULL )
384 : {
385 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
386 : }
387 :
388 3312 : for ( chIdx = 1; chIdx < MAX_CICP_CHANNELS; chIdx++ )
389 : {
390 3105 : hLsSetUpConversion->targetEnergyPrev[chIdx] = NULL;
391 3105 : hLsSetUpConversion->dmxEnergyPrev[chIdx] = NULL;
392 : }
393 207 : set_f( hLsSetUpConversion->targetEnergyPrev[0], 0.0f, MAX_SFB + 2 );
394 207 : set_f( hLsSetUpConversion->dmxEnergyPrev[0], 0.0f, MAX_SFB + 2 );
395 : }
396 :
397 :
398 : /* Initialize the DMX conversion matrix */
399 2730 : for ( chIdx = 0; chIdx < inChannels; chIdx++ )
400 : {
401 : /* Allocate memory depending on the number of output channels */
402 2352 : if ( ( hLsSetUpConversion->dmxMtx[chIdx] = (float *) malloc( outChannels * sizeof( float ) ) ) == NULL )
403 : {
404 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for temp dmx matrix \n" ) );
405 : }
406 2352 : set_zero( hLsSetUpConversion->dmxMtx[chIdx], outChannels );
407 : }
408 :
409 4074 : for ( ; chIdx < MAX_CICP_CHANNELS; chIdx++ )
410 : {
411 3696 : hLsSetUpConversion->dmxMtx[chIdx] = NULL;
412 : }
413 :
414 378 : if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM )
415 : {
416 3 : get_custom_ls_conversion_matrix( st_ivas->hEFAPdata, st_ivas->hTransSetup, st_ivas->hLsSetupCustom, hLsSetUpConversion );
417 : }
418 : else
419 : {
420 375 : if ( st_ivas->transport_config != IVAS_AUDIO_CONFIG_INVALID )
421 : {
422 375 : if ( paramUpmixMonoStereo == TRUE )
423 : {
424 : #ifdef FIX_1314_STEREO_TO_EXT
425 3 : if ( ( error = get_ls_conversion_matrix( hLsSetUpConversion, IVAS_AUDIO_CONFIG_5_1_2, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
426 : {
427 0 : return error;
428 : }
429 : #else
430 : get_ls_conversion_matrix( hLsSetUpConversion, IVAS_AUDIO_CONFIG_5_1_2, st_ivas->hDecoderConfig->output_config );
431 : #endif
432 : }
433 : else
434 : {
435 : #ifdef FIX_1314_STEREO_TO_EXT
436 372 : if ( ( error = get_ls_conversion_matrix( hLsSetUpConversion, st_ivas->transport_config, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
437 : {
438 0 : return error;
439 : }
440 : #else
441 : get_ls_conversion_matrix( hLsSetUpConversion, st_ivas->transport_config, st_ivas->hDecoderConfig->output_config );
442 : #endif
443 : }
444 : }
445 : else
446 : {
447 : #ifdef FIX_1314_STEREO_TO_EXT
448 0 : if ( ( error = get_ls_conversion_matrix( hLsSetUpConversion, st_ivas->intern_config, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
449 : {
450 0 : return error;
451 : }
452 : #else
453 : get_ls_conversion_matrix( hLsSetUpConversion, st_ivas->intern_config, st_ivas->hDecoderConfig->output_config );
454 : #endif
455 : }
456 : }
457 :
458 378 : st_ivas->hLsSetUpConversion = hLsSetUpConversion;
459 :
460 378 : return IVAS_ERR_OK;
461 : }
462 :
463 :
464 : /*-------------------------------------------------------------------------
465 : * ivas_ls_setup_conversion_close()
466 : *
467 : * Close the LS configuration Conversion Module
468 : *-------------------------------------------------------------------------*/
469 :
470 2649 : void ivas_ls_setup_conversion_close(
471 : LSSETUP_CONVERSION_HANDLE *hLsSetUpConversion /* i/o: LS converter handle */
472 : )
473 : {
474 : int16_t idx;
475 :
476 2649 : if ( hLsSetUpConversion == NULL || *hLsSetUpConversion == NULL )
477 : {
478 2271 : return;
479 : }
480 :
481 6426 : for ( idx = 0; idx < MAX_CICP_CHANNELS; idx++ )
482 : {
483 6048 : if ( ( *hLsSetUpConversion )->dmxMtx[idx] != NULL )
484 : {
485 2352 : free( ( *hLsSetUpConversion )->dmxMtx[idx] );
486 2352 : ( *hLsSetUpConversion )->dmxMtx[idx] = NULL;
487 : }
488 :
489 6048 : if ( ( *hLsSetUpConversion )->targetEnergyPrev[idx] != NULL )
490 : {
491 2181 : free( ( *hLsSetUpConversion )->targetEnergyPrev[idx] );
492 2181 : ( *hLsSetUpConversion )->targetEnergyPrev[idx] = NULL;
493 : }
494 :
495 6048 : if ( ( *hLsSetUpConversion )->dmxEnergyPrev[idx] != NULL )
496 : {
497 2181 : free( ( *hLsSetUpConversion )->dmxEnergyPrev[idx] );
498 2181 : ( *hLsSetUpConversion )->dmxEnergyPrev[idx] = NULL;
499 : }
500 : }
501 :
502 378 : free( *hLsSetUpConversion );
503 378 : *hLsSetUpConversion = NULL;
504 :
505 378 : return;
506 : }
507 :
508 :
509 : /*-------------------------------------------------------------------------
510 : * ivas_ls_setup_conversion()
511 : *
512 : * Convert (downmix or upmix) the input LS configuration
513 : * to output LS configuration in time domain
514 : *-------------------------------------------------------------------------*/
515 :
516 36242 : void ivas_ls_setup_conversion(
517 : Decoder_Struct *st_ivas, /* i : IVAS decoder structure */
518 : const int16_t input_chans, /* i : number of input channels to the renderer */
519 : const int16_t output_frame, /* i : frame length */
520 : float *input[], /* i : LS input/output synthesis signal */
521 : float *output[] /* i/o: LS input/output synthesis signal */
522 : )
523 : {
524 : int16_t chInIdx, chOutIdx, idx;
525 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
526 : float dmxCoeff, tmpVal;
527 : float output_tmp[MAX_OUTPUT_CHANNELS][L_FRAME48k];
528 :
529 36242 : push_wmops( "LS_Renderer" );
530 :
531 36242 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
532 :
533 404376 : for ( chOutIdx = 0; chOutIdx < st_ivas->hDecoderConfig->nchan_out; chOutIdx++ )
534 : {
535 368134 : set_zero( output_tmp[chOutIdx], output_frame );
536 2577778 : for ( chInIdx = 0; chInIdx < input_chans; chInIdx++ )
537 : {
538 2209644 : dmxCoeff = hLsSetUpConversion->dmxMtx[chInIdx][chOutIdx];
539 :
540 2209644 : if ( dmxCoeff == 0.f )
541 : {
542 1860478 : continue;
543 : }
544 349166 : else if ( dmxCoeff == 1.f )
545 : {
546 74664504 : for ( idx = 0; idx < output_frame; idx++ )
547 : {
548 74498760 : output_tmp[chOutIdx][idx] += input[chInIdx][idx];
549 : }
550 : }
551 : else
552 : {
553 99007742 : for ( idx = 0; idx < output_frame; idx++ )
554 : {
555 98824320 : tmpVal = dmxCoeff * input[chInIdx][idx];
556 98824320 : output_tmp[chOutIdx][idx] += tmpVal;
557 : }
558 : }
559 : }
560 : }
561 :
562 : /* Copy to output buffer */
563 404376 : for ( chOutIdx = 0; chOutIdx < st_ivas->hDecoderConfig->nchan_out; chOutIdx++ )
564 : {
565 368134 : mvr2r( output_tmp[chOutIdx], output[chOutIdx], output_frame );
566 : }
567 :
568 36242 : pop_wmops();
569 :
570 36242 : return;
571 : }
572 :
573 :
574 : /*-------------------------------------------------------------------------
575 : * ivas_ls_setup_conversion_process_mdct()
576 : *
577 : * Equalization in MDCT Domain
578 : *-------------------------------------------------------------------------*/
579 :
580 19509 : void ivas_ls_setup_conversion_process_mdct(
581 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
582 : float *output[] /* i/o: output synthesis signal */
583 : )
584 : {
585 : /* Declaration of all required variables */
586 : int16_t i, bandIdx, chInIdx, chOutIdx, cpe_idx, subFrameIdx, binIdx, idx;
587 : int16_t inChannels, outChannels, num_CPE;
588 : int16_t transform_type[MAX_CICP_CHANNELS][2];
589 : int16_t frameSize;
590 : float targetEnergy[MAX_SFB + 2], dmxEnergy[MAX_SFB + 2];
591 : float dmxCoeff;
592 : float dmxSignalReal[L_FRAME48k], dmxSignalImag[L_FRAME48k];
593 : float eqGain;
594 : float *sig[NB_DIV], *pTmp[NB_DIV], *x[MAX_CICP_CHANNELS][NB_DIV];
595 : float mdst[L_FRAME48k];
596 : float convertRes[L_FRAME48k];
597 : int16_t start, stop, start_tcx5, stop_tcx5;
598 : int16_t mct_chan_mode[MAX_CICP_CHANNELS];
599 :
600 : /* Declare all handles */
601 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
602 : CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS];
603 :
604 19509 : push_wmops( "LS_Renderer_MDCT" );
605 :
606 : /* Assign all the declared variables */
607 19509 : inChannels = st_ivas->nchan_transport;
608 19509 : outChannels = st_ivas->hDecoderConfig->nchan_out;
609 19509 : num_CPE = st_ivas->nCPE;
610 :
611 : /* Assign output pointer to variable x */
612 137163 : for ( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
613 : {
614 117654 : x[chInIdx][0] = output[chInIdx];
615 117654 : x[chInIdx][1] = output[chInIdx] + ( L_FRAME48k / 2 );
616 : }
617 :
618 : /* Assign all the declared handles*/
619 19509 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
620 78336 : for ( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
621 : {
622 58827 : hCPE[cpe_idx] = st_ivas->hCPE[cpe_idx];
623 : }
624 :
625 : /* Get the core type */
626 78336 : for ( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
627 : {
628 176481 : for ( idx = 0; idx < CPE_CHANNELS; idx++ )
629 : {
630 : /* get the channel index */
631 117654 : chInIdx = cpe_idx * CPE_CHANNELS + idx;
632 117654 : assert( chInIdx <= inChannels );
633 117654 : transform_type[chInIdx][0] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[0];
634 117654 : transform_type[chInIdx][1] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[1];
635 117654 : mct_chan_mode[chInIdx] = hCPE[cpe_idx]->hCoreCoder[idx]->mct_chan_mode;
636 : }
637 : }
638 :
639 : /* set overall frequency resolution of (sub)frame to maximum of (sub)frame, requires conversion if both channels are not the same */
640 19509 : frameSize = hLsSetUpConversion->sfbOffset[hLsSetUpConversion->sfbCnt];
641 :
642 19509 : set_zero( targetEnergy, MAX_SFB + 2 );
643 19509 : set_zero( dmxEnergy, MAX_SFB + 2 );
644 :
645 171447 : for ( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
646 : {
647 : /* Step 0: Set the buffers to zero */
648 151938 : set_zero( dmxSignalReal, frameSize );
649 151938 : set_zero( dmxSignalImag, frameSize );
650 :
651 1064766 : for ( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
652 : {
653 912828 : dmxCoeff = hLsSetUpConversion->dmxMtx[chInIdx][chOutIdx];
654 :
655 912828 : if ( chInIdx != LFE_CHANNEL && mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
656 : {
657 : /* Step 1: Compute the target energy and DMX signal (possible since we have all signals in TCX20 resolution) */
658 599793 : if ( dmxCoeff )
659 : {
660 : float tmpDMXSig, targetEne;
661 :
662 : /* Convert the signal resolution to TCX20 */
663 : /* initially, set pointers to input; if conversion occurs in (sub)frame, set to convertRes */
664 86460 : sig[0] = pTmp[0] = x[chInIdx][0];
665 86460 : sig[1] = pTmp[1] = x[chInIdx][1];
666 :
667 : /* convert (sub)frames to higher frequency resolution */
668 86460 : if ( transform_type[chInIdx][0] != TCX_20 )
669 : {
670 4545 : for ( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
671 : {
672 3030 : if ( transform_type[chInIdx][subFrameIdx] == TCX_5 )
673 : {
674 : /* subframe is TCX5, but TCX10 or TCX20 in other channel -> convert channel with TCX5 to TCX10 resolution */
675 1602 : pTmp[subFrameIdx] = sig[subFrameIdx] = convertRes + subFrameIdx * frameSize / 2;
676 1602 : convert_coeffs_to_higher_res( x[chInIdx][subFrameIdx], x[chInIdx][subFrameIdx] + frameSize / 4, pTmp[subFrameIdx], frameSize / 4 );
677 : }
678 : }
679 :
680 : /* convert channel with TCX10 to TCX20 resolution */
681 1515 : sig[0] = convertRes;
682 1515 : convert_coeffs_to_higher_res( pTmp[0], pTmp[1], sig[0], frameSize / 2 );
683 : }
684 :
685 : /* MDST estimate */
686 86460 : mdst[0] = mdst[frameSize - 1] = 0.f;
687 82531140 : for ( i = 1; i < frameSize - 1; i++ )
688 : {
689 82444680 : mdst[i] = sig[0][i + 1] - sig[0][i - 1];
690 : }
691 :
692 5705160 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
693 : {
694 5618700 : start = hLsSetUpConversion->sfbOffset[bandIdx];
695 5618700 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
696 :
697 5618700 : targetEne = 0.0f;
698 :
699 : /* Loop over all the bins in the band */
700 88236300 : for ( binIdx = start; binIdx < stop; binIdx++ )
701 : {
702 82617600 : tmpDMXSig = dmxCoeff * sig[0][binIdx];
703 82617600 : dmxSignalReal[binIdx] += tmpDMXSig;
704 82617600 : targetEne += tmpDMXSig * tmpDMXSig;
705 :
706 82617600 : tmpDMXSig = dmxCoeff * mdst[binIdx];
707 82617600 : dmxSignalImag[binIdx] += tmpDMXSig;
708 82617600 : targetEne += tmpDMXSig * tmpDMXSig;
709 : }
710 5618700 : targetEnergy[bandIdx] += targetEne;
711 : } /* end of band loop */
712 : }
713 : }
714 : } /* end of chInIdx loop */
715 :
716 10027668 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
717 : {
718 : float tmpReal, tmpImag, DMXEne;
719 :
720 9875730 : start = hLsSetUpConversion->sfbOffset[bandIdx];
721 9875730 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
722 :
723 : /* Loop over all the bins in the band */
724 9875730 : DMXEne = 0.0f;
725 155659410 : for ( binIdx = start; binIdx < stop; binIdx++ )
726 : {
727 145783680 : tmpReal = dmxSignalReal[binIdx];
728 145783680 : tmpImag = dmxSignalImag[binIdx];
729 :
730 145783680 : DMXEne += tmpReal * tmpReal + tmpImag * tmpImag;
731 : }
732 9875730 : dmxEnergy[bandIdx] += DMXEne;
733 : }
734 : } /* end of out channel loop */
735 :
736 : /* Step 3: Peform energy smoothing */
737 1287474 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
738 : {
739 1267965 : targetEnergy[bandIdx] = LS_OUT_CONV_SMOOTHING_FACTOR * targetEnergy[bandIdx] + ( 1.0f - LS_OUT_CONV_SMOOTHING_FACTOR ) * hLsSetUpConversion->targetEnergyPrev[0][bandIdx];
740 1267965 : dmxEnergy[bandIdx] = LS_OUT_CONV_SMOOTHING_FACTOR * dmxEnergy[bandIdx] + ( 1.0f - LS_OUT_CONV_SMOOTHING_FACTOR ) * hLsSetUpConversion->dmxEnergyPrev[0][bandIdx];
741 1267965 : hLsSetUpConversion->targetEnergyPrev[0][bandIdx] = targetEnergy[bandIdx];
742 1267965 : hLsSetUpConversion->dmxEnergyPrev[0][bandIdx] = dmxEnergy[bandIdx];
743 : }
744 :
745 : /* Step 4: Perform equalization */
746 137163 : for ( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
747 : {
748 117654 : if ( chInIdx != LFE_CHANNEL && mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
749 : {
750 77466 : if ( transform_type[chInIdx][0] == TCX_20 )
751 : {
752 : /* TCX20 */
753 5017128 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
754 : {
755 4941096 : start = hLsSetUpConversion->sfbOffset[bandIdx];
756 4941096 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
757 :
758 : /* Compute Eq gains */
759 4941096 : ivas_lssetupconversion_computeEQFactor( &targetEnergy[bandIdx], &dmxEnergy[bandIdx], &eqGain );
760 77616936 : for ( binIdx = start; binIdx < stop; binIdx++ )
761 : {
762 72675840 : x[chInIdx][0][binIdx] *= eqGain;
763 : }
764 : }
765 : }
766 : else
767 : {
768 1434 : stop_tcx5 = 0;
769 94548 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
770 : {
771 93114 : start = hLsSetUpConversion->sfbOffset[bandIdx] / 2;
772 93114 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1] / 2;
773 :
774 : /* Compute Eq gains */
775 93114 : ivas_lssetupconversion_computeEQFactor( &targetEnergy[bandIdx], &dmxEnergy[bandIdx], &eqGain );
776 :
777 279342 : for ( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
778 : {
779 186228 : if ( transform_type[chInIdx][subFrameIdx] == TCX_10 )
780 : {
781 : /* TCX10 */
782 723564 : for ( binIdx = start; binIdx < stop; binIdx++ )
783 : {
784 635520 : x[chInIdx][subFrameIdx][binIdx] *= eqGain;
785 : }
786 : }
787 : else
788 : {
789 : /* TCX5*/
790 98184 : start_tcx5 = stop_tcx5;
791 98184 : stop_tcx5 = ( stop + 1 ) / 2;
792 :
793 434664 : for ( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
794 : {
795 336480 : x[chInIdx][subFrameIdx][binIdx] *= eqGain;
796 336480 : x[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )] *= eqGain;
797 : }
798 : }
799 : }
800 : }
801 : }
802 : }
803 : }
804 :
805 19509 : pop_wmops();
806 19509 : return;
807 : }
808 :
809 :
810 : /*-------------------------------------------------------------------------
811 : * ivas_ls_setup_conversion_process_mdct_param_mc()
812 : *
813 : * Equalization in MDCT Domain
814 : *-------------------------------------------------------------------------*/
815 :
816 60 : void ivas_ls_setup_conversion_process_mdct_param_mc(
817 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
818 : float *x[][NB_DIV] /* i/o: output synthesis signal */
819 : )
820 : {
821 : /* Declaration of all required variables */
822 : int16_t i;
823 : int16_t idx;
824 : int16_t nchan_transport, nchan_out, nchan_transport_format;
825 : int16_t chInIdx, chOutIdx, cpe_idx, subFrameIdx, binIdx;
826 : int16_t band, bandIdx, num_bands;
827 :
828 : int16_t num_CPE;
829 : int16_t transform_type[MAX_CICP_CHANNELS][2];
830 : int16_t frameSize;
831 :
832 : float targetEnergy[MAX_SFB + 2], dmxEnergy[MAX_SFB + 2];
833 : float eqGain;
834 : float *sig[MAX_CICP_CHANNELS][NB_DIV], *pTmp[NB_DIV];
835 : float mdst[MAX_CICP_CHANNELS][L_FRAME48k];
836 : float convertRes[MAX_CICP_CHANNELS][L_FRAME48k];
837 : int16_t start, stop, start_tcx5, stop_tcx5;
838 : int16_t mct_chan_mode[MAX_CICP_CHANNELS];
839 :
840 : float cx[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
841 : float cx_imag[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
842 : float cy[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS];
843 : float real_in_buffer[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS];
844 : float imag_in_buffer[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS];
845 : float real_buffer[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
846 : float imag_buffer[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
847 :
848 : float Nrqq[MAX_OUTPUT_CHANNELS];
849 : float target_ch_ener[MAX_OUTPUT_CHANNELS];
850 : float *ild_q;
851 :
852 : float DMXEne;
853 : float dmxCoeff;
854 : float dmxSignalReal[L_FRAME48k], dmxSignalImag[L_FRAME48k];
855 :
856 : float tmpReal, tmpImag;
857 : float tmpDMXSig;
858 :
859 : /* Declare all handles */
860 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
861 : CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS];
862 : PARAM_MC_DEC_HANDLE hParamMC;
863 :
864 : /* Step 0: Set the buffers to zero */
865 60 : set_zero( dmxSignalReal, L_FRAME48k );
866 60 : set_zero( dmxSignalImag, L_FRAME48k );
867 :
868 : /* Assign all the declared variables */
869 60 : nchan_transport = st_ivas->nchan_transport;
870 60 : nchan_out = st_ivas->hDecoderConfig->nchan_out;
871 60 : num_CPE = st_ivas->nCPE;
872 60 : nchan_transport_format = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe;
873 :
874 : /* Assign all the declared handles*/
875 60 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
876 180 : for ( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
877 : {
878 120 : hCPE[cpe_idx] = st_ivas->hCPE[cpe_idx];
879 : }
880 60 : hParamMC = st_ivas->hParamMC;
881 :
882 : /* Get the core type */
883 180 : for ( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
884 : {
885 360 : for ( idx = 0; idx < CPE_CHANNELS; idx++ )
886 : {
887 : /* get the channel index */
888 240 : chInIdx = cpe_idx * CPE_CHANNELS + idx;
889 240 : assert( chInIdx <= nchan_transport );
890 240 : transform_type[chInIdx][0] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[0];
891 240 : transform_type[chInIdx][1] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[1];
892 240 : mct_chan_mode[chInIdx] = hCPE[cpe_idx]->hCoreCoder[idx]->mct_chan_mode;
893 : }
894 : }
895 :
896 : /* set overall frequency resolution of (sub)frame to maximum of (sub)frame, requires conversion if both channels are not the same */
897 60 : frameSize = hLsSetUpConversion->sfbOffset[hLsSetUpConversion->sfbCnt];
898 :
899 60 : set_zero( targetEnergy, MAX_SFB + 2 );
900 60 : set_zero( dmxEnergy, MAX_SFB + 2 );
901 :
902 240 : for ( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
903 : {
904 180 : if ( mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
905 : {
906 : /* initially, set pointers to input; if conversion occurs in (sub)frame, set to convertRes */
907 180 : sig[chInIdx][0] = pTmp[0] = x[chInIdx][0];
908 180 : sig[chInIdx][1] = pTmp[1] = x[chInIdx][1];
909 :
910 : /* convert (sub)frames to higher frequency resolution */
911 180 : if ( transform_type[chInIdx][0] != TCX_20 )
912 : {
913 63 : for ( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
914 : {
915 42 : if ( transform_type[chInIdx][subFrameIdx] == TCX_5 )
916 : {
917 : /* subframe is TCX5, but TCX10 or TCX20 in other channel -> convert channel with TCX5 to TCX10 resolution */
918 21 : pTmp[subFrameIdx] = sig[chInIdx][subFrameIdx] = convertRes[chInIdx] + subFrameIdx * frameSize / 2;
919 21 : convert_coeffs_to_higher_res( x[chInIdx][subFrameIdx], x[chInIdx][subFrameIdx] + frameSize / 4, pTmp[subFrameIdx], frameSize / 4 );
920 : }
921 : }
922 :
923 : /* convert channel with TCX10 to TCX20 resolution */
924 21 : sig[chInIdx][0] = convertRes[chInIdx];
925 21 : convert_coeffs_to_higher_res( pTmp[0], pTmp[1], sig[chInIdx][0], frameSize / 2 );
926 : }
927 : }
928 : }
929 :
930 : /* precalculate MDST estimate */
931 240 : for ( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
932 : {
933 180 : if ( mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
934 : {
935 180 : mdst[chInIdx][0] = mdst[chInIdx][frameSize - 1] = 0.f;
936 115020 : for ( i = 1; i < frameSize - 1; i++ )
937 : {
938 114840 : mdst[chInIdx][i] = sig[chInIdx][0][i + 1] - sig[chInIdx][0][i - 1];
939 : }
940 : }
941 : }
942 :
943 : /* Step 1.1, calculate Cx from MDST estimate */
944 1260 : for ( bandIdx = 0; bandIdx < PARAM_MC_MAX_PARAMETER_BANDS; bandIdx++ )
945 : {
946 1200 : set_zero( cx[bandIdx], PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
947 1200 : set_zero( cx_imag[bandIdx], PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
948 : }
949 :
950 60 : set_zero( Nrqq, MAX_OUTPUT_CHANNELS );
951 60 : set_zero( target_ch_ener, MAX_OUTPUT_CHANNELS );
952 :
953 840 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
954 : {
955 780 : set_zero( real_in_buffer, PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS );
956 780 : set_zero( imag_in_buffer, PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS );
957 780 : set_zero( real_buffer, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
958 780 : set_zero( imag_buffer, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
959 :
960 780 : start = hLsSetUpConversion->sfbOffset[bandIdx];
961 780 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
962 780 : num_bands = stop - start;
963 :
964 39180 : for ( i = 0; i < num_bands; i++ )
965 : {
966 38400 : band = start + i;
967 153600 : for ( idx = 0; idx < nchan_transport; idx++ )
968 : {
969 115200 : if ( mct_chan_mode[idx] != MCT_CHAN_MODE_IGNORE )
970 : {
971 115200 : real_in_buffer[i + num_bands * idx] = sig[idx][0][band];
972 115200 : imag_in_buffer[i + num_bands * idx] = mdst[idx][band];
973 : }
974 : }
975 : }
976 :
977 780 : cmplx_matrix_square( real_in_buffer, imag_in_buffer, num_bands, nchan_transport, real_buffer, imag_buffer );
978 :
979 780 : v_add( cx[bandIdx], real_buffer, cx[bandIdx], nchan_transport * nchan_transport );
980 :
981 780 : v_add( cx_imag[bandIdx], imag_buffer, cx_imag[bandIdx], nchan_transport * nchan_transport );
982 : }
983 :
984 840 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
985 : {
986 780 : DMXEne = 0.0f;
987 780 : set_zero( cy, MAX_CICP_CHANNELS * MAX_CICP_CHANNELS );
988 780 : set_zero( Nrqq, MAX_OUTPUT_CHANNELS );
989 780 : set_zero( target_ch_ener, MAX_OUTPUT_CHANNELS );
990 :
991 : /* Step 1.2, get target channel energies for the transported format, Nrqq calculation */
992 780 : ild_q = hParamMC->icld_q + bandIdx * hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe;
993 :
994 10140 : for ( chInIdx = 0; chInIdx < nchan_transport_format; chInIdx++ )
995 : {
996 9360 : float ref_ener = 0.0f;
997 : int16_t ref_channel_cnt;
998 : int16_t ref_channel_idx;
999 :
1000 18720 : for ( ref_channel_cnt = 0; ref_channel_cnt < hParamMC->hMetadataPMC->ild_mapping_conf->num_ref_channels[chInIdx]; ref_channel_cnt++ )
1001 : {
1002 9360 : ref_channel_idx = hParamMC->hMetadataPMC->ild_mapping_conf->ref_channel_idx[chInIdx][ref_channel_cnt];
1003 9360 : ref_ener += cx[bandIdx][ref_channel_idx + ref_channel_idx * nchan_transport];
1004 : }
1005 :
1006 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;
1007 : }
1008 :
1009 : /* Step 1.3 get target Cy (with dmx matrix from CICPX to MONO/STEREO saved in hParamMC) */
1010 2340 : for ( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
1011 : {
1012 20280 : for ( i = 0; i < nchan_transport_format; i++ )
1013 : {
1014 18720 : target_ch_ener[chOutIdx] += hParamMC->ls_conv_dmx_matrix[chOutIdx + i * nchan_out] * Nrqq[i];
1015 : }
1016 1560 : cy[chOutIdx + nchan_out * chOutIdx] = target_ch_ener[chOutIdx];
1017 : }
1018 :
1019 : /* Step 1.4 final target energy for the band would then be the sum over the diagonal of Cy*/
1020 2340 : for ( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
1021 : {
1022 1560 : targetEnergy[bandIdx] += cy[chOutIdx + nchan_out * chOutIdx];
1023 : }
1024 :
1025 : /* Step 2: Calculate DMX ener */
1026 780 : start = hLsSetUpConversion->sfbOffset[bandIdx];
1027 780 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
1028 :
1029 2340 : for ( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
1030 : {
1031 6240 : for ( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
1032 : {
1033 4680 : if ( mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
1034 : {
1035 4680 : dmxCoeff = hLsSetUpConversion->dmxMtx[chInIdx][chOutIdx];
1036 :
1037 : /* Step 1: Compute the target energy and DMX signal (possible since we have all signals in TCX20 resolution) */
1038 4680 : if ( dmxCoeff )
1039 : {
1040 : /* Loop over all the bins in the band */
1041 156720 : for ( binIdx = start; binIdx < stop; binIdx++ )
1042 : {
1043 153600 : tmpDMXSig = dmxCoeff * sig[chInIdx][0][binIdx];
1044 153600 : dmxSignalReal[binIdx] += tmpDMXSig;
1045 :
1046 153600 : tmpDMXSig = dmxCoeff * mdst[chInIdx][binIdx];
1047 153600 : dmxSignalImag[binIdx] += tmpDMXSig;
1048 : }
1049 : }
1050 : }
1051 : }
1052 :
1053 : /* Loop over all the bins in the band */
1054 1560 : DMXEne = 0.0f;
1055 78360 : for ( binIdx = start; binIdx < stop; binIdx++ )
1056 : {
1057 76800 : tmpReal = dmxSignalReal[binIdx];
1058 76800 : tmpImag = dmxSignalImag[binIdx];
1059 :
1060 76800 : DMXEne += tmpReal * tmpReal + tmpImag * tmpImag;
1061 : }
1062 : }
1063 :
1064 780 : dmxEnergy[bandIdx] = DMXEne;
1065 : }
1066 :
1067 : /* Step 3: Peform energy smoothing */
1068 840 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1069 : {
1070 780 : targetEnergy[bandIdx] = LS_OUT_CONV_SMOOTHING_FACTOR * targetEnergy[bandIdx] + ( 1.0f - LS_OUT_CONV_SMOOTHING_FACTOR ) * hLsSetUpConversion->targetEnergyPrev[0][bandIdx];
1071 780 : dmxEnergy[bandIdx] = LS_OUT_CONV_SMOOTHING_FACTOR * dmxEnergy[bandIdx] + ( 1.0f - LS_OUT_CONV_SMOOTHING_FACTOR ) * hLsSetUpConversion->dmxEnergyPrev[0][bandIdx];
1072 780 : hLsSetUpConversion->targetEnergyPrev[0][bandIdx] = targetEnergy[bandIdx];
1073 780 : hLsSetUpConversion->dmxEnergyPrev[0][bandIdx] = dmxEnergy[bandIdx];
1074 : }
1075 :
1076 : /* Step 4: Perform equalization */
1077 240 : for ( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
1078 : {
1079 180 : if ( mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
1080 : {
1081 180 : if ( transform_type[chInIdx][0] == TCX_20 )
1082 : {
1083 : /*TCX20*/
1084 2226 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1085 : {
1086 2067 : start = hLsSetUpConversion->sfbOffset[bandIdx];
1087 2067 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
1088 :
1089 : /*Compute Eq gains */
1090 2067 : ivas_lssetupconversion_computeEQFactor( &targetEnergy[bandIdx], &dmxEnergy[bandIdx], &eqGain );
1091 103827 : for ( binIdx = start; binIdx < stop; binIdx++ )
1092 : {
1093 101760 : x[chInIdx][0][binIdx] *= eqGain;
1094 : }
1095 : }
1096 : }
1097 : else
1098 : {
1099 21 : stop_tcx5 = 0;
1100 294 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1101 : {
1102 273 : start = hLsSetUpConversion->sfbOffset[bandIdx] / 2;
1103 273 : stop = hLsSetUpConversion->sfbOffset[bandIdx + 1] / 2;
1104 :
1105 : /*Compute Eq gains */
1106 273 : ivas_lssetupconversion_computeEQFactor( &targetEnergy[bandIdx], &dmxEnergy[bandIdx], &eqGain );
1107 :
1108 819 : for ( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
1109 : {
1110 546 : if ( transform_type[chInIdx][subFrameIdx] == TCX_10 )
1111 : {
1112 : /*TCX10*/
1113 6993 : for ( binIdx = start; binIdx < stop; binIdx++ )
1114 : {
1115 6720 : x[chInIdx][subFrameIdx][binIdx] *= eqGain;
1116 : }
1117 : }
1118 : else
1119 : {
1120 : /* TCX5*/
1121 273 : start_tcx5 = stop_tcx5;
1122 273 : stop_tcx5 = ( stop + 1 ) / 2;
1123 3633 : for ( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
1124 : {
1125 3360 : x[chInIdx][subFrameIdx][binIdx] *= eqGain;
1126 : }
1127 :
1128 3633 : for ( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
1129 : {
1130 3360 : x[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )] *= eqGain;
1131 : }
1132 : }
1133 : }
1134 : }
1135 : }
1136 : }
1137 : }
1138 :
1139 60 : return;
1140 : }
1141 :
1142 :
1143 : /*-------------------------------------------------------------------------
1144 : * ivas_ls_setup_conversion_process_param_mc()
1145 : *
1146 : * LS setup conversion in the CLDFB domain for Parametric MC
1147 : *-------------------------------------------------------------------------*/
1148 :
1149 4080 : void ivas_lssetupconversion_process_param_mc(
1150 : Decoder_Struct *st_ivas, /* i/o: LS setup conversion renderer handle */
1151 : const int16_t num_timeslots,
1152 : float Cldfb_RealBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals */
1153 : float Cldfb_ImagBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals */
1154 : int16_t channel_active[MAX_CICP_CHANNELS] /* i : bitmap indicating which output channels are active */
1155 : )
1156 : {
1157 : int16_t slotIdx, chOutIdx, chInIdx, bandIdx;
1158 : int16_t inChannels, outChannels;
1159 : float targetEnergy[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1160 : float dmxEnergy[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1161 : float tmpDMXSig, dmxCoeff, tmpReal, tmpImag;
1162 : float EQ;
1163 : float Cldfb_RealBuffer_tmp[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1164 : float Cldfb_ImagBuffer_tmp[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1165 : LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
1166 :
1167 4080 : push_wmops( "LS_Renderer_Process_Param_MC" );
1168 : /* inits */
1169 4080 : inChannels = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe;
1170 4080 : outChannels = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe;
1171 :
1172 4080 : hLsSetUpConversion = st_ivas->hLsSetUpConversion;
1173 4080 : EQ = 0.0f;
1174 :
1175 4080 : set_s( channel_active, 0, outChannels );
1176 :
1177 : /* Loop over each time slots and compute dmx for each time slot */
1178 20400 : for ( slotIdx = 0; slotIdx < num_timeslots; slotIdx++ )
1179 : {
1180 : /* copy buffers */
1181 114240 : for ( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
1182 : {
1183 97920 : mvr2r( Cldfb_RealBuffer_InOut[chInIdx][slotIdx], Cldfb_RealBuffer_tmp[chInIdx], CLDFB_NO_CHANNELS_MAX );
1184 97920 : mvr2r( Cldfb_ImagBuffer_InOut[chInIdx][slotIdx], Cldfb_ImagBuffer_tmp[chInIdx], CLDFB_NO_CHANNELS_MAX );
1185 : }
1186 : /* set the buffers to zero */
1187 212160 : for ( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1188 : {
1189 195840 : set_f( Cldfb_RealBuffer_InOut[chOutIdx][slotIdx], 0.0f, CLDFB_NO_CHANNELS_MAX );
1190 195840 : set_f( Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx], 0.0f, CLDFB_NO_CHANNELS_MAX );
1191 :
1192 195840 : set_f( dmxEnergy[chOutIdx], 0.0f, CLDFB_NO_CHANNELS_MAX );
1193 195840 : set_f( targetEnergy[chOutIdx], 0.0f, CLDFB_NO_CHANNELS_MAX );
1194 : }
1195 :
1196 : /* Compute the target energy and DMX signal */
1197 212160 : for ( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1198 : {
1199 1370880 : for ( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
1200 : {
1201 1175040 : dmxCoeff = hLsSetUpConversion->dmxMtx[chInIdx][chOutIdx];
1202 1175040 : if ( dmxCoeff == 0.0f )
1203 : {
1204 1077120 : continue;
1205 : }
1206 : else
1207 : {
1208 97920 : channel_active[chOutIdx] |= 1;
1209 5973120 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1210 : {
1211 5875200 : tmpDMXSig = dmxCoeff * Cldfb_RealBuffer_tmp[chInIdx][bandIdx];
1212 5875200 : Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx] += tmpDMXSig;
1213 5875200 : targetEnergy[chOutIdx][bandIdx] += tmpDMXSig * tmpDMXSig;
1214 :
1215 5875200 : tmpDMXSig = dmxCoeff * Cldfb_ImagBuffer_tmp[chInIdx][bandIdx];
1216 5875200 : Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx] += tmpDMXSig;
1217 5875200 : targetEnergy[chOutIdx][bandIdx] += tmpDMXSig * tmpDMXSig;
1218 : }
1219 : }
1220 : }
1221 : }
1222 :
1223 : /* Compute the DMX energy */
1224 212160 : for ( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1225 : {
1226 195840 : if ( channel_active[chOutIdx] )
1227 : {
1228 5973120 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1229 : {
1230 5875200 : tmpReal = Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx];
1231 5875200 : tmpImag = Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx];
1232 :
1233 5875200 : dmxEnergy[chOutIdx][bandIdx] = tmpReal * tmpReal + tmpImag * tmpImag;
1234 : }
1235 : }
1236 : }
1237 :
1238 : /* Peform energy smoothing */
1239 212160 : for ( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1240 : {
1241 195840 : if ( channel_active[chOutIdx] )
1242 : {
1243 5973120 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1244 : {
1245 5875200 : targetEnergy[chOutIdx][bandIdx] = LS_OUT_CONV_SMOOTHING_FACTOR * targetEnergy[chOutIdx][bandIdx] + ( 1 - LS_OUT_CONV_SMOOTHING_FACTOR ) * hLsSetUpConversion->targetEnergyPrev[chOutIdx][bandIdx];
1246 5875200 : dmxEnergy[chOutIdx][bandIdx] = LS_OUT_CONV_SMOOTHING_FACTOR * dmxEnergy[chOutIdx][bandIdx] + ( 1 - LS_OUT_CONV_SMOOTHING_FACTOR ) * hLsSetUpConversion->dmxEnergyPrev[chOutIdx][bandIdx];
1247 5875200 : hLsSetUpConversion->targetEnergyPrev[chOutIdx][bandIdx] = targetEnergy[chOutIdx][bandIdx];
1248 5875200 : hLsSetUpConversion->dmxEnergyPrev[chOutIdx][bandIdx] = dmxEnergy[chOutIdx][bandIdx];
1249 : }
1250 : }
1251 : }
1252 :
1253 : /* Compute and perform equalization */
1254 212160 : for ( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
1255 : {
1256 195840 : if ( channel_active[chOutIdx] )
1257 : {
1258 5973120 : for ( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
1259 : {
1260 5875200 : ivas_lssetupconversion_computeEQFactor( &targetEnergy[chOutIdx][bandIdx], &dmxEnergy[chOutIdx][bandIdx], &EQ );
1261 5875200 : Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx] *= EQ;
1262 5875200 : Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx] *= EQ;
1263 : }
1264 : }
1265 : }
1266 : }
1267 :
1268 4080 : pop_wmops();
1269 4080 : return;
1270 : }
|