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 "ivas_stat_rend.h"
34 : #include <stdint.h>
35 : #include "options.h"
36 : #include "prot_fx.h"
37 : #include "ivas_prot_rend_fx.h"
38 : #include <math.h>
39 : #include "ivas_rom_com.h"
40 : #include "wmc_auto.h"
41 : #include "ivas_prot_fx.h"
42 : #include "debug.h"
43 :
44 :
45 : /*---------------------------------------------------------------------*
46 : * Local function prototypes
47 : *---------------------------------------------------------------------*/
48 :
49 : static void TDREND_Clear_Update_flags_fx(
50 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd /* i/o: TD renderer handle */
51 : );
52 :
53 :
54 : static void angles_to_vec_fx(
55 : const Word16 radius, /* i : radius */
56 : const Word32 azimuth, /* i : Azimuth angle */
57 : const Word32 elevation, /* i : Elevation angle */
58 : Word32 *vec /* o : Pos/Dir vector */
59 : );
60 :
61 : /*---------------------------------------------------------------------*
62 : * ivas_td_binaural_open_unwrap()
63 : *
64 : * Call TD open/init function without st_ivas
65 : *---------------------------------------------------------------------*/
66 :
67 939 : ivas_error ivas_td_binaural_open_unwrap_fx(
68 : TDREND_HRFILT_FiltSet_t **hHrtfTD, /* i/o: HR filter model (from file or NULL) */
69 : const Word32 output_Fs, /* i : Output sampling rate */
70 : const Word16 nchan_transport, /* i : Number of channels */
71 : const IVAS_FORMAT ivas_format, /* i : IVAS format (ISM/MC) */
72 : const AUDIO_CONFIG transport_config, /* i : Transport configuration */
73 : const Word16 *directivity, /* i : Directivity pattern (used for ISM) */
74 : const Word32 *distAtt, /* i : Distance attenuation (used for ISM) */
75 : const IVAS_OUTPUT_SETUP hTransSetup, /* i : Loudspeaker layout */
76 : BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd, /* o : TD renderer handle */
77 : Word32 *binaural_latency_ns, /* i : Binauralization delay */
78 : Word16 *SrcInd )
79 : {
80 : BINAURAL_TD_OBJECT_RENDERER_HANDLE pBinRendTd;
81 : TDREND_PosType_t PosType;
82 : Word16 nS;
83 : const Word32 *ls_azimuth_fx, *ls_elevation_fx;
84 : Word32 Pos_fx[3]; // Q25
85 : Word32 Dir_fx[3]; // Q30
86 : TDREND_DirAtten_t *DirAtten_p;
87 : TDREND_DistAtten_t DistAtten;
88 : Word16 nchan_rend;
89 : ivas_error error;
90 :
91 939 : error = IVAS_ERR_OK;
92 :
93 939 : IF( ( pBinRendTd = malloc( sizeof( BINAURAL_TD_OBJECT_RENDERER ) ) ) == NULL )
94 : {
95 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
96 : }
97 939 : IF( ( pBinRendTd->TdRend_MixSpatSpec_p = malloc( sizeof( TDREND_MixSpatSpec_t ) ) ) == NULL )
98 : {
99 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
100 : }
101 939 : IF( ( pBinRendTd->DirAtten_p = malloc( sizeof( TDREND_DirAtten_t ) ) ) == NULL )
102 : {
103 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
104 : }
105 939 : IF( ( pBinRendTd->Listener_p = malloc( sizeof( TDREND_MIX_Listener_t ) ) ) == NULL )
106 : {
107 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
108 : }
109 :
110 939 : pBinRendTd->NumOfSrcs = 0;
111 939 : pBinRendTd->MaxSrcInd = -1;
112 :
113 939 : move16();
114 939 : move16();
115 : /* Mixer spatial setup */
116 939 : pBinRendTd->TdRend_MixSpatSpec_p->UseCommonDistAttenModel = TRUE;
117 939 : move16();
118 939 : pBinRendTd->TdRend_MixSpatSpec_p->DistAttenModel = 0; /* 0=Turned off, else use TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED */
119 939 : move16();
120 :
121 939 : IF( NE_32( ( error = TDREND_MIX_Init_fx( pBinRendTd, hHrtfTD, pBinRendTd->TdRend_MixSpatSpec_p, output_Fs ) ), IVAS_ERR_OK ) )
122 : {
123 0 : return error;
124 : }
125 :
126 : /* Set the attenuation (or can set MixSpatSpec.DistAttenModel above) */
127 939 : IF( NE_32( ( error = TDREND_MIX_SetDistAttenModel( pBinRendTd, TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED ) ), IVAS_ERR_OK ) )
128 : {
129 0 : return error;
130 : }
131 :
132 : /* Add sources to module and mixer, headphones */
133 939 : PosType = TDREND_POSTYPE_ABSOLUTE; /* or TDREND_POSTYPE_RELATIVE_TO_LISTENER */
134 939 : move16();
135 939 : nchan_rend = nchan_transport;
136 939 : move16();
137 939 : test();
138 939 : if ( EQ_16( ivas_format, MC_FORMAT ) && NE_16( transport_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
139 : {
140 19 : nchan_rend = sub( nchan_rend, 1 ); /* Skip LFE channel -- added to the others */
141 : }
142 :
143 2578 : FOR( nS = 0; nS < nchan_rend; nS++ )
144 : {
145 1639 : IF( NE_32( ( error = TDREND_MIX_AddSrc_fx( pBinRendTd, &SrcInd[nS], PosType ) ), IVAS_ERR_OK ) )
146 : {
147 0 : return error;
148 : }
149 : }
150 939 : IF( EQ_16( ivas_format, MC_FORMAT ) )
151 : {
152 43 : SWITCH( transport_config )
153 : {
154 7 : case IVAS_AUDIO_CONFIG_5_1:
155 7 : ls_azimuth_fx = ls_azimuth_CICP6_fx; // Q22
156 7 : ls_elevation_fx = ls_elevation_CICP6_fx; // Q22
157 7 : BREAK;
158 12 : case IVAS_AUDIO_CONFIG_7_1:
159 12 : ls_azimuth_fx = ls_azimuth_CICP12_fx; // Q22
160 12 : ls_elevation_fx = ls_elevation_CICP12_fx; // Q22
161 12 : BREAK;
162 0 : case IVAS_AUDIO_CONFIG_5_1_2:
163 0 : ls_azimuth_fx = ls_azimuth_CICP14_fx; // Q22
164 0 : ls_elevation_fx = ls_elevation_CICP14_fx; // Q22
165 0 : BREAK;
166 0 : case IVAS_AUDIO_CONFIG_5_1_4:
167 0 : ls_azimuth_fx = ls_azimuth_CICP16_fx; // Q22
168 0 : ls_elevation_fx = ls_elevation_CICP16_fx; // Q22
169 0 : BREAK;
170 0 : case IVAS_AUDIO_CONFIG_7_1_4:
171 0 : ls_azimuth_fx = ls_azimuth_CICP19_fx; // Q22
172 0 : ls_elevation_fx = ls_elevation_CICP19_fx; // Q22
173 0 : BREAK;
174 24 : case IVAS_AUDIO_CONFIG_LS_CUSTOM:
175 24 : ls_azimuth_fx = hTransSetup.ls_azimuth_fx; // Q22
176 24 : ls_elevation_fx = hTransSetup.ls_elevation_fx; // Q22
177 24 : BREAK;
178 0 : default:
179 0 : ls_azimuth_fx = NULL;
180 0 : ls_elevation_fx = NULL;
181 : }
182 :
183 43 : DirAtten_p = pBinRendTd->DirAtten_p;
184 :
185 318 : FOR( nS = 0; nS < nchan_rend; nS++ )
186 : {
187 : /* Set source positions according to loudspeaker layout */
188 275 : angles_to_vec_fx( ONE_IN_Q9, ls_azimuth_fx[nS], ls_elevation_fx[nS], Pos_fx );
189 :
190 275 : Dir_fx[0] = ONE_IN_Q30;
191 275 : move32();
192 275 : Dir_fx[1] = 0;
193 275 : move32();
194 275 : Dir_fx[2] = 0;
195 275 : move32();
196 : /* Source directivity info */
197 275 : DirAtten_p->ConeInnerAngle_fx = DEG_360_IN_Q22;
198 275 : move32();
199 275 : DirAtten_p->ConeOuterAngle_fx = DEG_360_IN_Q22;
200 275 : move32();
201 275 : DirAtten_p->ConeOuterGain_fx = ONE_IN_Q30;
202 275 : move32();
203 :
204 275 : DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED; // Q0
205 275 : move16();
206 275 : DistAtten.MaxDist_fx = 2113929216; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ /*15.75 in Q27*/
207 275 : move32();
208 275 : DistAtten.RefDist_fx = ONE_IN_Q30; // Q30
209 275 : move32();
210 275 : DistAtten.RollOffFactor_fx = ONE_IN_Q30; // Q30
211 275 : move32();
212 :
213 : // TDREND_SRC_SPATIAL_t *SrcSpatial_p = pBinRendTd->Sources[nS]->SrcSpatial_p;
214 275 : IF( NE_32( ( error = TDREND_MIX_SRC_SetPos_fx( pBinRendTd, nS, Pos_fx ) ), IVAS_ERR_OK ) )
215 : {
216 0 : return error;
217 : }
218 275 : IF( NE_32( ( error = TDREND_MIX_SRC_SetDir_fx( pBinRendTd, nS, Dir_fx, Q30 ) ), IVAS_ERR_OK ) )
219 : {
220 0 : return error;
221 : }
222 275 : IF( NE_32( ( error = TDREND_MIX_SRC_SetPlayState( pBinRendTd, nS, TDREND_PLAYSTATUS_PLAYING ) ), IVAS_ERR_OK ) )
223 : {
224 0 : return error;
225 : }
226 : /*TDREND_SRC_SPATIAL_t **/ // SrcSpatial_p = pBinRendTd->Sources[nS]->SrcSpatial_p;
227 275 : IF( NE_32( ( error = TDREND_MIX_SRC_SetDirAtten_fx( pBinRendTd, nS, DirAtten_p ) ), IVAS_ERR_OK ) )
228 : {
229 0 : return error;
230 : }
231 275 : IF( NE_32( ( error = TDREND_MIX_SRC_SetDistAtten( pBinRendTd, nS, &DistAtten ) ), IVAS_ERR_OK ) )
232 : {
233 0 : return error;
234 : }
235 : }
236 : }
237 939 : test();
238 939 : test();
239 939 : IF( EQ_16( ivas_format, ISM_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) || EQ_16( ivas_format, SBA_ISM_FORMAT ) )
240 : {
241 896 : DirAtten_p = pBinRendTd->DirAtten_p;
242 :
243 2260 : FOR( nS = 0; nS < nchan_rend; nS++ )
244 : {
245 1364 : IF( NULL == directivity )
246 : {
247 305 : DirAtten_p->ConeInnerAngle_fx = DEG_360_IN_Q22;
248 305 : DirAtten_p->ConeOuterAngle_fx = DEG_360_IN_Q22;
249 305 : DirAtten_p->ConeOuterGain_fx = ONE_IN_Q30;
250 : }
251 : ELSE
252 : {
253 1059 : DirAtten_p->ConeInnerAngle_fx = L_deposit_h( directivity[nS * 3] ); // 9Q6 -> 9Q22
254 1059 : DirAtten_p->ConeOuterAngle_fx = L_deposit_h( directivity[add( nS * 3, 1 )] ); // 9Q6 -> 9Q22
255 1059 : DirAtten_p->ConeOuterGain_fx = L_shr( L_deposit_h( directivity[add( nS * 3, 2 )] ), 1 ); // 0Q15 -> 1Q30
256 : }
257 1364 : move32();
258 1364 : move32();
259 1364 : move32();
260 1364 : if ( NULL == distAtt )
261 : {
262 305 : DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED; // Q0
263 305 : move16();
264 305 : DistAtten.MaxDist_fx = 2113929216; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ /*15.75 in Q27*/
265 305 : move32();
266 305 : DistAtten.RefDist_fx = ONE_IN_Q30; // Q30
267 305 : move32();
268 305 : DistAtten.RollOffFactor_fx = ONE_IN_Q30; // Q30
269 305 : move32();
270 : }
271 : else
272 : {
273 1059 : DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED; // Q0
274 1059 : DistAtten.MaxDist_fx = distAtt[0];
275 1059 : DistAtten.RefDist_fx = distAtt[1];
276 1059 : DistAtten.RollOffFactor_fx = distAtt[2];
277 : }
278 1364 : IF( NE_32( ( error = TDREND_MIX_SRC_SetDirAtten_fx( pBinRendTd, nS, DirAtten_p ) ), IVAS_ERR_OK ) )
279 : {
280 0 : return error;
281 : }
282 1364 : IF( NE_32( ( error = TDREND_MIX_SRC_SetDistAtten( pBinRendTd, nS, &DistAtten ) ), IVAS_ERR_OK ) )
283 : {
284 0 : return error;
285 : }
286 : }
287 : }
288 :
289 939 : *hBinRendererTd = pBinRendTd;
290 939 : test();
291 939 : IF( NE_16( ivas_format, MASA_ISM_FORMAT ) && NE_16( ivas_format, SBA_ISM_FORMAT ) )
292 : {
293 : #ifdef USE_TDREND_16BIT_ROM
294 769 : *binaural_latency_ns = L_shr_r( Mpy_32_32_r( ( *hBinRendererTd )->HrFiltSet_p->latency_s_fx, (Word32) 1000000000 ), ( *hBinRendererTd )->HrFiltSet_p->latency_s_Q_fx );
295 : #else
296 : *binaural_latency_ns = Mult_32_32( ( *hBinRendererTd )->HrFiltSet_p->latency_s_fx, 1000000000 /* 1000000000.f in Q0 */ );
297 : #endif
298 769 : move32();
299 : }
300 :
301 939 : return error;
302 : }
303 :
304 :
305 : /*---------------------------------------------------------------------*
306 : * ivas_td_binaural_close()
307 : *
308 : * Close TD Object binaural renderer
309 : *---------------------------------------------------------------------*/
310 :
311 19427 : void ivas_td_binaural_close_fx(
312 : BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd /* i/o: TD binaural object renderer handle */
313 : )
314 : {
315 19427 : test();
316 19427 : IF( hBinRendererTd == NULL || *hBinRendererTd == NULL )
317 : {
318 18488 : return;
319 : }
320 :
321 939 : free( ( *hBinRendererTd )->TdRend_MixSpatSpec_p );
322 939 : free( ( *hBinRendererTd )->DirAtten_p );
323 :
324 939 : TDREND_MIX_Dealloc_fx( *hBinRendererTd );
325 :
326 939 : free( *hBinRendererTd );
327 939 : *hBinRendererTd = NULL;
328 :
329 939 : return;
330 : }
331 :
332 :
333 : /*---------------------------------------------------------------------*
334 : * ivas_td_binaural_renderer_unwrap()
335 : *
336 : * Call ivas_td_binaural_renderer() without st_ivas.
337 : *---------------------------------------------------------------------*/
338 :
339 324504 : ivas_error ivas_td_binaural_renderer_unwrap_fx(
340 : const REVERB_HANDLE hReverb, /* i : Reverberator handle */
341 : const AUDIO_CONFIG transport_config, /* i : Transport configuration */
342 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD binaural object renderer handle */
343 : const Word16 num_src, /* i : number of sources to render */
344 : const Word16 lfe_idx, /* i : LFE channel index */
345 : const IVAS_FORMAT ivas_format, /* i : IVAS format */
346 : ISM_METADATA_HANDLE *hIsmMetaData, /* i : ISM metadata handle */
347 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientaton data handle */
348 : const Word16 ism_md_subframe_update, /* i : Number of subframes to delay ism metadata to sync with audio */
349 : Word32 *output_fx[], /* i/o: SCE channels / Binaural synthesis Q11 */
350 : const Word16 output_frame, /* i : output frame length */
351 : const Word16 num_subframes /* i : number of subframes to render */
352 : )
353 : {
354 : Word16 subframe_length;
355 : Word16 subframe_idx;
356 : ivas_error error;
357 : Word16 c_indx, nS;
358 : Word16 ch;
359 : Word16 *enableCombinedOrientation; /* i : Combined orientation flag */
360 : IVAS_QUATERNION *Quaternions; /* i : Head tracking data per subframe */
361 : IVAS_VECTOR3 *Pos; /* i : Listener position data per subframe */
362 :
363 :
364 : Word32 reverb_signal_fx[BINAURAL_CHANNELS][L_FRAME48k];
365 : Word32 *p_reverb_signal_fx[BINAURAL_CHANNELS];
366 :
367 324504 : enableCombinedOrientation = NULL;
368 324504 : Quaternions = NULL;
369 324504 : Pos = NULL;
370 324504 : IF( hCombinedOrientationData != NULL )
371 : {
372 168002 : enableCombinedOrientation = hCombinedOrientationData->enableCombinedOrientation;
373 168002 : Quaternions = hCombinedOrientationData->Quaternions;
374 168002 : Pos = hCombinedOrientationData->listenerPos;
375 168002 : move16();
376 : }
377 :
378 973512 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
379 : {
380 649008 : p_reverb_signal_fx[ch] = reverb_signal_fx[ch];
381 : }
382 :
383 324504 : subframe_length = idiv1616( output_frame, num_subframes );
384 :
385 324504 : c_indx = 0;
386 324504 : move16();
387 886568 : FOR( nS = 0; nS < num_src; nS++ )
388 : {
389 562064 : test();
390 562064 : IF( !( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( nS, lfe_idx ) ) ) /* Skip LFE for MC */
391 : {
392 550564 : hBinRendererTd->Sources[c_indx]->InputFrame_p_fx = output_fx[nS]; /* Q11 */
393 550564 : hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE;
394 550564 : move16();
395 550564 : c_indx = add( c_indx, 1 );
396 : }
397 : }
398 :
399 843714 : FOR( subframe_idx = 0; subframe_idx < num_subframes; subframe_idx++ )
400 : {
401 519210 : IF( EQ_16( subframe_idx, ism_md_subframe_update ) )
402 : {
403 : /* Update object position(s) */
404 324504 : IF( NE_32( ( error = TDREND_Update_object_positions_fx( hBinRendererTd, num_src, ivas_format, hIsmMetaData ) ), IVAS_ERR_OK ) )
405 : {
406 0 : return error;
407 : }
408 : }
409 :
410 : /* Update the listener's location/orientation */
411 : Word16 tmp_headRotEnabled;
412 519210 : tmp_headRotEnabled = 0;
413 519210 : move16();
414 : Word16 tmp_CombinedOrient_subframe_idx;
415 519210 : tmp_CombinedOrient_subframe_idx = 0;
416 519210 : move16();
417 519210 : IF( enableCombinedOrientation != NULL )
418 : {
419 268805 : tmp_headRotEnabled = enableCombinedOrientation[hCombinedOrientationData->subframe_idx];
420 268805 : move16();
421 268805 : tmp_CombinedOrient_subframe_idx = hCombinedOrientationData->subframe_idx;
422 : }
423 :
424 519210 : IF( NE_32( ( error = TDREND_Update_listener_orientation_fx( hBinRendererTd, tmp_headRotEnabled, &Quaternions[tmp_CombinedOrient_subframe_idx], &Pos[tmp_CombinedOrient_subframe_idx] ) ), IVAS_ERR_OK ) )
425 : {
426 0 : return error;
427 : }
428 :
429 519210 : IF( hReverb != NULL )
430 : {
431 : Word16 i;
432 :
433 4236400 : FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
434 : {
435 3987200 : scale_sig32( output_fx[i], L_FRAME48k, -4 ); // Q11 - 4 = Q7
436 : }
437 :
438 249200 : IF( NE_32( ( error = ivas_reverb_process_fx( hReverb, transport_config, 0, output_fx, p_reverb_signal_fx, subframe_idx ) ), IVAS_ERR_OK ) ) // Q p_reverb_signal_fx = Q output_fx - 2 = 5
439 : {
440 0 : return error;
441 : }
442 :
443 4236400 : FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
444 : {
445 3987200 : scale_sig32( output_fx[i], L_FRAME48k, 4 ); // Q7 + 4 = Q11
446 : }
447 :
448 747600 : FOR( i = 0; i < BINAURAL_CHANNELS; ++i )
449 : {
450 498400 : scale_sig32( p_reverb_signal_fx[i] + subframe_idx * hReverb->full_block_size, hReverb->full_block_size, 2 + 4 ); // Q5 + 6 = Q11
451 : }
452 : }
453 :
454 : /* Render subframe */
455 :
456 519210 : IF( NE_32( ( error = TDREND_GetMix_fx( hBinRendererTd, output_fx, subframe_length, subframe_idx ) ), IVAS_ERR_OK ) )
457 : {
458 0 : return error;
459 : }
460 :
461 :
462 : /* Advance subframe pointer */
463 519210 : c_indx = 0;
464 519210 : move16();
465 1418570 : FOR( nS = 0; nS < num_src; nS++ )
466 : {
467 899360 : test();
468 899360 : IF( !( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( nS, lfe_idx ) ) ) /* Skip LFE for MC */
469 : {
470 880960 : hBinRendererTd->Sources[c_indx]->InputFrame_p_fx += subframe_length;
471 880960 : c_indx = add( c_indx, 1 );
472 : }
473 : }
474 :
475 : /* update combined orientation access index */
476 519210 : ivas_combined_orientation_update_index( hCombinedOrientationData, subframe_length );
477 : }
478 :
479 324504 : IF( hReverb != NULL )
480 : {
481 155750 : v_add_32( reverb_signal_fx[0], output_fx[0], output_fx[0], output_frame ); // Q11
482 155750 : v_add_32( reverb_signal_fx[1], output_fx[1], output_fx[1], output_frame ); // Q11
483 : }
484 :
485 324504 : return IVAS_ERR_OK;
486 : }
487 :
488 :
489 : /*---------------------------------------------------------------------*
490 : * TDREND_GetMix()
491 : *
492 : * Render one 5 ms subframe from the mixer
493 : *---------------------------------------------------------------------*/
494 :
495 685912 : ivas_error TDREND_GetMix_fx(
496 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
497 : Word32 *output[], /* i/o: ISM object synth / rendered output in 0,1 Q11 */
498 : const Word16 subframe_length, /* i/o: subframe length */
499 : const Word16 subframe_idx /* i : Subframe index to 5 ms subframe */
500 : )
501 : {
502 : Word16 i;
503 : TDREND_SRC_t *Src_p;
504 : TDREND_SRC_SPATIAL_t *SrcSpatial_p;
505 : TDREND_SRC_REND_t *SrcRend_p;
506 : ivas_error error;
507 : Word32 output_buf[2][L_SPATIAL_SUBFR_48k]; /* Temp buffer for left/right rendered signal */
508 : Word32 hrf_left_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
509 : Word32 hrf_right_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
510 : Word16 intp_count;
511 :
512 685912 : Word16 hrf_left_delta_e = 0, hrf_right_delta_e = 0;
513 685912 : move16();
514 685912 : move16();
515 :
516 685912 : error = IVAS_ERR_OK;
517 685912 : move32();
518 : /* Clear the output buffer to accumulate rendered sources */
519 685912 : set32_fx( output_buf[0], 0, subframe_length );
520 685912 : set32_fx( output_buf[1], 0, subframe_length );
521 : /* Clear interpolation buffers and counter */
522 685912 : set32_fx( hrf_left_delta, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
523 685912 : set32_fx( hrf_right_delta, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
524 :
525 685912 : intp_count = 0;
526 685912 : move16();
527 :
528 : /* Create the mix */
529 : /* Loop through the source list and render each source */
530 2074139 : FOR( i = 0; i < hBinRendererTd->NumOfSrcs; i++ )
531 : {
532 1388227 : Src_p = hBinRendererTd->Sources[i];
533 1388227 : SrcSpatial_p = Src_p->SrcSpatial_p;
534 1388227 : SrcRend_p = Src_p->SrcRend_p;
535 :
536 : /* Update rendering params if needed */
537 1388227 : test();
538 1388227 : test();
539 1388227 : IF( EQ_16( SrcRend_p->PlayStatus, TDREND_PLAYSTATUS_PLAYING ) && ( hBinRendererTd->Listener_p->PoseUpdated || SrcSpatial_p->Updated ) )
540 : {
541 917847 : TDREND_SRC_REND_UpdateFiltersFromSpatialParams_fx( hBinRendererTd, SrcRend_p, SrcSpatial_p,
542 917847 : Src_p->hrf_left_prev_fx, &Src_p->hrf_left_prev_e, Src_p->hrf_right_prev_fx, &Src_p->hrf_right_prev_e,
543 : hrf_left_delta, &hrf_left_delta_e, hrf_right_delta, &hrf_right_delta_e,
544 : &intp_count, &Src_p->filterlength, &Src_p->itd,
545 : &Src_p->Gain_fx,
546 : Src_p );
547 : }
548 :
549 : /* Render source if needed */
550 1388227 : test();
551 1388227 : IF( EQ_16( SrcRend_p->InputAvailable, TRUE ) && EQ_16( SrcRend_p->PlayStatus, TDREND_PLAYSTATUS_PLAYING ) )
552 : {
553 1388227 : error = TDREND_REND_RenderSourceHRFilt_fx( Src_p, hrf_left_delta, &hrf_left_delta_e,
554 : hrf_right_delta, &hrf_right_delta_e, intp_count, output_buf, subframe_length );
555 : }
556 : }
557 :
558 :
559 : /* Populate output variable */
560 685912 : Copy32( output_buf[0], output[0] + imult1616( subframe_idx, subframe_length ), subframe_length ); /* Left same Q as Src_p->InputFrame_p_fx Q11 */
561 685912 : Copy32( output_buf[1], output[1] + imult1616( subframe_idx, subframe_length ), subframe_length ); /* Right same Q as Src_p->InputFrame_p_fx Q11 */
562 :
563 : /* Clear the PoseUpdated and Source position update flags */
564 685912 : TDREND_Clear_Update_flags_fx( hBinRendererTd );
565 :
566 685912 : return error;
567 : }
568 :
569 :
570 : /*---------------------------------------------------------------------*
571 : * TDREND_Clear_Update_flags()
572 : *
573 : * Initializes the audio mixer module
574 : *---------------------------------------------------------------------*/
575 :
576 685912 : static void TDREND_Clear_Update_flags_fx(
577 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd /* i/o: TD renderer handle */
578 : )
579 : {
580 : Word16 i;
581 :
582 685912 : hBinRendererTd->Listener_p->PoseUpdated = FALSE;
583 685912 : move16();
584 :
585 2074139 : FOR( i = 0; i < hBinRendererTd->NumOfSrcs; i++ )
586 : {
587 1388227 : hBinRendererTd->Sources[i]->SrcSpatial_p->Updated = FALSE;
588 1388227 : move16();
589 : #ifdef OBJ_EDITING_API
590 1388227 : hBinRendererTd->Sources[i]->SrcRend_p->SrcGainUpdated = FALSE;
591 1388227 : move16();
592 : #endif
593 : }
594 :
595 685912 : return;
596 : }
597 :
598 :
599 : /*---------------------------------------------------------------------*
600 : * TDREND_Update_object_positions_fx()
601 : *
602 : * Update object position(s)
603 : *---------------------------------------------------------------------*/
604 :
605 366089 : ivas_error TDREND_Update_object_positions_fx(
606 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD Renderer handle */
607 : const Word16 num_src, /* i : number of sources to render */
608 : const IVAS_FORMAT in_format, /* i : Format of input sources */
609 : const ISM_METADATA_HANDLE *hIsmMetaData /* i : Input metadata for ISM objects */
610 : )
611 : {
612 : #ifndef NONBE_1377_REND_DIRATT_CONF
613 : TDREND_DirAtten_t *DirAtten_p;
614 : #endif
615 : Word16 nS;
616 : Word32 Pos_fx[3]; // Q25
617 : Word32 Dir_fx[3]; // Q30
618 : ivas_error error;
619 : #ifndef NONBE_1377_REND_DIRATT_CONF
620 : DirAtten_p = hBinRendererTd->DirAtten_p;
621 : #endif
622 :
623 : /* For each source, write the frame data to the source object*/
624 1057915 : FOR( nS = 0; nS < num_src; nS++ )
625 : {
626 691826 : test();
627 691826 : test();
628 691826 : IF( EQ_16( in_format, ISM_FORMAT ) || EQ_16( in_format, MASA_ISM_FORMAT ) || EQ_16( in_format, SBA_ISM_FORMAT ) )
629 : {
630 : /* Update the source positions */
631 : /* Source position and direction */
632 410778 : angles_to_vec_fx( hIsmMetaData[nS]->radius_fx /*Q9*/, hIsmMetaData[nS]->azimuth_fx, hIsmMetaData[nS]->elevation_fx, Pos_fx );
633 410778 : angles_to_vec_fx( ONE_IN_Q14, hIsmMetaData[nS]->yaw_fx, hIsmMetaData[nS]->pitch_fx, Dir_fx );
634 :
635 : // DirAtten_p->ConeInnerAngle_fx = DEG_360_IN_Q22;
636 : // move32();
637 : // DirAtten_p->ConeOuterAngle_fx = DEG_360_IN_Q22;
638 : // move32();
639 : // DirAtten_p->ConeOuterGain_fx = ONE_IN_Q30;
640 : // move32();
641 :
642 410778 : IF( NE_32( ( error = TDREND_MIX_SRC_SetPos_fx( hBinRendererTd, nS, Pos_fx ) ), IVAS_ERR_OK ) )
643 : {
644 0 : return error;
645 : }
646 : #ifndef NONBE_1377_REND_DIRATT_CONF
647 : IF( NE_32( ( error = TDREND_MIX_SRC_SetDirAtten_fx( hBinRendererTd, nS, DirAtten_p ) ), IVAS_ERR_OK ) )
648 : {
649 : return error;
650 : }
651 : #endif
652 :
653 410778 : IF( hIsmMetaData[nS]->non_diegetic_flag )
654 : {
655 828 : Pos_fx[0] = 0;
656 : /* Pos[1] = hIsmMetaData[nS]->azimuth / 90.f; */
657 828 : Pos_fx[1] = L_shl( Mpy_32_32_r( hIsmMetaData[nS]->azimuth_fx, 23860929 /* 1 / 90.f in Q31 */ ), Q3 ); /* Q25 */
658 828 : move32();
659 828 : Pos_fx[2] = 0;
660 828 : move32();
661 :
662 828 : IF( NE_32( ( error = TDREND_MIX_SRC_SetPos_fx( hBinRendererTd, nS, Pos_fx ) ), IVAS_ERR_OK ) )
663 : {
664 0 : return error;
665 : }
666 828 : hBinRendererTd->Sources[nS]->SrcSpatial_p->PosType = TDREND_POSTYPE_NON_DIEGETIC;
667 828 : move16();
668 : }
669 : ELSE
670 : {
671 409950 : hBinRendererTd->Sources[nS]->SrcSpatial_p->PosType = TDREND_POSTYPE_ABSOLUTE;
672 409950 : move16();
673 : }
674 :
675 410778 : IF( NE_32( ( error = TDREND_MIX_SRC_SetDir_fx( hBinRendererTd, nS, Dir_fx, Q30 ) ), IVAS_ERR_OK ) )
676 : {
677 0 : return error;
678 : }
679 : }
680 : }
681 :
682 366089 : return IVAS_ERR_OK;
683 : }
684 :
685 : /*---------------------------------------------------------------------*
686 : * TDREND_Update_listener_orientation()
687 : *
688 : * Update listener orientation (s)
689 : *---------------------------------------------------------------------*/
690 :
691 685912 : ivas_error TDREND_Update_listener_orientation_fx(
692 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD Renderer handle */
693 : const Word16 headRotEnabled, /* i : Headrotation flag */
694 : const IVAS_QUATERNION *headPosition_fx, /* i : Listener orientation Qx */
695 : const IVAS_VECTOR3 *Pos_fx /* i : Listener Position */
696 : )
697 : {
698 : Word32 FrontVec_fx[3];
699 : Word32 UpVec_fx[3];
700 : Word32 Rmat_fx[3][3];
701 : Word16 orient_q, headPosition_q;
702 : Word32 Pos_p_fx[3];
703 : ivas_error error;
704 :
705 685912 : IF( headRotEnabled )
706 : {
707 : Word16 Rmat_q;
708 :
709 354498 : headPosition_q = headPosition_fx->q_fact;
710 354498 : move16();
711 :
712 : /* Obtain head rotation matrix */
713 354498 : QuatToRotMat_fx( *headPosition_fx, Rmat_fx ); // Rmat_fx Q: 2*headPosition_q-32
714 354498 : Rmat_q = sub( shl( headPosition_q, 1 ), 32 );
715 :
716 : /* Apply rotation matrix to looking vector [1;0;0] */
717 354498 : FrontVec_fx[0] = Rmat_fx[0][0]; // Q Rmat_q
718 354498 : move32();
719 354498 : FrontVec_fx[1] = Rmat_fx[0][1]; // Q Rmat_q
720 354498 : move32();
721 354498 : FrontVec_fx[2] = Rmat_fx[0][2]; // Q Rmat_q
722 354498 : move32();
723 :
724 : /* Apply rotation matrix to up vector [0;0;1] */
725 354498 : UpVec_fx[0] = Rmat_fx[2][0]; // Q Rmat_q
726 354498 : move32();
727 354498 : UpVec_fx[1] = Rmat_fx[2][1]; // Q Rmat_q
728 354498 : move32();
729 354498 : UpVec_fx[2] = Rmat_fx[2][2]; // Q Rmat_q
730 354498 : move32();
731 :
732 354498 : orient_q = Rmat_q;
733 354498 : move16();
734 :
735 354498 : IF( Pos_fx != NULL )
736 : {
737 : /* Input position */
738 354498 : Pos_p_fx[0] = ( *Pos_fx ).x_fx; // Q Pos_fx->q_fact
739 354498 : Pos_p_fx[1] = ( *Pos_fx ).y_fx; // Q Pos_fx->q_fact
740 354498 : Pos_p_fx[2] = ( *Pos_fx ).z_fx; // Q Pos_fx->q_fact
741 : }
742 : ELSE
743 : {
744 : /* Listener at the origin */
745 0 : Pos_p_fx[0] = 0;
746 0 : Pos_p_fx[1] = 0;
747 0 : Pos_p_fx[2] = 0;
748 : }
749 354498 : move32();
750 354498 : move32();
751 354498 : move32();
752 : }
753 : ELSE
754 : {
755 : /* Oriented with looking vector along the x axis */
756 331414 : FrontVec_fx[0] = ONE_IN_Q30;
757 331414 : move32();
758 331414 : FrontVec_fx[1] = 0;
759 331414 : move32();
760 331414 : FrontVec_fx[2] = 0;
761 331414 : move32();
762 : /* Oriented with up vector along the z axis */
763 331414 : UpVec_fx[0] = 0;
764 331414 : move32();
765 331414 : UpVec_fx[1] = 0;
766 331414 : move32();
767 331414 : UpVec_fx[2] = ONE_IN_Q30;
768 331414 : move32();
769 :
770 331414 : orient_q = Q30;
771 331414 : move32();
772 :
773 : /* Listener at the origin */
774 331414 : Pos_p_fx[0] = 0;
775 331414 : move32();
776 331414 : Pos_p_fx[1] = 0;
777 331414 : move32();
778 331414 : Pos_p_fx[2] = 0;
779 331414 : move32();
780 : }
781 :
782 : /* Set the listener position and orientation:*/
783 685912 : TDREND_MIX_LIST_SetPos_fx( hBinRendererTd, Pos_p_fx );
784 685912 : error = TDREND_MIX_LIST_SetOrient_fx( hBinRendererTd, FrontVec_fx, UpVec_fx, orient_q );
785 :
786 685912 : return error;
787 : }
788 :
789 :
790 : /*---------------------------------------------------------------------*
791 : * ivas_td_binaural_open_ext()
792 : *
793 : *
794 : *---------------------------------------------------------------------*/
795 :
796 737 : ivas_error ivas_td_binaural_open_ext_fx(
797 : TDREND_WRAPPER *pTDRend,
798 : AUDIO_CONFIG inConfig,
799 : RENDER_CONFIG_DATA *hRendCfg, /* i : Renderer configuration */
800 : LSSETUP_CUSTOM_STRUCT *customLsInput,
801 : const Word32 outFs,
802 : #ifdef NONBE_1377_REND_DIRATT_CONF
803 : const Word16 object_id, /* i: Object ID */
804 : #endif
805 : Word16 *SrcInd,
806 : Word16 *num_src )
807 : {
808 : Word16 nchan_transport;
809 : AUDIO_CONFIG transport_config;
810 : IVAS_FORMAT ivas_format;
811 : IVAS_OUTPUT_SETUP hTransSetup;
812 : ivas_error error;
813 737 : Word32 *distAtt_fx = NULL;
814 737 : Word16 *directivity_fx = NULL;
815 :
816 737 : IF( NE_16( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
817 : {
818 713 : IF( NE_32( ( error = getAudioConfigNumChannels( inConfig, &nchan_transport ) ), IVAS_ERR_OK ) )
819 : {
820 0 : return error;
821 : }
822 : }
823 : ELSE
824 : {
825 24 : nchan_transport = customLsInput->num_spk;
826 24 : move16();
827 : }
828 737 : *num_src = nchan_transport;
829 737 : move16();
830 :
831 737 : transport_config = inConfig;
832 737 : move16();
833 737 : IF( ( getAudioConfigType( inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) )
834 : {
835 32 : ivas_format = MC_FORMAT;
836 32 : move16();
837 : }
838 : ELSE
839 : {
840 705 : ivas_format = ISM_FORMAT;
841 705 : move16();
842 : }
843 737 : hTransSetup.ls_azimuth_fx = NULL;
844 737 : hTransSetup.ls_elevation_fx = NULL;
845 :
846 737 : IF( EQ_16( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
847 : {
848 24 : hTransSetup.ls_azimuth_fx = customLsInput->ls_azimuth_fx;
849 24 : hTransSetup.ls_elevation_fx = customLsInput->ls_elevation_fx;
850 : }
851 :
852 737 : if ( NULL != hRendCfg )
853 : {
854 : #ifdef NONBE_1377_REND_DIRATT_CONF
855 432 : directivity_fx = hRendCfg->directivity_fx + 3 * object_id; /* Address calculation -- no BASOPs */
856 : #else
857 : directivity_fx = hRendCfg->directivity_fx;
858 : #endif
859 432 : distAtt_fx = hRendCfg->distAtt_fx;
860 : }
861 :
862 737 : return ivas_td_binaural_open_unwrap_fx( pTDRend->hHrtfTD, outFs, nchan_transport, ivas_format, transport_config, directivity_fx, distAtt_fx, hTransSetup, &pTDRend->hBinRendererTd, &pTDRend->binaural_latency_ns, SrcInd );
863 : }
864 :
865 :
866 : /*---------------------------------------------------------------------*
867 : * ivas_td_binaural_renderer_ext()
868 : *
869 : * Receives the current frames for the object streams, updates metadata
870 : * and renders the current frame.
871 : *---------------------------------------------------------------------*/
872 :
873 324504 : ivas_error ivas_td_binaural_renderer_ext_fx(
874 : const TDREND_WRAPPER *pTDRend, /* i : TD Renderer wrapper structure */
875 : const AUDIO_CONFIG inConfig, /* i : Input audio configuration */
876 : const LSSETUP_CUSTOM_STRUCT *customLsInput, /* i : Input custom loudspeaker layout */
877 : const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* i : Combined head and external orientations */
878 : const IVAS_ISM_METADATA *currentPos, /* i : Object position */
879 : const REVERB_HANDLE hReverb, /* i : Reverberator handle */
880 : const Word16 ism_md_subframe_update_ext, /* i : Metadata Delay in subframes to sync with audio delay */
881 : const Word32 output_Fs, /* i : output sampling rate */
882 : const Word16 output_frame, /* i : output frame length */
883 : Word32 output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis Q11 */
884 : Word16 *exp )
885 : {
886 : ISM_METADATA_FRAME hIsmMetaDataFrame;
887 : ISM_METADATA_HANDLE hIsmMetaData[1];
888 : Word16 lfe_idx, exp_tmp;
889 : Word16 num_src;
890 : IVAS_FORMAT ivas_format;
891 : IVAS_REND_AudioConfigType inConfigType;
892 : AUDIO_CONFIG transport_config;
893 : ivas_error error;
894 :
895 : Word32 *p_output_fx[MAX_OUTPUT_CHANNELS];
896 5516568 : FOR( Word16 i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
897 : {
898 5192064 : p_output_fx[i] = output[i];
899 : }
900 :
901 324504 : push_wmops( "ivas_td_binaural_renderer_ext" );
902 :
903 324504 : inConfigType = getAudioConfigType( inConfig );
904 324504 : lfe_idx = LFE_CHANNEL;
905 324504 : move16();
906 324504 : hIsmMetaData[0] = NULL;
907 :
908 :
909 324504 : IF( EQ_32( inConfigType, IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) )
910 : {
911 24504 : ivas_format = MC_FORMAT;
912 24504 : move16();
913 24504 : transport_config = inConfig;
914 24504 : move16();
915 :
916 24504 : IF( NE_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
917 : {
918 11500 : IF( NE_32( ( error = getAudioConfigNumChannels( inConfig, &num_src ) ), IVAS_ERR_OK ) )
919 : {
920 0 : return error;
921 : }
922 : }
923 : ELSE
924 : {
925 13004 : IF( customLsInput->num_lfe > 0 )
926 : {
927 0 : lfe_idx = customLsInput->lfe_idx[0];
928 0 : move16();
929 : }
930 : ELSE
931 : {
932 13004 : lfe_idx = -1;
933 13004 : move16();
934 : }
935 13004 : num_src = add( customLsInput->num_spk, customLsInput->num_lfe );
936 : }
937 : }
938 : ELSE
939 : {
940 300000 : ivas_format = ISM_FORMAT;
941 300000 : move16();
942 300000 : num_src = 1;
943 300000 : move16();
944 300000 : transport_config = IVAS_AUDIO_CONFIG_ISM1;
945 300000 : move16();
946 300000 : hIsmMetaData[0] = &hIsmMetaDataFrame;
947 300000 : move16();
948 300000 : hIsmMetaData[0]->azimuth_fx = currentPos->azimuth_fx;
949 300000 : move32();
950 300000 : hIsmMetaData[0]->elevation_fx = currentPos->elevation_fx;
951 300000 : move32();
952 300000 : hIsmMetaData[0]->yaw_fx = currentPos->yaw_fx;
953 300000 : move32();
954 300000 : hIsmMetaData[0]->pitch_fx = currentPos->pitch_fx;
955 300000 : move32();
956 300000 : hIsmMetaData[0]->radius_fx = currentPos->radius_fx;
957 300000 : move32();
958 300000 : hIsmMetaData[0]->non_diegetic_flag = currentPos->non_diegetic_flag;
959 300000 : move16();
960 : }
961 :
962 324504 : Word16 num_subframes = BASOP_Util_Divide3232_Scale( L_mult0( output_frame, FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ), output_Fs, &exp_tmp );
963 324504 : IF( sub( 15, exp_tmp ) )
964 : {
965 324504 : num_subframes = shr( num_subframes, sub( 15, exp_tmp ) );
966 : }
967 843714 : FOR( Word16 subframe_idx = 0; subframe_idx < num_subframes; subframe_idx++ )
968 : {
969 519210 : Word16 idx = subframe_idx;
970 519210 : move16();
971 519210 : Word16 pos_q = Q25;
972 519210 : move16();
973 :
974 519210 : test();
975 519210 : IF( *hCombinedOrientationData != NULL && ( *hCombinedOrientationData )->listenerPos != NULL )
976 : {
977 268805 : ( *hCombinedOrientationData )->listenerPos[idx].x_fx = L_shr( ( *hCombinedOrientationData )->listenerPos[idx].x_fx, sub( ( *hCombinedOrientationData )->listenerPos[idx].q_fact, pos_q ) );
978 268805 : move32();
979 268805 : ( *hCombinedOrientationData )->listenerPos[idx].y_fx = L_shr( ( *hCombinedOrientationData )->listenerPos[idx].y_fx, sub( ( *hCombinedOrientationData )->listenerPos[idx].q_fact, pos_q ) );
980 268805 : move32();
981 268805 : ( *hCombinedOrientationData )->listenerPos[idx].z_fx = L_shr( ( *hCombinedOrientationData )->listenerPos[idx].z_fx, sub( ( *hCombinedOrientationData )->listenerPos[idx].q_fact, pos_q ) );
982 268805 : move32();
983 268805 : ( *hCombinedOrientationData )->listenerPos[idx].q_fact = pos_q;
984 268805 : move16();
985 : }
986 2076840 : FOR( Word16 i = 0; i < 3; i++ )
987 : {
988 1557630 : pTDRend->hBinRendererTd->Listener_p->Pos_fx[i] = L_shr( pTDRend->hBinRendererTd->Listener_p->Pos_fx[i], sub( pTDRend->hBinRendererTd->Listener_p->Pos_q, pos_q ) );
989 1557630 : pTDRend->hBinRendererTd->Listener_p->Pos_q = pos_q;
990 1557630 : move32();
991 1557630 : move16();
992 : }
993 : }
994 :
995 324504 : IF( NE_32( ( error = ivas_td_binaural_renderer_unwrap_fx( hReverb, transport_config, pTDRend->hBinRendererTd, num_src, lfe_idx, ivas_format, hIsmMetaData, *hCombinedOrientationData,
996 : ism_md_subframe_update_ext, p_output_fx, output_frame, num_subframes ) ),
997 : IVAS_ERR_OK ) )
998 : {
999 0 : return error;
1000 : }
1001 :
1002 324504 : IF( hReverb != NULL )
1003 : {
1004 155750 : *exp = sub( *exp, 2 );
1005 155750 : move16();
1006 : }
1007 :
1008 324504 : pop_wmops();
1009 :
1010 324504 : return IVAS_ERR_OK;
1011 : }
1012 :
1013 :
1014 : /*---------------------------------------------------------------------*
1015 : * angles_to_vec()
1016 : *
1017 : * Convert azimuth and elevation angles to position/orientation vector
1018 : *---------------------------------------------------------------------*/
1019 821831 : static void angles_to_vec_fx(
1020 : const Word16 radius, /* i : radius Qx */
1021 : const Word32 azimuth, /* i : Azimuth angle Q22 */
1022 : const Word32 elevation, /* i : Elevation angle Q22 */
1023 : Word32 *vec /* o : Pos/Dir vector Qx+16 */
1024 : )
1025 : {
1026 : Word16 elevation_fx, azimuth_fx;
1027 821831 : elevation_fx = (Word16) L_shr( Mult_32_16( elevation, 91 ), 7 ); // Q15
1028 821831 : move16();
1029 821831 : azimuth_fx = (Word16) L_shr( Mult_32_16( azimuth, 91 ), 7 ); // Q15
1030 821831 : move16();
1031 821831 : vec[0] = L_mult( radius, mult( getCosWord16R2( elevation_fx ), getCosWord16R2( azimuth_fx ) ) ); // Qx + 16
1032 821831 : move32();
1033 821831 : vec[1] = L_mult( radius, mult( getCosWord16R2( elevation_fx ), getSineWord16R2( azimuth_fx ) ) ); // Qx + 16
1034 821831 : move32();
1035 821831 : vec[2] = L_mult( radius, getSineWord16R2( elevation_fx ) ); // Qx + 16
1036 821831 : move32();
1037 821831 : return;
1038 : }
|