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 "prot_fx.h"
36 : #include "ivas_prot_rend_fx.h"
37 : #include <math.h>
38 : #include "ivas_rom_com.h"
39 : #include "wmc_auto.h"
40 : #include "ivas_prot_fx.h"
41 : #include "debug.h"
42 :
43 :
44 : /*---------------------------------------------------------------------*
45 : * ivas_td_binaural_open()
46 : *
47 : * Open and initialize TD Object binaural renderer
48 : *---------------------------------------------------------------------*/
49 :
50 202 : ivas_error ivas_td_binaural_open_fx(
51 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
52 : Word16 *SrcInd, /*Temporarily used to store the updated value of SrcInd*/
53 : Word16 *num_src )
54 : {
55 202 : *num_src = st_ivas->nchan_transport;
56 202 : move16();
57 :
58 202 : test();
59 202 : if ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) )
60 : {
61 170 : *num_src = st_ivas->nchan_ism;
62 170 : move16();
63 : }
64 :
65 : #ifdef FIX_HRTF_LOAD
66 202 : if ( st_ivas->hHrtfTD == NULL && st_ivas->hDecoderConfig->Opt_HRTF_binary &&
67 0 : ( st_ivas->ivas_format != SBA_ISM_FORMAT ) // ToDo: temporary hack to avoid ASAN errors -> see issue #1202
68 : )
69 : {
70 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "HRTF binary file present but not used in TD renderer" );
71 : }
72 :
73 : #endif
74 202 : return ivas_td_binaural_open_unwrap_fx( &st_ivas->hHrtfTD, st_ivas->hDecoderConfig->output_Fs, *num_src, st_ivas->ivas_format, st_ivas->transport_config, st_ivas->hRenderConfig->directivity_fx, st_ivas->hRenderConfig->distAtt_fx, st_ivas->hTransSetup, &st_ivas->hBinRendererTd, &st_ivas->binaural_latency_ns, SrcInd );
75 : }
76 :
77 :
78 : /*---------------------------------------------------------------------*
79 : * ivas_td_binaural_renderer_sf()
80 : *
81 : * Receives the current frames for the object streams, updates metadata
82 : * and renders the current frame.
83 : *---------------------------------------------------------------------*/
84 :
85 41994 : ivas_error ivas_td_binaural_renderer_sf_fx(
86 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
87 : Word32 *output_fx[], /* i/o: SCE channels / Binaural synthesis Q11*/
88 : const Word16 n_samples_granularity /* i : granularity of the renderer/buffer */
89 : )
90 : {
91 : Word16 first_sf, last_sf, subframe_idx;
92 : Word32 *output_fx_local[BINAURAL_CHANNELS];
93 : Word32 reverb_signal_fx[BINAURAL_CHANNELS][L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES];
94 : Word32 *p_reverb_signal_fx[BINAURAL_CHANNELS];
95 : Word32 *tc_local_fx[MAX_TRANSPORT_CHANNELS];
96 : Word16 ch, slot_size, slots_to_render, output_frame, tmp;
97 : ivas_error error;
98 :
99 : Word16 ism_md_subframe_update_jbm;
100 : Word16 c_indx, nS, i;
101 : Word16 nchan_ism_internal, nchan_ism, ch_offset;
102 :
103 : IVAS_QUATERNION *tmp_Quaternion_fx;
104 : IVAS_VECTOR3 *tmp_vector_fx;
105 : Word16 enableCombinedOrientation;
106 :
107 : /* Set the number of ISMs */
108 41994 : test();
109 41994 : test();
110 41994 : IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) || ( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && GT_16( st_ivas->nchan_ism, 0 ) ) )
111 : {
112 126 : nchan_ism_internal = st_ivas->nchan_ism;
113 126 : move16();
114 126 : nchan_ism = st_ivas->nchan_ism;
115 126 : move16();
116 126 : ch_offset = 2;
117 126 : move16();
118 : }
119 41868 : ELSE IF( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) )
120 : {
121 9250 : nchan_ism_internal = st_ivas->nchan_ism;
122 9250 : move16();
123 9250 : nchan_ism = st_ivas->nchan_ism;
124 9250 : move16();
125 9250 : ch_offset = 0;
126 9250 : move16();
127 : }
128 : ELSE
129 : {
130 32618 : nchan_ism_internal = st_ivas->hTcBuffer->nchan_transport_internal;
131 32618 : move16();
132 32618 : nchan_ism = st_ivas->nchan_transport;
133 32618 : move16();
134 32618 : ch_offset = 0;
135 32618 : move16();
136 : }
137 :
138 : /* Number of subframes to delay metadata to sync with audio */
139 41994 : IF( st_ivas->hDecoderConfig->Opt_delay_comp )
140 : {
141 41104 : ism_md_subframe_update_jbm = s_max( 0, sub( st_ivas->hTcBuffer->nb_subframes, 3 ) );
142 : }
143 : ELSE
144 : {
145 890 : ism_md_subframe_update_jbm = sub( st_ivas->hTcBuffer->nb_subframes, 2 );
146 : }
147 :
148 41994 : IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
149 : {
150 126 : ism_md_subframe_update_jbm = s_max( 0, sub( st_ivas->hTcBuffer->nb_subframes, 2 ) );
151 : }
152 :
153 125982 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
154 : {
155 83988 : p_reverb_signal_fx[ch] = reverb_signal_fx[ch];
156 : }
157 172746 : FOR( ch = 0; ch < nchan_ism_internal; ch++ )
158 : {
159 130752 : tc_local_fx[ch] = st_ivas->hTcBuffer->tc_fx[ch + ch_offset] + st_ivas->hTcBuffer->n_samples_rendered;
160 : }
161 :
162 125982 : FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ )
163 : {
164 83988 : output_fx_local[ch] = output_fx[ch]; // Q11
165 : }
166 :
167 41994 : slot_size = st_ivas->hTcBuffer->n_samples_granularity;
168 41994 : move16();
169 :
170 : /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */
171 41994 : tmp = 0;
172 41994 : move16();
173 41994 : IF( n_samples_granularity != 0 )
174 : {
175 41994 : tmp = idiv1616( n_samples_granularity, slot_size );
176 : }
177 41994 : slots_to_render = s_min( sub( st_ivas->hTcBuffer->num_slots, st_ivas->hTcBuffer->slots_rendered ), tmp );
178 41994 : first_sf = st_ivas->hTcBuffer->subframes_rendered;
179 41994 : move16();
180 41994 : last_sf = first_sf;
181 41994 : move16();
182 41994 : st_ivas->hTcBuffer->slots_rendered = add( st_ivas->hTcBuffer->slots_rendered, slots_to_render );
183 41994 : move16();
184 :
185 208696 : WHILE( slots_to_render > 0 )
186 : {
187 166702 : slots_to_render = sub( slots_to_render, st_ivas->hTcBuffer->subframe_nbslots[last_sf] );
188 166702 : last_sf = add( last_sf, 1 );
189 : }
190 :
191 208696 : FOR( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
192 : {
193 166702 : output_frame = i_mult( st_ivas->hTcBuffer->subframe_nbslots[subframe_idx], st_ivas->hTcBuffer->n_samples_granularity );
194 :
195 : /* Update object position(s) */
196 166702 : c_indx = 0;
197 166702 : move16();
198 :
199 686456 : FOR( nS = 0; nS < nchan_ism; nS++ )
200 : {
201 519754 : test();
202 519754 : IF( !( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_16( nS, LFE_CHANNEL ) ) ) /* Skip LFE for MC */
203 : {
204 507261 : st_ivas->hBinRendererTd->Sources[c_indx]->InputFrame_p_fx = tc_local_fx[nS]; /* Q11 */
205 507261 : st_ivas->hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE;
206 507261 : move16();
207 507261 : c_indx = add( c_indx, 1 );
208 : }
209 : }
210 :
211 166702 : IF( EQ_16( subframe_idx, ism_md_subframe_update_jbm ) )
212 : {
213 : #ifdef OBJ_EDITING_API
214 41585 : test();
215 41585 : IF( EQ_16( st_ivas->ivas_format, ISM_FORMAT ) || EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) )
216 38350 : {
217 : ISM_METADATA_FRAME ismMetaData[MAX_NUM_OBJECTS];
218 : ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS];
219 148680 : FOR( nS = 0; nS < nchan_ism; nS++ )
220 : {
221 110330 : ismMetaData[nS].azimuth_fx = st_ivas->hIsmMetaData[nS]->edited_azimuth_fx;
222 110330 : move32();
223 110330 : ismMetaData[nS].elevation_fx = st_ivas->hIsmMetaData[nS]->edited_elevation_fx;
224 110330 : move32();
225 110330 : ismMetaData[nS].radius_fx = st_ivas->hIsmMetaData[nS]->edited_radius_fx;
226 110330 : move16();
227 110330 : ismMetaData[nS].yaw_fx = st_ivas->hIsmMetaData[nS]->edited_yaw_fx;
228 110330 : move32();
229 110330 : ismMetaData[nS].pitch_fx = st_ivas->hIsmMetaData[nS]->edited_pitch_fx;
230 110330 : move32();
231 110330 : ismMetaData[nS].non_diegetic_flag = st_ivas->hIsmMetaData[nS]->non_diegetic_flag;
232 110330 : move16();
233 110330 : ismMetaData[nS].gain_fx = st_ivas->hIsmMetaData[nS]->edited_gain_fx;
234 110330 : move32();
235 110330 : hIsmMetaData[nS] = &ismMetaData[nS];
236 : }
237 :
238 38350 : IF( NE_16( ( error = TDREND_Update_object_positions_fx( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, hIsmMetaData ) ), IVAS_ERR_OK ) )
239 : {
240 0 : return error;
241 : }
242 : }
243 : else
244 : #endif
245 : {
246 3235 : IF( NE_16( error = TDREND_Update_object_positions_fx( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, st_ivas->hIsmMetaData ), IVAS_ERR_OK ) )
247 : {
248 0 : return error;
249 : }
250 : }
251 : }
252 :
253 : /* Update the listener's location/orientation */
254 166702 : IF( st_ivas->hCombinedOrientationData != NULL )
255 : {
256 85693 : tmp_Quaternion_fx = &st_ivas->hCombinedOrientationData->Quaternions[st_ivas->hCombinedOrientationData->subframe_idx];
257 85693 : tmp_vector_fx = &st_ivas->hCombinedOrientationData->listenerPos[st_ivas->hCombinedOrientationData->subframe_idx];
258 85693 : enableCombinedOrientation = st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx];
259 85693 : move16();
260 :
261 : /* Shifting x_fx, y_fx, z_fx to the same Q-factor as Listener_p->Pos_q (usually Q25) */
262 85693 : Word16 pos_q = st_ivas->hBinRendererTd->Listener_p->Pos_q;
263 85693 : move16();
264 85693 : tmp_vector_fx->x_fx = L_shr( tmp_vector_fx->x_fx, sub( tmp_vector_fx->q_fact, pos_q ) );
265 85693 : tmp_vector_fx->y_fx = L_shr( tmp_vector_fx->y_fx, sub( tmp_vector_fx->q_fact, pos_q ) );
266 85693 : tmp_vector_fx->z_fx = L_shr( tmp_vector_fx->z_fx, sub( tmp_vector_fx->q_fact, pos_q ) );
267 85693 : tmp_vector_fx->q_fact = pos_q;
268 85693 : move16();
269 : }
270 : ELSE
271 : {
272 81009 : tmp_Quaternion_fx = NULL;
273 81009 : tmp_vector_fx = NULL;
274 81009 : enableCombinedOrientation = 0;
275 81009 : move16();
276 : }
277 :
278 166702 : IF( NE_32( ( error = TDREND_Update_listener_orientation_fx( st_ivas->hBinRendererTd, enableCombinedOrientation, tmp_Quaternion_fx, tmp_vector_fx ) ), IVAS_ERR_OK ) )
279 : {
280 0 : return error;
281 : }
282 :
283 166702 : test();
284 166702 : IF( st_ivas->hRenderConfig != NULL && EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
285 : {
286 122347 : FOR( i = 0; i < nchan_ism_internal; ++i )
287 : {
288 98604 : scale_sig32( tc_local_fx[i], st_ivas->hReverb->full_block_size, -4 ); // Q11 - 4 = Q7
289 : }
290 :
291 23743 : IF( NE_32( ( error = ivas_reverb_process_fx( st_ivas->hReverb, st_ivas->transport_config, 0, tc_local_fx, p_reverb_signal_fx, 0 ) ), IVAS_ERR_OK ) ) // Q(p_reverb_signal_fx) = 11
292 : {
293 0 : return error;
294 : }
295 :
296 122347 : FOR( i = 0; i < nchan_ism_internal; ++i )
297 : {
298 98604 : scale_sig32( tc_local_fx[i], st_ivas->hReverb->full_block_size, 4 ); // Q7 + 4 = Q11
299 : }
300 :
301 71229 : FOR( i = 0; i < BINAURAL_CHANNELS; ++i )
302 : {
303 47486 : scale_sig32( p_reverb_signal_fx[i], st_ivas->hReverb->full_block_size, 2 + 4 ); // Q5 + 6 = Q11
304 : }
305 : }
306 :
307 : /* Render subframe */
308 : /* ism_md_subframe_update_jbm != subframe_idx: trigger update only for ism_md_subframe_update_jbm == subframe_idx,
309 : where then the two TDREND_GetMix()-arguments subframe_idx and ism_md_subframe_update are equal, and we want to enforce the update inside TDREND_GetMix to use subframe_idx == 0 */
310 166702 : IF( NE_32( ( error = TDREND_GetMix_fx( st_ivas->hBinRendererTd, output_fx_local, output_frame, 0 ) ), IVAS_ERR_OK ) )
311 : {
312 0 : return error;
313 : }
314 :
315 166702 : test();
316 166702 : IF( st_ivas->hRenderConfig != NULL && EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
317 : {
318 : /* add reverb to rendered signals */
319 23743 : v_add_32( reverb_signal_fx[0], output_fx_local[0], output_fx_local[0], output_frame ); // Q11
320 23743 : v_add_32( reverb_signal_fx[1], output_fx_local[1], output_fx_local[1], output_frame );
321 : }
322 :
323 686468 : FOR( ch = 0; ch < nchan_ism_internal; ch++ )
324 : {
325 519766 : tc_local_fx[ch] += output_frame;
326 : }
327 :
328 500106 : FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ )
329 : {
330 333404 : output_fx_local[ch] += output_frame;
331 : }
332 :
333 : /* update combined orientation access index */
334 166702 : ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, output_frame );
335 : }
336 :
337 41994 : st_ivas->hTcBuffer->subframes_rendered = last_sf;
338 41994 : move16();
339 :
340 41994 : return IVAS_ERR_OK;
341 : }
342 :
343 : /*---------------------------------------------------------------------*
344 : * ivas_td_binaural_renderer_sf_splitBinaural()
345 : *
346 : * Render to multiple binaural pairs based on relative head positions for split rendering.
347 : *---------------------------------------------------------------------*/
348 :
349 0 : ivas_error ivas_td_binaural_renderer_sf_splitBinaural(
350 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
351 : Word32 *output[], /* i/o: SCE channels / Binaural synthesis */
352 : const Word16 nSamplesRendered /* i : number of samples to render */
353 : )
354 : {
355 : Word16 i;
356 : Word16 pos_idx;
357 : IVAS_QUATERNION originalHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES];
358 : MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
359 : BINAURAL_TD_OBJECT_RENDERER_HANDLE origTdRendHandle;
360 : ivas_error error;
361 : Word16 original_subframes_rendered;
362 : Word16 original_slots_rendered;
363 : Word32 *p_bin_output[BINAURAL_CHANNELS];
364 : Word32 output_local[MAX_OUTPUT_CHANNELS][L_FRAME48k];
365 : Word16 q_fact_orig[MAX_PARAM_SPATIAL_SUBFRAMES];
366 :
367 : Word16 SrcInd[MAX_NUM_TDREND_CHANNELS];
368 :
369 0 : pMultiBinPoseData = &st_ivas->hSplitBinRend->splitrend.multiBinPoseData;
370 0 : move32();
371 :
372 : /* If not yet allocated, open additional instances of TD renderer */
373 0 : FOR( i = 0; i < pMultiBinPoseData->num_poses - 1; ++i )
374 : {
375 0 : IF( st_ivas->hTdRendHandles[i] != NULL )
376 : {
377 0 : continue;
378 : }
379 0 : IF( ( error = ivas_td_binaural_open_unwrap_fx( &st_ivas->hHrtfTD,
380 : st_ivas->hDecoderConfig->output_Fs,
381 : st_ivas->nchan_transport,
382 : st_ivas->ivas_format,
383 : st_ivas->transport_config,
384 : st_ivas->hRenderConfig->directivity_fx,
385 : st_ivas->hRenderConfig->distAtt_fx,
386 : st_ivas->hTransSetup,
387 : &st_ivas->hTdRendHandles[i],
388 : &st_ivas->binaural_latency_ns,
389 : SrcInd ) ) != IVAS_ERR_OK )
390 : {
391 0 : return error;
392 : }
393 : }
394 :
395 : /* Save current head positions */
396 0 : FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i )
397 : {
398 0 : originalHeadRot[i] = st_ivas->hCombinedOrientationData->Quaternions[i];
399 0 : q_fact_orig[i] = originalHeadRot[i].q_fact;
400 : }
401 :
402 0 : original_subframes_rendered = st_ivas->hTcBuffer->subframes_rendered;
403 0 : move16();
404 0 : original_slots_rendered = st_ivas->hTcBuffer->slots_rendered;
405 0 : move16();
406 0 : origTdRendHandle = st_ivas->hBinRendererTd;
407 0 : move32();
408 :
409 0 : FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i )
410 : {
411 0 : modify_Quat_q_fx( &originalHeadRot[i], &originalHeadRot[i], Q22 );
412 : }
413 :
414 0 : FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
415 : {
416 : /* Update head positions */
417 0 : IF( NE_16( pos_idx, 0 ) )
418 : {
419 0 : COMBINED_ORIENTATION_HANDLE pCombinedOrientationData = st_ivas->hCombinedOrientationData;
420 0 : FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i )
421 : {
422 0 : pCombinedOrientationData->Quaternions[i].w_fx = L_negate( 12582912 ); // Q22
423 : /*euler*/
424 0 : Quat2EulerDegree_fx( originalHeadRot[i],
425 0 : &pCombinedOrientationData->Quaternions[i].z_fx,
426 0 : &pCombinedOrientationData->Quaternions[i].y_fx,
427 0 : &pCombinedOrientationData->Quaternions[i].x_fx );
428 0 : pCombinedOrientationData->Quaternions[i].x_fx = L_add( pCombinedOrientationData->Quaternions[i].x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] );
429 0 : pCombinedOrientationData->Quaternions[i].y_fx = L_add( pCombinedOrientationData->Quaternions[i].y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] );
430 0 : pCombinedOrientationData->Quaternions[i].z_fx = L_add( pCombinedOrientationData->Quaternions[i].z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] );
431 :
432 0 : Euler2Quat_fx( deg2rad_fx( pCombinedOrientationData->Quaternions[i].x_fx ),
433 : deg2rad_fx( pCombinedOrientationData->Quaternions[i].y_fx ),
434 0 : deg2rad_fx( pCombinedOrientationData->Quaternions[i].z_fx ), &pCombinedOrientationData->Quaternions[i] );
435 :
436 0 : modify_Quat_q_fx( &pCombinedOrientationData->Quaternions[i], &pCombinedOrientationData->Quaternions[i], q_fact_orig[i] );
437 : }
438 : }
439 :
440 : /* set output channels */
441 0 : FOR( i = 0; i < BINAURAL_CHANNELS; i++ )
442 : {
443 0 : p_bin_output[i] = output_local[add( i_mult( pos_idx, BINAURAL_CHANNELS ), i )];
444 0 : move32();
445 : }
446 0 : st_ivas->hTcBuffer->subframes_rendered = original_subframes_rendered;
447 0 : move16();
448 0 : st_ivas->hTcBuffer->slots_rendered = original_slots_rendered;
449 0 : move16();
450 :
451 : /* update combined orientation access index */
452 0 : ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData );
453 :
454 : /* Render */
455 0 : IF( NE_16( pos_idx, 0 ) )
456 : {
457 0 : st_ivas->hBinRendererTd = st_ivas->hTdRendHandles[sub( pos_idx, 1 )];
458 0 : move32();
459 : }
460 :
461 0 : IF( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_bin_output, nSamplesRendered ) ) != IVAS_ERR_OK )
462 : {
463 0 : return error;
464 : }
465 :
466 0 : IF( EQ_16( st_ivas->ivas_format, MC_FORMAT ) )
467 : {
468 : Word32 *p_tc[MAX_TRANSPORT_CHANNELS];
469 0 : FOR( i = 0; i < st_ivas->nchan_transport; i++ )
470 : {
471 0 : p_tc[i] = st_ivas->hTcBuffer->tc_fx[i] + st_ivas->hTcBuffer->n_samples_rendered;
472 : }
473 0 : ivas_binaural_add_LFE_fx( st_ivas, nSamplesRendered, p_tc, p_bin_output );
474 : }
475 : }
476 :
477 0 : FOR( i = 0; i < i_mult( pMultiBinPoseData->num_poses, BINAURAL_CHANNELS ); i++ )
478 : {
479 0 : Copy32( output_local[i], output[i], nSamplesRendered );
480 : }
481 :
482 : /* Restore original head rotation */
483 0 : FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i )
484 : {
485 0 : modify_Quat_q_fx( &originalHeadRot[i], &originalHeadRot[i], q_fact_orig[i] );
486 0 : st_ivas->hCombinedOrientationData->Quaternions[i] = originalHeadRot[i];
487 0 : move32();
488 : }
489 :
490 : /* restore original td renderer handle */
491 0 : st_ivas->hBinRendererTd = origTdRendHandle;
492 0 : move32();
493 :
494 0 : return IVAS_ERR_OK;
495 : }
|