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