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 323 : 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 323 : 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 323 : test();
71 323 : test();
72 323 : test();
73 : #ifdef FIX_1050_EFAP_ALLOC
74 323 : test();
75 323 : IF( st_ivas->hIntSetup.is_loudspeaker_setup &&
76 : st_ivas->hDecoderConfig->output_config != IVAS_AUDIO_CONFIG_STEREO &&
77 : st_ivas->hIntSetup.ls_azimuth_fx != NULL && st_ivas->hIntSetup.ls_elevation_fx != NULL &&
78 : st_ivas->hEFAPdata == NULL )
79 : #else
80 : 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 )
81 : #endif
82 : {
83 108 : 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 ) )
84 : {
85 0 : return error;
86 : }
87 : }
88 :
89 1615 : FOR( i = 0; i < MAX_NUM_OBJECTS; i++ )
90 : {
91 1292 : set32_fx( st_ivas->hIsmRendererData->prev_gains_fx[i], 0, MAX_OUTPUT_CHANNELS );
92 1292 : set32_fx( st_ivas->hIsmRendererData->gains_fx[i], 0, MAX_OUTPUT_CHANNELS );
93 : }
94 :
95 323 : IF( st_ivas->hDecoderConfig->Opt_tsm )
96 : {
97 : Word32 res_dec, res_frac;
98 99 : init_interpolator_length = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_CLDFB_TIMESLOTS * CLDFB_SLOT_NS );
99 99 : move16();
100 99 : iDiv_and_mod_32( st_ivas->hDecoderConfig->output_Fs, FRAMES_PER_SEC, &res_dec, &res_frac, 0 );
101 99 : interpolator_length = (UWord16) ( res_dec );
102 99 : move16();
103 : }
104 : ELSE
105 : {
106 : Word32 res_dec, res_frac;
107 224 : iDiv_and_mod_32( st_ivas->hDecoderConfig->output_Fs, FRAMES_PER_SEC, &res_dec, &res_frac, 0 );
108 224 : init_interpolator_length = (UWord16) ( res_dec );
109 224 : move16();
110 224 : interpolator_length = init_interpolator_length;
111 224 : move16();
112 : }
113 :
114 323 : IF( ( st_ivas->hIsmRendererData->interpolator_fx = (Word16 *) malloc( sizeof( Word16 ) * init_interpolator_length ) ) == NULL )
115 : {
116 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISM renderer interpolator\n" ) );
117 : }
118 :
119 323 : st_ivas->hIsmRendererData->interpolator_len = init_interpolator_length;
120 323 : move16();
121 :
122 251200 : FOR( i = 0; i < sub( interpolator_length, 1 ); i++ )
123 : {
124 250877 : st_ivas->hIsmRendererData->interpolator_fx[i] = div_s( i, sub( interpolator_length, 1 ) );
125 250877 : move16();
126 : }
127 323 : st_ivas->hIsmRendererData->interpolator_fx[interpolator_length - 1] = 32767; // (1.0f in Q15 )- 1
128 323 : move16();
129 :
130 323 : return IVAS_ERR_OK;
131 : }
132 :
133 :
134 : /*-------------------------------------------------------------------------*
135 : * ivas_ism_renderer_close()
136 : *
137 : * Close struct for object rendering.
138 : *-------------------------------------------------------------------------*/
139 2962 : void ivas_ism_renderer_close(
140 : ISM_RENDERER_HANDLE *hIsmRendererData /* i/o: ISM renderer handle */
141 : )
142 : {
143 2962 : test();
144 2962 : IF( hIsmRendererData == NULL || *hIsmRendererData == NULL )
145 : {
146 2127 : return;
147 : }
148 :
149 835 : IF( ( *hIsmRendererData )->interpolator_fx != NULL )
150 : {
151 835 : free( ( *hIsmRendererData )->interpolator_fx );
152 835 : ( *hIsmRendererData )->interpolator_fx = NULL;
153 : }
154 :
155 835 : free( *hIsmRendererData );
156 835 : *hIsmRendererData = NULL;
157 :
158 835 : return;
159 : }
160 :
161 :
162 : /*-------------------------------------------------------------------------*
163 : * ivas_ism_render_sf()
164 : *
165 : * Object rendering process
166 : *-------------------------------------------------------------------------*/
167 25218 : void ivas_ism_render_sf_fx(
168 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
169 : const RENDERER_TYPE renderer_type, /* i : active renderer type */
170 : Word32 *output_fx[], /* i/o: core-coder transport channels/object output Q11*/
171 : const Word16 n_samples_to_render /* i : output frame length per channel */
172 : )
173 : {
174 : Word16 i, j, k, j2;
175 : Word16 *g1_fx, g2_fx;
176 : Word32 *tc_fx;
177 : Word16 num_objects, nchan_out_woLFE, lfe_index;
178 : Word16 azimuth, elevation;
179 : Word16 tc_offset;
180 : Word16 interp_offset;
181 : Word32 gain_fx, prev_gain_fx;
182 : Word32 tc_local_fx[MAX_NUM_OBJECTS][L_FRAME48k];
183 : Word32 *p_tc_fx[MAX_NUM_OBJECTS];
184 : Word16 ism_md_subframe_update_jbm, slots_to_render, first_sf, last_sf, subframe_idx;
185 : Word16 n_samples_rendered_loop;
186 :
187 : /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */
188 25218 : slots_to_render = s_min( sub( st_ivas->hTcBuffer->num_slots, st_ivas->hTcBuffer->slots_rendered ), n_samples_to_render / st_ivas->hTcBuffer->n_samples_granularity );
189 25218 : first_sf = st_ivas->hTcBuffer->subframes_rendered;
190 25218 : move16();
191 25218 : last_sf = first_sf;
192 25218 : move16();
193 25218 : n_samples_rendered_loop = 0;
194 25218 : move16();
195 :
196 : #ifdef DEBUGGING
197 : assert( slots_to_render == 0 );
198 : assert( last_sf <= st_ivas->hTcBuffer->nb_subframes );
199 : #endif
200 :
201 123427 : WHILE( slots_to_render > 0 )
202 : {
203 98209 : slots_to_render = sub( slots_to_render, st_ivas->hTcBuffer->subframe_nbslots[last_sf] );
204 98209 : last_sf = add( last_sf, 1 );
205 : }
206 :
207 25218 : num_objects = st_ivas->nchan_ism;
208 :
209 25218 : nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE;
210 25218 : move16();
211 :
212 25218 : tc_offset = st_ivas->hTcBuffer->n_samples_rendered;
213 25218 : move16();
214 25218 : interp_offset = st_ivas->hTcBuffer->n_samples_rendered;
215 25218 : move16();
216 :
217 : /* Number of subframes to delay metadata to sync with audio */
218 25218 : IF( st_ivas->hDecoderConfig->Opt_delay_comp )
219 : {
220 25218 : ism_md_subframe_update_jbm = s_max( 0, sub( st_ivas->hTcBuffer->nb_subframes, 3 ) );
221 : }
222 : ELSE
223 : {
224 0 : ism_md_subframe_update_jbm = sub( st_ivas->hTcBuffer->nb_subframes, 2 );
225 : }
226 :
227 25218 : IF( st_ivas->hDecoderConfig->Opt_tsm )
228 : {
229 5688 : FOR( i = 0; i < num_objects; i++ )
230 : {
231 4266 : p_tc_fx[i] = &st_ivas->hTcBuffer->tc_fx[i][tc_offset]; // Q11
232 : }
233 : }
234 : ELSE
235 : {
236 87380 : FOR( i = 0; i < num_objects; i++ )
237 : {
238 63584 : Copy32( &output_fx[i][tc_offset], tc_local_fx[i], n_samples_to_render );
239 63584 : p_tc_fx[i] = tc_local_fx[i];
240 : }
241 : }
242 :
243 260834 : FOR( i = 0; i < nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; i++ )
244 : {
245 235616 : set32_fx( output_fx[i], 0, n_samples_to_render );
246 : }
247 :
248 :
249 123427 : FOR( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
250 : {
251 : int16_t n_samples_in_subframe;
252 :
253 98209 : n_samples_in_subframe = st_ivas->hTcBuffer->n_samples_granularity * st_ivas->hTcBuffer->subframe_nbslots[subframe_idx];
254 98209 : test();
255 98209 : IF( st_ivas->hCombinedOrientationData && EQ_16( st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx], 1 ) )
256 : {
257 12000 : ivas_jbm_dec_get_adapted_linear_interpolator_fx( n_samples_in_subframe, n_samples_in_subframe, st_ivas->hIsmRendererData->interpolator_fx );
258 12000 : interp_offset = 0;
259 12000 : move16();
260 : }
261 :
262 361620 : FOR( i = 0; i < num_objects; i++ )
263 : {
264 : /* Combined rotation: rotate the object positions depending the head and external orientations */
265 263411 : test();
266 263411 : IF( st_ivas->hCombinedOrientationData != NULL && EQ_16( st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx], 1 ) )
267 : {
268 12000 : if ( GE_16( subframe_idx, ism_md_subframe_update_jbm ) )
269 : {
270 9000 : 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[st_ivas->hCombinedOrientationData->subframe_idx], st_ivas->hIntSetup.is_planar_setup );
271 : }
272 : else
273 : {
274 3000 : rotateAziEle_fx( extract_l( L_shr( st_ivas->hIsmMetaData[i]->last_azimuth_fx, 22 ) ), extract_l( L_shr( st_ivas->hIsmMetaData[i]->last_elevation_fx, 22 ) ), &azimuth, &elevation, st_ivas->hCombinedOrientationData->Rmat_fx[st_ivas->hCombinedOrientationData->subframe_idx], st_ivas->hIntSetup.is_planar_setup );
275 : }
276 :
277 12000 : IF( st_ivas->hEFAPdata != NULL )
278 : {
279 12000 : efap_determine_gains_fx( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains_fx[i], L_shl( azimuth, 22 ), L_shl( elevation, 22 ), EFAP_MODE_EFAP );
280 : }
281 : }
282 :
283 263411 : lfe_index = 0;
284 263411 : move16();
285 2482532 : FOR( ( j = 0, j2 = 0 ); j < nchan_out_woLFE; ( j++, j2++ ) )
286 : {
287 2219121 : test();
288 2219121 : IF( ( st_ivas->hIntSetup.num_lfe > 0 ) && EQ_16( st_ivas->hIntSetup.index_lfe[lfe_index], j ) )
289 : {
290 165811 : IF( LT_16( lfe_index, sub( st_ivas->hIntSetup.num_lfe, 1 ) ) )
291 : {
292 0 : lfe_index = add( lfe_index, 1 );
293 0 : j2 = add( j2, 1 );
294 : }
295 : ELSE
296 : {
297 165811 : j2 = add( j2, 1 );
298 : }
299 : }
300 :
301 2219121 : gain_fx = st_ivas->hIsmRendererData->gains_fx[i][j];
302 2219121 : move32();
303 2219121 : prev_gain_fx = st_ivas->hIsmRendererData->prev_gains_fx[i][j];
304 2219121 : move32();
305 :
306 2219121 : test();
307 2219121 : IF( ( L_abs( gain_fx ) > 0 ) || ( L_abs( prev_gain_fx ) > 0 ) )
308 : {
309 1091186 : g1_fx = &st_ivas->hIsmRendererData->interpolator_fx[interp_offset];
310 1091186 : tc_fx = p_tc_fx[i];
311 237817666 : FOR( k = 0; k < n_samples_in_subframe; k++ )
312 : {
313 236726480 : g2_fx = sub( 32767, *g1_fx ); // 32767 = (1.0f in Q15) - 1
314 236726480 : output_fx[j2][k + n_samples_rendered_loop] = L_add( output_fx[j2][k + n_samples_rendered_loop], 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)
315 236726480 : move16();
316 : }
317 : }
318 :
319 : /* update here only in case of head rotation */
320 2219121 : test();
321 2219121 : IF( st_ivas->hCombinedOrientationData != NULL && st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx] == 1 )
322 : {
323 132000 : st_ivas->hIsmRendererData->prev_gains_fx[i][j] = gain_fx; // Q30
324 132000 : move32();
325 : }
326 : }
327 263411 : p_tc_fx[i] += n_samples_in_subframe;
328 : }
329 :
330 : /* update combined orientation access index */
331 98209 : ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, n_samples_in_subframe );
332 :
333 98209 : n_samples_rendered_loop = add( n_samples_rendered_loop, n_samples_in_subframe );
334 : /* update rendered subframe and slots info for all cases apart from a following crend call, the update will
335 : then happen in the crend call*/
336 98209 : if ( NE_16( renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) )
337 : {
338 58000 : st_ivas->hTcBuffer->subframes_rendered = add( st_ivas->hTcBuffer->subframes_rendered, 1 );
339 58000 : st_ivas->hTcBuffer->slots_rendered = add( st_ivas->hTcBuffer->slots_rendered, st_ivas->hTcBuffer->subframe_nbslots[subframe_idx] );
340 : }
341 98209 : tc_offset = add( tc_offset, n_samples_in_subframe );
342 98209 : interp_offset = add( interp_offset, n_samples_in_subframe );
343 : }
344 :
345 25218 : return;
346 : }
347 :
348 :
349 : /*-------------------------------------------------------------------------*
350 : * ivas_ism_get_stereo_gains()
351 : *
352 : *
353 : *-------------------------------------------------------------------------*/
354 :
355 169000 : void ivas_ism_get_stereo_gains_fx(
356 : const Word16 aziDeg, /* i : object azimuth Q0*/
357 : const Word16 eleDeg, /* i : object elevation Q0*/
358 : Word16 *left_gain_fx, /* o : left channel gain Q15*/
359 : Word16 *right_gain_fx /* o : right channel gain Q15*/
360 : )
361 : {
362 : /* Convert azi and ele to an azi value of the cone of confusion */
363 169000 : Word16 azAddEl = add( aziDeg, eleDeg );
364 169000 : Word16 azSubEl = sub( aziDeg, eleDeg );
365 : Word16 gains[2];
366 :
367 169000 : const Word16 *ptr_sin_az = ivas_sin_az_fx;
368 :
369 242127 : WHILE( azAddEl > 180 )
370 : {
371 73127 : azAddEl = sub( azAddEl, 360 );
372 : }
373 169581 : WHILE( azAddEl < -180 )
374 : {
375 581 : azAddEl = add( azAddEl, 360 );
376 : }
377 242673 : WHILE( azSubEl > 180 )
378 : {
379 73673 : azSubEl = sub( azSubEl, 360 );
380 : }
381 170075 : WHILE( azSubEl < -180 )
382 : {
383 1075 : azSubEl = add( azSubEl, 360 );
384 : }
385 169000 : 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 ) );
386 :
387 169000 : IF( GE_16( sin_az_cos_el, SIN_30_DEGREES_Q15 ) )
388 : { /* Left side */
389 34030 : gains[0] = (Word16) 0x7fff; // 1.0f in Q15
390 34030 : move16();
391 34030 : gains[1] = 0;
392 34030 : move16();
393 : }
394 134970 : ELSE IF( LE_16( sin_az_cos_el, SIN_NEG_30_DEGREES_Q15 ) )
395 : { /* Right side */
396 34304 : gains[0] = 0;
397 34304 : move16();
398 34304 : gains[1] = (Word16) 0x7fff; // 1.0f in Q15
399 34304 : move16();
400 : }
401 : ELSE /* Tangent panning law */
402 : {
403 100666 : get_panning_gain_fx( sin_az_cos_el, gains );
404 : }
405 :
406 169000 : *left_gain_fx = gains[0];
407 169000 : move16();
408 169000 : *right_gain_fx = gains[1];
409 169000 : move16();
410 :
411 169000 : return;
412 : }
413 :
414 : /*-------------------------------------------------------------------------*
415 : * ivas_omasa_separate_object_renderer_open()
416 : *
417 : * Open structures, reserve memory, and init values.
418 : *-------------------------------------------------------------------------*/
419 :
420 494 : ivas_error ivas_omasa_separate_object_renderer_open(
421 : Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
422 : )
423 : {
424 : Word16 interpolator_length;
425 : Word16 i;
426 : Word16 init_interpolator_length;
427 :
428 494 : IF( ( st_ivas->hIsmRendererData = (ISM_RENDERER_HANDLE) malloc( sizeof( ISM_RENDERER_DATA ) ) ) == NULL )
429 : {
430 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM renderer \n" ) );
431 : }
432 :
433 2470 : FOR( i = 0; i < MAX_NUM_OBJECTS; i++ )
434 : {
435 1976 : set32_fx( st_ivas->hIsmRendererData->prev_gains_fx[i], 0, MAX_OUTPUT_CHANNELS );
436 : }
437 : Word32 res_dec1, res_frac1;
438 : Word32 res_dec2, res_frac2;
439 494 : iDiv_and_mod_32( st_ivas->hDecoderConfig->output_Fs, FRAMES_PER_SEC, &res_dec1, &res_frac1, 0 );
440 494 : iDiv_and_mod_32( res_dec1, MAX_PARAM_SPATIAL_SUBFRAMES, &res_dec2, &res_frac2, 0 );
441 494 : init_interpolator_length = extract_l( res_dec2 );
442 494 : interpolator_length = init_interpolator_length;
443 494 : move16();
444 :
445 494 : st_ivas->hIsmRendererData->interpolator_fx = (Word16 *) malloc( sizeof( Word16 ) * init_interpolator_length );
446 494 : st_ivas->hIsmRendererData->interpolator_len = init_interpolator_length;
447 494 : move16();
448 118814 : FOR( i = 0; i < interpolator_length; i++ )
449 : {
450 118320 : st_ivas->hIsmRendererData->interpolator_fx[i] = div_s( i, interpolator_length );
451 118320 : move16();
452 : }
453 494 : st_ivas->hIsmRendererData->interpolator_len = interpolator_length;
454 494 : move16();
455 :
456 : #ifndef FIX_1161_REDUCE_OMASA_HEAP
457 : st_ivas->hMasaIsmData->delayBuffer_size = extract_l( ( st_ivas->hDecoderConfig->output_Fs / 50 ) / MAX_PARAM_SPATIAL_SUBFRAMES );
458 : move16();
459 :
460 : test();
461 : 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 ) )
462 : {
463 : st_ivas->hMasaIsmData->delayBuffer_nchan = 1;
464 : move16();
465 : }
466 : ELSE
467 : {
468 : st_ivas->hMasaIsmData->delayBuffer_nchan = st_ivas->nchan_ism;
469 : move16();
470 : }
471 :
472 : IF( ( st_ivas->hMasaIsmData->delayBuffer_fx = (Word32 **) malloc( st_ivas->hMasaIsmData->delayBuffer_nchan * sizeof( Word32 * ) ) ) == NULL )
473 : {
474 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM delay buffer \n" ) );
475 : }
476 :
477 : FOR( i = 0; i < st_ivas->hMasaIsmData->delayBuffer_nchan; i++ )
478 : {
479 : IF( ( st_ivas->hMasaIsmData->delayBuffer_fx[i] = (Word32 *) malloc( st_ivas->hMasaIsmData->delayBuffer_size * sizeof( Word32 ) ) ) == NULL )
480 : {
481 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for MASA ISM delay buffer \n" ) );
482 : }
483 : set32_fx( st_ivas->hMasaIsmData->delayBuffer_fx[i], 0, st_ivas->hMasaIsmData->delayBuffer_size );
484 : }
485 : #endif
486 :
487 494 : return IVAS_ERR_OK;
488 : }
489 :
490 :
491 : /*-------------------------------------------------------------------------*
492 : * ivas_omasa_separate_object_renderer_close()
493 : *
494 : * Close structures, free memory.
495 : *-------------------------------------------------------------------------*/
496 :
497 1882 : void ivas_omasa_separate_object_renderer_close(
498 : Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
499 : )
500 : {
501 : Word16 i;
502 :
503 1882 : IF( st_ivas->hMasaIsmData != NULL )
504 : {
505 1882 : IF( st_ivas->hMasaIsmData->delayBuffer_fx != NULL )
506 : {
507 1653 : FOR( i = 0; i < st_ivas->hMasaIsmData->delayBuffer_nchan; i++ )
508 : {
509 1097 : IF( st_ivas->hMasaIsmData->delayBuffer_fx[i] != NULL )
510 : {
511 1097 : free( st_ivas->hMasaIsmData->delayBuffer_fx[i] );
512 1097 : st_ivas->hMasaIsmData->delayBuffer_fx[i] = NULL;
513 : }
514 : }
515 :
516 556 : free( st_ivas->hMasaIsmData->delayBuffer_fx );
517 556 : st_ivas->hMasaIsmData->delayBuffer_fx = NULL;
518 : }
519 : }
520 :
521 1882 : ivas_ism_renderer_close( &st_ivas->hIsmRendererData );
522 :
523 1882 : return;
524 : }
525 :
526 :
527 : /*-------------------------------------------------------------------------*
528 : * ivas_omasa_separate_object_render_jbm()
529 : *
530 : * Rendering separated objects and mixing them to the parametrically rendered signals for JBM
531 : *-------------------------------------------------------------------------*/
532 :
533 2704 : void ivas_omasa_separate_object_render_jbm_fx(
534 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
535 : const UWord16 nSamplesRendered, /* i : number of samples rendered */
536 : Word32 input_fx_in[][L_FRAME48k], /* i : separated object signal Q11*/
537 : Word32 *output_fx[], /* o : rendered time signal Q11*/
538 : const Word16 subframes_rendered, /* i : number of subframes rendered */
539 : const Word16 slots_rendered /* i : number of CLDFB slots rendered */
540 : )
541 : {
542 : VBAP_HANDLE hVBAPdata;
543 : DIRAC_REND_HANDLE hDirACRend;
544 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
545 : Word16 nchan_out_woLFE, num_lfe;
546 : ISM_RENDERER_HANDLE hRendererData;
547 : Word16 j, k, j2;
548 : Word16 obj;
549 : Word32 gains_fx[MAX_OUTPUT_CHANNELS];
550 : Word16 g1_fx, g2_fx;
551 : Word16 lfe_index;
552 : Word16 azimuth, elevation;
553 : Word16 num_objects;
554 : UWord8 single_separated;
555 : Word32 *input_fx[MAX_TRANSPORT_CHANNELS];
556 : Word32 *output_fx_local[MAX_OUTPUT_CHANNELS];
557 : Word16 offsetSamples;
558 : Word16 n_samples_sf, md_idx;
559 : Word16 slots_to_render, first_sf, last_sf, subframe_idx;
560 :
561 2704 : hVBAPdata = st_ivas->hVBAPdata;
562 2704 : hDirACRend = st_ivas->hDirACRend;
563 2704 : hSpatParamRendCom = st_ivas->hSpatParamRendCom;
564 2704 : nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE;
565 2704 : move16();
566 2704 : num_lfe = st_ivas->hIntSetup.num_lfe;
567 2704 : move16();
568 2704 : hRendererData = st_ivas->hIsmRendererData;
569 2704 : lfe_index = hDirACRend->hOutSetup.index_lfe[0];
570 2704 : move16();
571 :
572 2704 : test();
573 2704 : 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 ) )
574 : {
575 1633 : single_separated = 1;
576 1633 : move16();
577 1633 : num_objects = 1;
578 1633 : move16();
579 : }
580 : ELSE
581 : {
582 1071 : single_separated = 0;
583 1071 : move16();
584 1071 : num_objects = st_ivas->nchan_ism;
585 1071 : move16();
586 : }
587 :
588 2704 : offsetSamples = i_mult( slots_rendered, hSpatParamRendCom->slot_size );
589 :
590 27902 : FOR( j = 0; j < nchan_out_woLFE + num_lfe; j++ )
591 : {
592 25198 : output_fx_local[j] = output_fx[j];
593 : }
594 :
595 2704 : IF( st_ivas->hDecoderConfig->Opt_tsm )
596 : {
597 2515 : FOR( obj = 0; obj < num_objects; obj++ )
598 : {
599 1611 : input_fx[obj] = &st_ivas->hTcBuffer->tc_fx[obj + 2][offsetSamples];
600 1611 : move32();
601 : }
602 : }
603 : ELSE
604 : {
605 4574 : FOR( obj = 0; obj < num_objects; obj++ )
606 : {
607 2774 : input_fx[obj] = input_fx_in[obj];
608 2774 : move32();
609 : }
610 : }
611 :
612 2704 : slots_to_render = idiv1616( nSamplesRendered, hSpatParamRendCom->slot_size );
613 2704 : first_sf = subframes_rendered;
614 2704 : move16();
615 2704 : last_sf = first_sf;
616 2704 : move16();
617 :
618 12181 : WHILE( slots_to_render > 0 )
619 : {
620 9477 : slots_to_render = sub( slots_to_render, hSpatParamRendCom->subframe_nbslots[last_sf] );
621 9477 : last_sf = add( last_sf, 1 );
622 : }
623 :
624 7089 : FOR( obj = 0; obj < num_objects; obj++ )
625 : {
626 : /* Delay the signal to match CLDFB delay. Delay the whole buffer with the first rendering call of the stretched buffer. */
627 4385 : offsetSamples = 0;
628 4385 : move16();
629 :
630 19478 : FOR( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
631 : {
632 15093 : n_samples_sf = i_mult( hSpatParamRendCom->subframe_nbslots[subframe_idx], hSpatParamRendCom->slot_size );
633 15093 : IF( n_samples_sf != hRendererData->interpolator_len )
634 : {
635 11469 : FOR( k = 0; k < n_samples_sf; k++ )
636 : {
637 11400 : hRendererData->interpolator_fx[k] = div_s( k, n_samples_sf );
638 11400 : move16();
639 : }
640 69 : hRendererData->interpolator_len = n_samples_sf;
641 69 : move16();
642 : }
643 :
644 15093 : md_idx = hSpatParamRendCom->render_to_md_map[subframe_idx];
645 15093 : move16();
646 :
647 15093 : IF( single_separated )
648 : {
649 5653 : azimuth = st_ivas->hMasaIsmData->azimuth_separated_ism[md_idx];
650 5653 : move16();
651 5653 : elevation = st_ivas->hMasaIsmData->elevation_separated_ism[md_idx];
652 5653 : move16();
653 : }
654 : ELSE
655 : {
656 9440 : azimuth = st_ivas->hMasaIsmData->azimuth_ism[obj][md_idx];
657 9440 : move16();
658 9440 : elevation = st_ivas->hMasaIsmData->elevation_ism[obj][md_idx];
659 9440 : move16();
660 : }
661 :
662 15093 : if ( st_ivas->hOutSetup.is_planar_setup )
663 : {
664 : /* If no elevation support in output format, then rendering should be done with zero elevation */
665 665 : elevation = 0;
666 665 : move16();
667 : }
668 :
669 15093 : IF( hVBAPdata != NULL )
670 : {
671 6103 : vbap_determine_gains_fx( hVBAPdata, gains_fx, azimuth, elevation, 1 );
672 : }
673 : ELSE
674 : {
675 8990 : ivas_dirac_dec_get_response_fx( azimuth, elevation, gains_fx, hDirACRend->hOutSetup.ambisonics_order, Q29 );
676 : }
677 :
678 170486 : FOR( j = 0; j < nchan_out_woLFE; j++ )
679 : {
680 155393 : IF( hDirACRend->hOutSetup.num_lfe > 0 )
681 : {
682 51729 : j2 = add( j, extract_l( GE_16( j, lfe_index ) ) );
683 : }
684 : ELSE
685 : {
686 103664 : j2 = j;
687 103664 : move16();
688 : }
689 :
690 155393 : test();
691 155393 : IF( ( L_abs( gains_fx[j] ) > 0 ) || ( L_abs( hRendererData->prev_gains_fx[obj][j] ) > 0 ) )
692 : {
693 23938638 : FOR( k = 0; k < n_samples_sf; k++ )
694 : {
695 23819280 : g1_fx = hRendererData->interpolator_fx[k];
696 23819280 : move16();
697 23819280 : g2_fx = sub( 32767, g1_fx ); // 32767 = 1.0f in Q15
698 :
699 23819280 : 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)
700 23819280 : move32();
701 : }
702 : }
703 155393 : hRendererData->prev_gains_fx[obj][j] = gains_fx[j];
704 155393 : move32();
705 : }
706 :
707 15093 : offsetSamples = add( offsetSamples, n_samples_sf );
708 : }
709 : }
710 :
711 2704 : return;
712 : }
|