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