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 "ivas_cnst.h"
36 : #include "prot_fx.h"
37 : #include "ivas_prot_fx.h"
38 : #include "ivas_prot_rend_fx.h"
39 : #include "ivas_stat_com.h"
40 : #include "ivas_rom_com.h"
41 : #include "rom_com.h"
42 : #include "ivas_rom_dec.h"
43 : #include <math.h>
44 : #include "wmc_auto.h"
45 :
46 :
47 : /*-------------------------------------------------------------------------*
48 : * ivas_ism_renderer_open()
49 : *
50 : * Open struct for object rendering, reserve memory, and init values.
51 : *-------------------------------------------------------------------------*/
52 :
53 : #define SIN_NEG_30_DEGREES_Q15 ( (Word16) 0xC000 )
54 : #define SIN_30_DEGREES_Q15 ( (Word16) 0x4000 )
55 :
56 244 : ivas_error ivas_ism_renderer_open_fx(
57 : Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
58 : )
59 : {
60 : Word16 i;
61 : UWord16 interpolator_length;
62 : UWord16 init_interpolator_length;
63 : ivas_error error;
64 :
65 244 : IF( ( st_ivas->hIsmRendererData = (ISM_RENDERER_HANDLE) malloc( sizeof( ISM_RENDERER_DATA ) ) ) == NULL )
66 : {
67 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISM renderer\n" ) );
68 : }
69 :
70 244 : test();
71 244 : test();
72 244 : test();
73 244 : IF( st_ivas->hIntSetup.is_loudspeaker_setup && st_ivas->hIntSetup.ls_azimuth_fx != NULL && st_ivas->hIntSetup.ls_elevation_fx != NULL && st_ivas->hEFAPdata == NULL )
74 : {
75 112 : IF( NE_32( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth_fx, st_ivas->hIntSetup.ls_elevation_fx, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ), IVAS_ERR_OK ) )
76 : {
77 0 : return error;
78 : }
79 : }
80 :
81 1220 : FOR( i = 0; i < MAX_NUM_OBJECTS; i++ )
82 : {
83 976 : set32_fx( st_ivas->hIsmRendererData->prev_gains_fx[i], 0, MAX_OUTPUT_CHANNELS );
84 976 : set32_fx( st_ivas->hIsmRendererData->gains_fx[i], 0, MAX_OUTPUT_CHANNELS );
85 : }
86 :
87 244 : IF( st_ivas->hDecoderConfig->Opt_tsm )
88 : {
89 : Word32 res_dec, res_frac;
90 84 : init_interpolator_length = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_CLDFB_TIMESLOTS * CLDFB_SLOT_NS );
91 84 : move16();
92 84 : iDiv_and_mod_32( st_ivas->hDecoderConfig->output_Fs, FRAMES_PER_SEC, &res_dec, &res_frac, 0 );
93 84 : interpolator_length = (UWord16) ( res_dec );
94 84 : move16();
95 : }
96 : ELSE
97 : {
98 : Word32 res_dec, res_frac;
99 160 : iDiv_and_mod_32( st_ivas->hDecoderConfig->output_Fs, FRAMES_PER_SEC, &res_dec, &res_frac, 0 );
100 160 : init_interpolator_length = (UWord16) ( res_dec );
101 160 : move16();
102 160 : interpolator_length = init_interpolator_length;
103 160 : move16();
104 : }
105 244 : IF( ( st_ivas->hIsmRendererData->interpolator_fx = (Word16 *) malloc( sizeof( Word16 ) * init_interpolator_length ) ) == NULL )
106 : {
107 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISM renderer interpolator\n" ) );
108 : }
109 :
110 244 : st_ivas->hIsmRendererData->interpolator_len = init_interpolator_length;
111 244 : move16();
112 :
113 198400 : FOR( i = 0; i < sub( interpolator_length, 1 ); i++ )
114 : {
115 198156 : st_ivas->hIsmRendererData->interpolator_fx[i] = div_s( i, sub( interpolator_length, 1 ) );
116 198156 : move16();
117 : }
118 244 : st_ivas->hIsmRendererData->interpolator_fx[interpolator_length - 1] = 32767; // (1.0f in Q15 )- 1
119 244 : move16();
120 :
121 244 : return IVAS_ERR_OK;
122 : }
123 :
124 :
125 : /*-------------------------------------------------------------------------*
126 : * ivas_ism_renderer_close()
127 : *
128 : * Close struct for object rendering.
129 : *-------------------------------------------------------------------------*/
130 2795 : void ivas_ism_renderer_close(
131 : ISM_RENDERER_HANDLE *hIsmRendererData /* i/o: ISM renderer handle */
132 : )
133 : {
134 2795 : test();
135 2795 : IF( hIsmRendererData == NULL || *hIsmRendererData == NULL )
136 : {
137 2002 : return;
138 : }
139 :
140 793 : IF( ( *hIsmRendererData )->interpolator_fx != NULL )
141 : {
142 793 : free( ( *hIsmRendererData )->interpolator_fx );
143 793 : ( *hIsmRendererData )->interpolator_fx = NULL;
144 : }
145 :
146 793 : free( *hIsmRendererData );
147 793 : *hIsmRendererData = NULL;
148 :
149 793 : return;
150 : }
151 :
152 : /*-------------------------------------------------------------------------*
153 : * ivas_ism_render_sf()
154 : *
155 : * Object rendering process
156 : *-------------------------------------------------------------------------*/
157 24028 : void ivas_ism_render_sf_fx(
158 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
159 : Word32 *output_fx[], /* i/o: core-coder transport channels/object output Q11*/
160 : const Word16 n_samples_to_render /* i : output frame length per channel */
161 : )
162 : {
163 : Word16 i, j, k, j2;
164 : Word16 *g1_fx, g2_fx;
165 : Word32 *tc_fx;
166 : Word16 num_objects, nchan_out_woLFE, lfe_index;
167 : Word16 azimuth, elevation;
168 : Word16 tc_offset;
169 : Word16 interp_offset;
170 : Word32 gain_fx, prev_gain_fx;
171 : Word32 tc_local_fx[MAX_NUM_OBJECTS][L_FRAME48k];
172 : Word32 *p_tc_fx[MAX_NUM_OBJECTS];
173 :
174 24028 : num_objects = st_ivas->nchan_transport;
175 24028 : move16();
176 24028 : if ( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) )
177 : {
178 3210 : num_objects = st_ivas->nchan_ism;
179 3210 : move16();
180 : }
181 :
182 24028 : nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE;
183 24028 : move16();
184 :
185 24028 : tc_offset = st_ivas->hTcBuffer->n_samples_rendered;
186 24028 : move16();
187 24028 : interp_offset = st_ivas->hTcBuffer->n_samples_rendered;
188 24028 : move16();
189 :
190 24028 : IF( st_ivas->hDecoderConfig->Opt_tsm )
191 : {
192 5681 : FOR( i = 0; i < num_objects; i++ )
193 : {
194 4259 : p_tc_fx[i] = &st_ivas->hTcBuffer->tc_fx[i][tc_offset]; // Q11
195 : }
196 : }
197 : ELSE
198 : {
199 82620 : FOR( i = 0; i < num_objects; i++ )
200 : {
201 60014 : Copy32( &output_fx[i][tc_offset], tc_local_fx[i], n_samples_to_render );
202 60014 : p_tc_fx[i] = tc_local_fx[i];
203 : }
204 : }
205 :
206 247264 : FOR( i = 0; i < nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; i++ )
207 : {
208 223236 : set32_fx( output_fx[i], 0, n_samples_to_render );
209 : }
210 :
211 24028 : test();
212 24028 : IF( st_ivas->hCombinedOrientationData && EQ_16( st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx], 1 ) )
213 : {
214 3000 : ivas_jbm_dec_get_adapted_linear_interpolator_fx( n_samples_to_render, n_samples_to_render, st_ivas->hIsmRendererData->interpolator_fx );
215 3000 : interp_offset = 0;
216 3000 : move16();
217 : }
218 :
219 88301 : FOR( i = 0; i < num_objects; i++ )
220 : {
221 : /* Combined rotation: rotate the object positions depending the head and external orientations */
222 64273 : test();
223 64273 : IF( st_ivas->hCombinedOrientationData != NULL && EQ_16( st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx], 1 ) )
224 : {
225 3000 : rotateAziEle_fx( extract_l( L_shr( st_ivas->hIsmMetaData[i]->azimuth_fx, 22 ) ), extract_l( L_shr( st_ivas->hIsmMetaData[i]->elevation_fx, 22 ) ), &azimuth, &elevation, st_ivas->hCombinedOrientationData->Rmat_fx[0], st_ivas->hIntSetup.is_planar_setup );
226 :
227 3000 : IF( st_ivas->hEFAPdata != NULL )
228 : {
229 3000 : efap_determine_gains_fx( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains_fx[i], L_shl( azimuth, 22 ), L_shl( elevation, 22 ), EFAP_MODE_EFAP );
230 : }
231 : }
232 :
233 64273 : lfe_index = 0;
234 64273 : move16();
235 606806 : FOR( ( j = 0, j2 = 0 ); j < nchan_out_woLFE; ( j++, j2++ ) )
236 : {
237 542533 : test();
238 542533 : IF( ( st_ivas->hIntSetup.num_lfe > 0 ) && EQ_16( st_ivas->hIntSetup.index_lfe[lfe_index], j ) )
239 : {
240 40443 : IF( LT_16( lfe_index, sub( st_ivas->hIntSetup.num_lfe, 1 ) ) )
241 : {
242 0 : lfe_index = add( lfe_index, 1 );
243 0 : j2 = add( j2, 1 );
244 : }
245 : ELSE
246 : {
247 40443 : j2 = add( j2, 1 );
248 : }
249 : }
250 :
251 542533 : gain_fx = st_ivas->hIsmRendererData->gains_fx[i][j];
252 542533 : move32();
253 542533 : prev_gain_fx = st_ivas->hIsmRendererData->prev_gains_fx[i][j];
254 542533 : move32();
255 :
256 542533 : test();
257 542533 : IF( ( L_abs( gain_fx ) > 0 ) || ( L_abs( prev_gain_fx ) > 0 ) )
258 : {
259 265791 : g1_fx = &st_ivas->hIsmRendererData->interpolator_fx[interp_offset];
260 265791 : tc_fx = p_tc_fx[i];
261 219870431 : FOR( k = 0; k < n_samples_to_render; k++ )
262 : {
263 219604640 : g2_fx = sub( 32767, *g1_fx ); // 32767 = (1.0f in Q15) - 1
264 219604640 : output_fx[j2][k] = L_add( output_fx[j2][k], L_shl( Mpy_32_32( L_add( Mpy_32_16_1( gain_fx, *( g1_fx++ ) ), Mpy_32_16_1( prev_gain_fx, g2_fx ) ), *( tc_fx++ ) ), 1 ) ); // Q11( (30+15+1-16) + 11 -31 +1)
265 219604640 : move16();
266 : }
267 : }
268 :
269 : /* update here only in case of head rotation */
270 542533 : test();
271 542533 : IF( st_ivas->hCombinedOrientationData != NULL && st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx] == 1 )
272 : {
273 33000 : st_ivas->hIsmRendererData->prev_gains_fx[i][j] = gain_fx; // Q30
274 33000 : move32();
275 : }
276 : }
277 : }
278 :
279 : /* update combined orientation access index */
280 24028 : ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, n_samples_to_render );
281 :
282 24028 : return;
283 : }
284 :
285 :
286 : /*-------------------------------------------------------------------------*
287 : * ivas_ism_get_stereo_gains()
288 : *
289 : *
290 : *-------------------------------------------------------------------------*/
291 :
292 168640 : void ivas_ism_get_stereo_gains_fx(
293 : const Word16 aziDeg, /* i : object azimuth Q0*/
294 : const Word16 eleDeg, /* i : object elevation Q0*/
295 : Word16 *left_gain_fx, /* o : left channel gain Q15*/
296 : Word16 *right_gain_fx /* o : right channel gain Q15*/
297 : )
298 : {
299 : /* Convert azi and ele to an azi value of the cone of confusion */
300 168640 : Word16 azAddEl = add( aziDeg, eleDeg );
301 168640 : Word16 azSubEl = sub( aziDeg, eleDeg );
302 : Word16 gains[2];
303 :
304 168640 : const Word16 *ptr_sin_az = ivas_sin_az_fx;
305 :
306 241767 : WHILE( azAddEl > 180 )
307 : {
308 73127 : azAddEl = sub( azAddEl, 360 );
309 : }
310 169219 : WHILE( azAddEl < -180 )
311 : {
312 579 : azAddEl = add( azAddEl, 360 );
313 : }
314 242264 : WHILE( azSubEl > 180 )
315 : {
316 73624 : azSubEl = sub( azSubEl, 360 );
317 : }
318 169703 : WHILE( azSubEl < -180 )
319 : {
320 1063 : azSubEl = add( azSubEl, 360 );
321 : }
322 168640 : Word16 sin_az_cos_el = extract_l( L_shr( L_add( L_deposit_l( ptr_sin_az[azAddEl + 180] ), L_deposit_l( ptr_sin_az[azSubEl + 180] ) ), 1 ) );
323 :
324 168640 : IF( GE_16( sin_az_cos_el, SIN_30_DEGREES_Q15 ) )
325 : { /* Left side */
326 33926 : gains[0] = (Word16) 0x7fff; // 1.0f in Q15
327 33926 : move16();
328 33926 : gains[1] = 0;
329 33926 : move16();
330 : }
331 134714 : ELSE IF( LE_16( sin_az_cos_el, SIN_NEG_30_DEGREES_Q15 ) )
332 : { /* Right side */
333 34147 : gains[0] = 0;
334 34147 : move16();
335 34147 : gains[1] = (Word16) 0x7fff; // 1.0f in Q15
336 34147 : move16();
337 : }
338 : ELSE /* Tangent panning law */
339 : {
340 100567 : get_panning_gain_fx( sin_az_cos_el, gains );
341 : }
342 :
343 168640 : *left_gain_fx = gains[0];
344 168640 : move16();
345 168640 : *right_gain_fx = gains[1];
346 168640 : move16();
347 :
348 168640 : return;
349 : }
350 :
351 : /*-------------------------------------------------------------------------*
352 : * ivas_masa_oism_separate_object_renderer_open()
353 : *
354 : * Open structures, reserve memory, and init values.
355 : *-------------------------------------------------------------------------*/
356 :
357 549 : ivas_error ivas_omasa_separate_object_renderer_open(
358 : Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
359 : )
360 : {
361 : Word16 interpolator_length;
362 : Word16 i;
363 : Word16 init_interpolator_length;
364 :
365 549 : IF( ( st_ivas->hIsmRendererData = (ISM_RENDERER_HANDLE) malloc( sizeof( ISM_RENDERER_DATA ) ) ) == NULL )
366 : {
367 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM renderer \n" ) );
368 : }
369 :
370 2745 : FOR( i = 0; i < MAX_NUM_OBJECTS; i++ )
371 : {
372 2196 : set32_fx( st_ivas->hIsmRendererData->prev_gains_fx[i], 0, MAX_OUTPUT_CHANNELS );
373 : }
374 : Word32 res_dec1, res_frac1;
375 : Word32 res_dec2, res_frac2;
376 549 : iDiv_and_mod_32( st_ivas->hDecoderConfig->output_Fs, FRAMES_PER_SEC, &res_dec1, &res_frac1, 0 );
377 549 : iDiv_and_mod_32( res_dec1, MAX_PARAM_SPATIAL_SUBFRAMES, &res_dec2, &res_frac2, 0 );
378 549 : init_interpolator_length = extract_l( res_dec2 );
379 549 : interpolator_length = init_interpolator_length;
380 549 : move16();
381 :
382 549 : st_ivas->hIsmRendererData->interpolator_fx = (Word16 *) malloc( sizeof( Word16 ) * init_interpolator_length );
383 549 : st_ivas->hIsmRendererData->interpolator_len = init_interpolator_length;
384 549 : move16();
385 128869 : FOR( i = 0; i < interpolator_length; i++ )
386 : {
387 128320 : st_ivas->hIsmRendererData->interpolator_fx[i] = div_s( i, interpolator_length );
388 128320 : move16();
389 : }
390 549 : st_ivas->hIsmRendererData->interpolator_len = interpolator_length;
391 549 : move16();
392 :
393 549 : st_ivas->hMasaIsmData->delayBuffer_size = extract_l( ( st_ivas->hDecoderConfig->output_Fs / 50 ) / MAX_PARAM_SPATIAL_SUBFRAMES );
394 549 : move16();
395 :
396 549 : test();
397 549 : IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
398 : {
399 321 : st_ivas->hMasaIsmData->delayBuffer_nchan = 1;
400 321 : move16();
401 : }
402 : ELSE
403 : {
404 228 : st_ivas->hMasaIsmData->delayBuffer_nchan = st_ivas->nchan_ism;
405 228 : move16();
406 : }
407 :
408 549 : IF( ( st_ivas->hMasaIsmData->delayBuffer_fx = (Word32 **) malloc( st_ivas->hMasaIsmData->delayBuffer_nchan * sizeof( Word32 * ) ) ) == NULL )
409 : {
410 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM delay buffer \n" ) );
411 : }
412 :
413 1654 : FOR( i = 0; i < st_ivas->hMasaIsmData->delayBuffer_nchan; i++ )
414 : {
415 1105 : IF( ( st_ivas->hMasaIsmData->delayBuffer_fx[i] = (Word32 *) malloc( st_ivas->hMasaIsmData->delayBuffer_size * sizeof( Word32 ) ) ) == NULL )
416 : {
417 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM delay buffer \n" ) );
418 : }
419 1105 : set32_fx( st_ivas->hMasaIsmData->delayBuffer_fx[i], 0, st_ivas->hMasaIsmData->delayBuffer_size );
420 : }
421 :
422 549 : return IVAS_ERR_OK;
423 : }
424 :
425 :
426 : /*-------------------------------------------------------------------------*
427 : * ivas_omasa_separate_object_renderer_close()
428 : *
429 : * Close structures, free memory.
430 : *-------------------------------------------------------------------------*/
431 :
432 1808 : void ivas_omasa_separate_object_renderer_close(
433 : Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
434 : )
435 : {
436 : Word16 i;
437 :
438 1808 : IF( st_ivas->hMasaIsmData != NULL )
439 : {
440 1808 : IF( st_ivas->hMasaIsmData->delayBuffer_fx != NULL )
441 : {
442 1615 : FOR( i = 0; i < st_ivas->hMasaIsmData->delayBuffer_nchan; i++ )
443 : {
444 1078 : IF( st_ivas->hMasaIsmData->delayBuffer_fx[i] != NULL )
445 : {
446 1078 : free( st_ivas->hMasaIsmData->delayBuffer_fx[i] );
447 1078 : st_ivas->hMasaIsmData->delayBuffer_fx[i] = NULL;
448 : }
449 : }
450 :
451 537 : free( st_ivas->hMasaIsmData->delayBuffer_fx );
452 537 : st_ivas->hMasaIsmData->delayBuffer_fx = NULL;
453 : }
454 : }
455 :
456 1808 : ivas_ism_renderer_close( &st_ivas->hIsmRendererData );
457 :
458 1808 : return;
459 : }
460 :
461 :
462 : /*-------------------------------------------------------------------------*
463 : * ivas_omasa_separate_object_render_jbm()
464 : *
465 : * Rendering separated objects and mixing them to the parametrically rendered signals for JBM
466 : *-------------------------------------------------------------------------*/
467 :
468 2705 : void ivas_omasa_separate_object_render_jbm_fx(
469 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
470 : const UWord16 nSamplesRendered, /* i : number of samples rendered */
471 : Word32 input_fx_in[][L_FRAME48k], /* i : separated object signal Q11*/
472 : Word32 *output_fx[], /* o : rendered time signal Q11*/
473 : const Word16 subframes_rendered, /* i : number of subframes rendered */
474 : const Word16 slots_rendered /* i : number of CLDFB slots rendered */
475 : )
476 : {
477 : VBAP_HANDLE hVBAPdata;
478 : DIRAC_REND_HANDLE hDirACRend;
479 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
480 : Word16 nchan_out_woLFE, num_lfe;
481 : ISM_RENDERER_HANDLE hRendererData;
482 : Word16 j, k, j2;
483 : Word16 obj;
484 : Word32 gains_fx[MAX_OUTPUT_CHANNELS];
485 : Word16 g1_fx, g2_fx;
486 : Word16 lfe_index;
487 : Word16 azimuth, elevation;
488 : Word16 num_objects;
489 : UWord8 single_separated;
490 : Word32 *input_fx[MAX_TRANSPORT_CHANNELS];
491 : Word32 *output_fx_local[MAX_OUTPUT_CHANNELS];
492 : Word16 offsetSamples;
493 : Word16 n_samples_sf, md_idx;
494 : Word16 slots_to_render, first_sf, last_sf, subframe_idx;
495 :
496 2705 : hVBAPdata = st_ivas->hVBAPdata;
497 2705 : hDirACRend = st_ivas->hDirACRend;
498 2705 : hSpatParamRendCom = st_ivas->hSpatParamRendCom;
499 2705 : nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE;
500 2705 : move16();
501 2705 : num_lfe = st_ivas->hIntSetup.num_lfe;
502 2705 : move16();
503 2705 : hRendererData = st_ivas->hIsmRendererData;
504 2705 : lfe_index = hDirACRend->hOutSetup.index_lfe[0];
505 2705 : move16();
506 :
507 2705 : test();
508 2705 : IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
509 : {
510 1634 : single_separated = 1;
511 1634 : move16();
512 1634 : num_objects = 1;
513 1634 : move16();
514 : }
515 : ELSE
516 : {
517 1071 : single_separated = 0;
518 1071 : move16();
519 1071 : num_objects = st_ivas->nchan_ism;
520 1071 : move16();
521 : }
522 :
523 2705 : offsetSamples = i_mult( slots_rendered, hSpatParamRendCom->slot_size );
524 :
525 27915 : FOR( j = 0; j < nchan_out_woLFE + num_lfe; j++ )
526 : {
527 25210 : output_fx_local[j] = output_fx[j];
528 : }
529 :
530 2705 : IF( st_ivas->hDecoderConfig->Opt_tsm )
531 : {
532 2514 : FOR( obj = 0; obj < num_objects; obj++ )
533 : {
534 1609 : input_fx[obj] = &st_ivas->hTcBuffer->tc_fx[obj + 2][offsetSamples];
535 1609 : move32();
536 : }
537 : }
538 : ELSE
539 : {
540 4574 : FOR( obj = 0; obj < num_objects; obj++ )
541 : {
542 2774 : input_fx[obj] = input_fx_in[obj];
543 2774 : move32();
544 : }
545 : }
546 :
547 2705 : slots_to_render = idiv1616( nSamplesRendered, hSpatParamRendCom->slot_size );
548 2705 : first_sf = subframes_rendered;
549 2705 : move16();
550 2705 : last_sf = first_sf;
551 2705 : move16();
552 :
553 12180 : WHILE( slots_to_render > 0 )
554 : {
555 9475 : slots_to_render = sub( slots_to_render, hSpatParamRendCom->subframe_nbslots[last_sf] );
556 9475 : last_sf = add( last_sf, 1 );
557 : }
558 :
559 7088 : FOR( obj = 0; obj < num_objects; obj++ )
560 : {
561 : /* Delay the signal to match CLDFB delay. Delay the whole buffer with the first rendering call of the stretched buffer. */
562 4383 : IF( slots_rendered == 0 )
563 : {
564 : Word16 tcBufferSize;
565 :
566 3766 : tcBufferSize = i_mult( hSpatParamRendCom->num_slots, hSpatParamRendCom->slot_size );
567 3766 : delay_signal32_fx( input_fx[obj], tcBufferSize, st_ivas->hMasaIsmData->delayBuffer_fx[obj], st_ivas->hMasaIsmData->delayBuffer_size );
568 : }
569 4383 : offsetSamples = 0;
570 4383 : move16();
571 :
572 19463 : FOR( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
573 : {
574 15080 : n_samples_sf = i_mult( hSpatParamRendCom->subframe_nbslots[subframe_idx], hSpatParamRendCom->slot_size );
575 15080 : IF( n_samples_sf != hRendererData->interpolator_len )
576 : {
577 16959 : FOR( k = 0; k < n_samples_sf; k++ )
578 : {
579 16860 : hRendererData->interpolator_fx[k] = div_s( k, n_samples_sf );
580 16860 : move16();
581 : }
582 99 : hRendererData->interpolator_len = n_samples_sf;
583 99 : move16();
584 : }
585 :
586 15080 : md_idx = hSpatParamRendCom->render_to_md_map[subframe_idx];
587 15080 : move16();
588 :
589 15080 : IF( single_separated )
590 : {
591 5653 : azimuth = st_ivas->hMasaIsmData->azimuth_separated_ism[md_idx];
592 5653 : move16();
593 5653 : elevation = st_ivas->hMasaIsmData->elevation_separated_ism[md_idx];
594 5653 : move16();
595 : }
596 : ELSE
597 : {
598 9427 : azimuth = st_ivas->hMasaIsmData->azimuth_ism[obj][md_idx];
599 9427 : move16();
600 9427 : elevation = st_ivas->hMasaIsmData->elevation_ism[obj][md_idx];
601 9427 : move16();
602 : }
603 :
604 15080 : if ( st_ivas->hOutSetup.is_planar_setup )
605 : {
606 : /* If no elevation support in output format, then rendering should be done with zero elevation */
607 673 : elevation = 0;
608 673 : move16();
609 : }
610 :
611 15080 : IF( hVBAPdata != NULL )
612 : {
613 6102 : vbap_determine_gains_fx( hVBAPdata, gains_fx, azimuth, elevation, 1 );
614 : }
615 : ELSE
616 : {
617 8978 : ivas_dirac_dec_get_response_fx( azimuth, elevation, gains_fx, hDirACRend->hOutSetup.ambisonics_order, Q29 );
618 : }
619 :
620 170418 : FOR( j = 0; j < nchan_out_woLFE; j++ )
621 : {
622 155338 : IF( hDirACRend->hOutSetup.num_lfe > 0 )
623 : {
624 51722 : j2 = add( j, extract_l( GE_16( j, lfe_index ) ) );
625 : }
626 : ELSE
627 : {
628 103616 : j2 = j;
629 103616 : move16();
630 : }
631 :
632 155338 : test();
633 155338 : IF( ( L_abs( gains_fx[j] ) > 0 ) || ( L_abs( hRendererData->prev_gains_fx[obj][j] ) > 0 ) )
634 : {
635 23913228 : FOR( k = 0; k < n_samples_sf; k++ )
636 : {
637 23793960 : g1_fx = hRendererData->interpolator_fx[k];
638 23793960 : move16();
639 23793960 : g2_fx = sub( 32767, g1_fx ); // 32767 = 1.0f in Q15
640 :
641 23793960 : output_fx_local[j2][k + offsetSamples] = L_add( output_fx_local[j2][k + offsetSamples], L_add( L_shl( Mpy_32_32( Mpy_32_16_1( input_fx[obj][k + offsetSamples], g1_fx ), gains_fx[j] ), 2 ), L_shl( Mpy_32_32( Mpy_32_16_1( input_fx[obj][k + offsetSamples], g2_fx ), hRendererData->prev_gains_fx[obj][j] ), 2 ) ) ); // Q11( (30+15+1-16) + 11 -31 +1)
642 23793960 : move32();
643 : }
644 : }
645 155338 : hRendererData->prev_gains_fx[obj][j] = gains_fx[j];
646 155338 : move32();
647 : }
648 :
649 15080 : offsetSamples = add( offsetSamples, n_samples_sf );
650 : }
651 : }
652 :
653 2705 : return;
654 : }
|