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