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.h"
37 : #include "ivas_prot.h"
38 : #include "ivas_prot_rend.h"
39 : #include <math.h>
40 : #include "ivas_rom_com.h"
41 : #ifdef DEBUGGING
42 : #include "debug.h"
43 : #endif
44 : #include "wmc_auto.h"
45 :
46 :
47 : /*---------------------------------------------------------------------*
48 : * Local function prototypes
49 : *---------------------------------------------------------------------*/
50 :
51 : static void TDREND_Clear_Update_flags( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd );
52 :
53 : static void angles_to_vec( const float radius, const float azimuth, const float elevation, float *vec );
54 :
55 :
56 : /*---------------------------------------------------------------------*
57 : * ivas_td_binaural_open_unwrap()
58 : *
59 : * Call TD open/init function without st_ivas
60 : *---------------------------------------------------------------------*/
61 :
62 24372 : ivas_error ivas_td_binaural_open_unwrap(
63 : TDREND_HRFILT_FiltSet_t **hHrtfTD, /* i/o: HR filter model (from file or NULL) */
64 : const int32_t output_Fs, /* i : Output sampling rate */
65 : const int16_t nchan_transport, /* i : Number of channels */
66 : const IVAS_FORMAT ivas_format, /* i : IVAS format (ISM/MC) */
67 : const AUDIO_CONFIG transport_config, /* i : Transport configuration */
68 : const float *directivity, /* i : Directivity pattern (used for ISM) */
69 : const float *distAtt, /* i : Distance attenuation (used for ISM) */
70 : const IVAS_OUTPUT_SETUP hTransSetup, /* i : Loudspeaker layout */
71 : BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd, /* o : TD renderer handle */
72 : int32_t *binaural_latency_ns /* i : Binauralization delay */
73 : )
74 : {
75 : BINAURAL_TD_OBJECT_RENDERER_HANDLE pBinRendTd;
76 : TDREND_PosType_t PosType;
77 : int16_t nS;
78 : int16_t SrcInd[MAX_NUM_TDREND_CHANNELS];
79 : const float *ls_azimuth, *ls_elevation;
80 : float Pos[3];
81 : float Dir[3];
82 : TDREND_DirAtten_t *DirAtten_p;
83 : TDREND_DistAtten_t DistAtten;
84 : int16_t nchan_rend;
85 : ivas_error error;
86 :
87 24372 : error = IVAS_ERR_OK;
88 :
89 24372 : if ( ( pBinRendTd = malloc( sizeof( BINAURAL_TD_OBJECT_RENDERER ) ) ) == NULL )
90 : {
91 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
92 : }
93 24372 : if ( ( pBinRendTd->TdRend_MixSpatSpec_p = malloc( sizeof( TDREND_MixSpatSpec_t ) ) ) == NULL )
94 : {
95 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
96 : }
97 24372 : if ( ( pBinRendTd->DirAtten_p = malloc( sizeof( TDREND_DirAtten_t ) ) ) == NULL )
98 : {
99 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
100 : }
101 24372 : if ( ( pBinRendTd->Listener_p = malloc( sizeof( TDREND_MIX_Listener_t ) ) ) == NULL )
102 : {
103 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) );
104 : }
105 :
106 24372 : pBinRendTd->NumOfSrcs = 0;
107 24372 : pBinRendTd->MaxSrcInd = -1;
108 :
109 : /* Mixer spatial setup */
110 24372 : pBinRendTd->TdRend_MixSpatSpec_p->UseCommonDistAttenModel = TRUE;
111 24372 : pBinRendTd->TdRend_MixSpatSpec_p->DistAttenModel = 0; /* 0=Turned off, else use TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED */
112 :
113 24372 : if ( ( error = TDREND_MIX_Init( pBinRendTd, hHrtfTD, pBinRendTd->TdRend_MixSpatSpec_p, output_Fs ) ) != IVAS_ERR_OK )
114 : {
115 0 : return error;
116 : }
117 :
118 : /* Set the attenuation (or can set MixSpatSpec.DistAttenModel above) */
119 24372 : if ( ( error = TDREND_MIX_SetDistAttenModel( pBinRendTd, TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED ) ) != IVAS_ERR_OK )
120 : {
121 0 : return error;
122 : }
123 :
124 : /* Add sources to module and mixer, headphones */
125 24372 : PosType = TDREND_POSTYPE_ABSOLUTE; /* or TDREND_POSTYPE_RELATIVE_TO_LISTENER */
126 :
127 24372 : nchan_rend = nchan_transport;
128 24372 : if ( ( ivas_format == MC_FORMAT ) && ( transport_config != IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
129 : {
130 81 : nchan_rend--; /* Skip LFE channel -- added to the others */
131 : }
132 :
133 52284 : for ( nS = 0; nS < nchan_rend; nS++ )
134 : {
135 27912 : if ( ( error = TDREND_MIX_AddSrc( pBinRendTd, &SrcInd[nS], PosType ) ) != IVAS_ERR_OK )
136 : {
137 0 : return error;
138 : }
139 : }
140 :
141 24372 : if ( ivas_format == MC_FORMAT )
142 : {
143 225 : switch ( transport_config )
144 : {
145 33 : case IVAS_AUDIO_CONFIG_5_1:
146 33 : ls_azimuth = ls_azimuth_CICP6;
147 33 : ls_elevation = ls_elevation_CICP6;
148 33 : break;
149 48 : case IVAS_AUDIO_CONFIG_7_1:
150 48 : ls_azimuth = ls_azimuth_CICP12;
151 48 : ls_elevation = ls_elevation_CICP12;
152 48 : break;
153 0 : case IVAS_AUDIO_CONFIG_5_1_2:
154 0 : ls_azimuth = ls_azimuth_CICP14;
155 0 : ls_elevation = ls_elevation_CICP14;
156 0 : break;
157 0 : case IVAS_AUDIO_CONFIG_5_1_4:
158 0 : ls_azimuth = ls_azimuth_CICP16;
159 0 : ls_elevation = ls_elevation_CICP16;
160 0 : break;
161 0 : case IVAS_AUDIO_CONFIG_7_1_4:
162 0 : ls_azimuth = ls_azimuth_CICP19;
163 0 : ls_elevation = ls_elevation_CICP19;
164 0 : break;
165 144 : case IVAS_AUDIO_CONFIG_LS_CUSTOM:
166 144 : ls_azimuth = hTransSetup.ls_azimuth;
167 144 : ls_elevation = hTransSetup.ls_elevation;
168 144 : break;
169 0 : default:
170 0 : ls_azimuth = NULL;
171 0 : ls_elevation = NULL;
172 : }
173 :
174 225 : DirAtten_p = pBinRendTd->DirAtten_p;
175 :
176 1662 : for ( nS = 0; nS < nchan_rend; nS++ )
177 : {
178 : /* Set source positions according to loudspeaker layout */
179 1437 : angles_to_vec( 1.0f, ls_azimuth[nS], ls_elevation[nS], Pos );
180 1437 : Dir[0] = 1.0f;
181 1437 : Dir[1] = 0.0f;
182 1437 : Dir[2] = 0.0f;
183 :
184 : /* Source directivity info */
185 1437 : DirAtten_p->ConeInnerAngle = 360.0f;
186 1437 : DirAtten_p->ConeOuterAngle = 360.0f;
187 1437 : DirAtten_p->ConeOuterGain = 1.0f;
188 :
189 1437 : DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED;
190 1437 : DistAtten.MaxDist = 15.75f;
191 1437 : DistAtten.RefDist = 1.0f;
192 1437 : DistAtten.RollOffFactor = 1.0f;
193 :
194 1437 : if ( ( error = TDREND_MIX_SRC_SetPos( pBinRendTd, nS, Pos ) ) != IVAS_ERR_OK )
195 : {
196 0 : return error;
197 : }
198 :
199 1437 : if ( ( error = TDREND_MIX_SRC_SetDir( pBinRendTd, nS, Dir ) ) != IVAS_ERR_OK )
200 : {
201 0 : return error;
202 : }
203 :
204 1437 : if ( ( error = TDREND_MIX_SRC_SetPlayState( pBinRendTd, nS, TDREND_PLAYSTATUS_PLAYING ) ) != IVAS_ERR_OK )
205 : {
206 0 : return error;
207 : }
208 :
209 1437 : if ( ( error = TDREND_MIX_SRC_SetDirAtten( pBinRendTd, nS, DirAtten_p ) ) != IVAS_ERR_OK )
210 : {
211 0 : return error;
212 : }
213 1437 : if ( ( error = TDREND_MIX_SRC_SetDistAtten( pBinRendTd, nS, &DistAtten ) ) != IVAS_ERR_OK )
214 : {
215 0 : return error;
216 : }
217 : }
218 : }
219 :
220 24372 : if ( ivas_format == ISM_FORMAT || ivas_format == MASA_ISM_FORMAT || ivas_format == SBA_ISM_FORMAT )
221 : {
222 24147 : DirAtten_p = pBinRendTd->DirAtten_p;
223 :
224 50622 : for ( nS = 0; nS < nchan_rend; nS++ )
225 : {
226 26475 : if ( NULL == directivity )
227 : {
228 8790 : DirAtten_p->ConeInnerAngle = 360.0f; /* Front cone */
229 8790 : DirAtten_p->ConeOuterAngle = 360.0f; /* Back cone */
230 8790 : DirAtten_p->ConeOuterGain = 1.0f; /* Back attenuation */
231 : }
232 : else
233 : {
234 17685 : DirAtten_p->ConeInnerAngle = directivity[nS * 3];
235 17685 : DirAtten_p->ConeOuterAngle = directivity[nS * 3 + 1];
236 17685 : DirAtten_p->ConeOuterGain = directivity[nS * 3 + 2];
237 : }
238 26475 : if ( NULL == distAtt )
239 : {
240 8790 : DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED;
241 8790 : DistAtten.MaxDist = 15.75f;
242 8790 : DistAtten.RefDist = 1.0f;
243 8790 : DistAtten.RollOffFactor = 1.0f;
244 : }
245 : else
246 : {
247 17685 : DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED;
248 17685 : DistAtten.MaxDist = distAtt[0];
249 17685 : DistAtten.RefDist = distAtt[1];
250 17685 : DistAtten.RollOffFactor = distAtt[2];
251 : }
252 26475 : if ( ( error = TDREND_MIX_SRC_SetDirAtten( pBinRendTd, nS, DirAtten_p ) ) != IVAS_ERR_OK )
253 : {
254 0 : return error;
255 : }
256 26475 : if ( ( error = TDREND_MIX_SRC_SetDistAtten( pBinRendTd, nS, &DistAtten ) ) != IVAS_ERR_OK )
257 : {
258 0 : return error;
259 : }
260 : }
261 : }
262 :
263 24372 : *hBinRendererTd = pBinRendTd;
264 :
265 24372 : if ( ivas_format != MASA_ISM_FORMAT && ivas_format != SBA_ISM_FORMAT )
266 : {
267 23706 : *binaural_latency_ns = (int32_t) ( ( *hBinRendererTd )->HrFiltSet_p->latency_s * 1000000000.f );
268 : }
269 :
270 24372 : return error;
271 : }
272 :
273 :
274 : /*---------------------------------------------------------------------*
275 : * ivas_td_binaural_close()
276 : *
277 : * Close TD Object binaural renderer
278 : *---------------------------------------------------------------------*/
279 :
280 249708 : void ivas_td_binaural_close(
281 : BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd /* i/o: TD binaural object renderer handle */
282 : )
283 : {
284 249708 : if ( hBinRendererTd == NULL || *hBinRendererTd == NULL )
285 : {
286 225336 : return;
287 : }
288 :
289 24372 : free( ( *hBinRendererTd )->TdRend_MixSpatSpec_p );
290 24372 : free( ( *hBinRendererTd )->DirAtten_p );
291 :
292 24372 : TDREND_MIX_Dealloc( *hBinRendererTd );
293 :
294 24372 : free( *hBinRendererTd );
295 24372 : *hBinRendererTd = NULL;
296 :
297 24372 : return;
298 : }
299 :
300 :
301 : /*---------------------------------------------------------------------*
302 : * ivas_td_binaural_renderer_unwrap()
303 : *
304 : * Call ivas_td_binaural_renderer() without st_ivas.
305 : *---------------------------------------------------------------------*/
306 :
307 6091464 : ivas_error ivas_td_binaural_renderer_unwrap(
308 : const REVERB_HANDLE hReverb, /* i : Reverberator handle */
309 : const AUDIO_CONFIG transport_config, /* i : Transport configuration */
310 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD binaural object renderer handle */
311 : const int16_t num_src, /* i : number of sources to render */
312 : const int16_t lfe_idx, /* i : LFE channel index */
313 : const IVAS_FORMAT ivas_format, /* i : IVAS format */
314 : ISM_METADATA_HANDLE *hIsmMetaData, /* i : ISM metadata handle */
315 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientaton data handle */
316 : const int16_t ism_md_subframe_update, /* i : Number of subframes to delay ism metadata to sync with audio */
317 : float *output[], /* i/o: SCE channels / Binaural synthesis */
318 : const int16_t output_frame, /* i : output frame length */
319 : const int16_t num_subframes /* i : number of subframes to render */
320 : )
321 : {
322 : int16_t subframe_length;
323 : int16_t subframe_idx;
324 : float reverb_signal[BINAURAL_CHANNELS][L_FRAME48k];
325 : ivas_error error;
326 : int16_t c_indx, nS;
327 : float *p_reverb_signal[BINAURAL_CHANNELS];
328 : int16_t ch;
329 : int16_t *enableCombinedOrientation; /* i : Combined orientation flag */
330 : IVAS_QUATERNION *Quaternions; /* i : Head tracking data per subframe */
331 : IVAS_VECTOR3 *Pos; /* i : Listener position data per subframe */
332 :
333 6091464 : enableCombinedOrientation = NULL;
334 6091464 : Quaternions = NULL;
335 6091464 : Pos = NULL;
336 6091464 : if ( hCombinedOrientationData != NULL )
337 : {
338 3080256 : enableCombinedOrientation = hCombinedOrientationData->enableCombinedOrientation;
339 3080256 : Quaternions = hCombinedOrientationData->Quaternions;
340 3080256 : Pos = hCombinedOrientationData->listenerPos;
341 : }
342 :
343 18274392 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
344 : {
345 12182928 : p_reverb_signal[ch] = reverb_signal[ch];
346 : }
347 :
348 6091464 : subframe_length = output_frame / num_subframes;
349 :
350 6091464 : c_indx = 0;
351 13609368 : for ( nS = 0; nS < num_src; nS++ )
352 : {
353 7517904 : if ( !( ivas_format == MC_FORMAT && nS == lfe_idx ) ) /* Skip LFE for MC */
354 : {
355 7448856 : hBinRendererTd->Sources[c_indx]->InputFrame_p = output[nS];
356 7448856 : hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE;
357 7448856 : c_indx++;
358 : }
359 : }
360 :
361 15841824 : for ( subframe_idx = 0; subframe_idx < num_subframes; subframe_idx++ )
362 : {
363 9750360 : if ( subframe_idx == ism_md_subframe_update )
364 : {
365 : /* Update object position(s) */
366 5658984 : if ( ( error = TDREND_Update_object_positions( hBinRendererTd, num_src, ivas_format, hIsmMetaData ) ) != IVAS_ERR_OK )
367 : {
368 0 : return error;
369 : }
370 : }
371 :
372 : /* Update the listener's location/orientation */
373 9750360 : if ( ( error = TDREND_Update_listener_orientation( hBinRendererTd, ( enableCombinedOrientation != NULL ) ? enableCombinedOrientation[hCombinedOrientationData->subframe_idx] : 0, ( Quaternions != NULL ) ? &Quaternions[hCombinedOrientationData->subframe_idx] : NULL, ( Pos != NULL ) ? &Pos[hCombinedOrientationData->subframe_idx] : NULL ) ) != IVAS_ERR_OK )
374 : {
375 0 : return error;
376 : }
377 :
378 9750360 : if ( hReverb != NULL )
379 : {
380 4812660 : if ( ( error = ivas_reverb_process( hReverb, transport_config, 0, output, p_reverb_signal, subframe_idx ) ) != IVAS_ERR_OK )
381 : {
382 0 : return error;
383 : }
384 : }
385 :
386 : /* Render subframe */
387 9750360 : if ( ( error = TDREND_GetMix( hBinRendererTd, output, subframe_length, subframe_idx ) ) != IVAS_ERR_OK )
388 : {
389 0 : return error;
390 : }
391 :
392 : /* Advance subframe pointer */
393 9750360 : c_indx = 0;
394 21784320 : for ( nS = 0; nS < num_src; nS++ )
395 : {
396 12033960 : if ( !( ivas_format == MC_FORMAT && nS == lfe_idx ) ) /* Skip LFE for MC */
397 : {
398 11923440 : hBinRendererTd->Sources[c_indx]->InputFrame_p += subframe_length;
399 11923440 : c_indx++;
400 : }
401 : }
402 :
403 : /* update combined orientation access index */
404 9750360 : ivas_combined_orientation_update_index( hCombinedOrientationData, subframe_length );
405 : }
406 :
407 6091464 : if ( hReverb != NULL )
408 : {
409 : /* add reverb to rendered signals */
410 3006684 : v_add( reverb_signal[0], output[0], output[0], output_frame );
411 3006684 : v_add( reverb_signal[1], output[1], output[1], output_frame );
412 : }
413 :
414 6091464 : return IVAS_ERR_OK;
415 : }
416 :
417 :
418 : /*---------------------------------------------------------------------*
419 : * TDREND_GetMix()
420 : *
421 : * Render one 5 ms subframe from the mixer
422 : *---------------------------------------------------------------------*/
423 :
424 10283808 : ivas_error TDREND_GetMix(
425 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
426 : float *output[], /* i/o: ISM object synth / rendered output in 0,1 */
427 : const int16_t subframe_length, /* i/o: subframe length */
428 : const int16_t subframe_idx /* i : Subframe index to 5 ms subframe */
429 : )
430 : {
431 : int16_t i;
432 : TDREND_SRC_t *Src_p;
433 : TDREND_SRC_SPATIAL_t *SrcSpatial_p;
434 : TDREND_SRC_REND_t *SrcRend_p;
435 : ivas_error error;
436 : float output_buf[2][L_SPATIAL_SUBFR_48k]; /* Temp buffer for left/right rendered signal */
437 : float hrf_left_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
438 : float hrf_right_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
439 : int16_t intp_count;
440 : int16_t currShift, prevShift, transition_len, length_in2;
441 :
442 10283808 : error = IVAS_ERR_OK;
443 :
444 : /* Clear the output buffer to accumulate rendered sources */
445 10283808 : set_f( output_buf[0], 0.0f, subframe_length );
446 10283808 : set_f( output_buf[1], 0.0f, subframe_length );
447 :
448 : /* Clear interpolation buffers and counter */
449 10283808 : set_f( hrf_left_delta, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
450 10283808 : set_f( hrf_right_delta, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
451 10283808 : intp_count = 0;
452 :
453 : /* Create the mix */
454 : /* Loop through the source list and render each source */
455 23858655 : for ( i = 0; i < hBinRendererTd->NumOfSrcs; i++ )
456 : {
457 13574847 : Src_p = hBinRendererTd->Sources[i];
458 13574847 : SrcSpatial_p = Src_p->SrcSpatial_p;
459 13574847 : SrcRend_p = Src_p->SrcRend_p;
460 :
461 : /* Update rendering params if needed */
462 13574847 : if ( ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) && ( hBinRendererTd->Listener_p->PoseUpdated || SrcSpatial_p->Updated ) )
463 : {
464 9857616 : TDREND_SRC_REND_UpdateFiltersFromSpatialParams( hBinRendererTd, SrcRend_p, SrcSpatial_p, Src_p->hrf_left_prev,
465 9857616 : Src_p->hrf_right_prev, hrf_left_delta, hrf_right_delta, &intp_count, &Src_p->filterlength, &Src_p->itd, &Src_p->Gain, Src_p );
466 :
467 : /* For large ITD values at lower sampling rate, check if the transition can be done */
468 9857616 : if ( Src_p->itd * Src_p->previtd < 0 )
469 : {
470 206419 : currShift = (int16_t) abs( Src_p->itd );
471 206419 : prevShift = (int16_t) abs( Src_p->previtd );
472 206419 : transition_len = subframe_length - max( 0, SFX_SPAT_BIN_SINC_M - currShift );
473 206419 : length_in2 = transition_len - (int16_t) ( ( (float) ( transition_len * prevShift ) / ( (float) ( prevShift + currShift ) ) ) + 0.5f ) - currShift;
474 206419 : if ( length_in2 <= 0 )
475 : {
476 : /* Subframe too short for ITD transition -- change to ITD=0 and push the rest of the transition to next subframe */
477 0 : Src_p->itd = 0;
478 : }
479 : }
480 : }
481 :
482 : /* Render source if needed */
483 13574847 : if ( ( SrcRend_p->InputAvailable == TRUE ) && ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) )
484 : {
485 13574847 : error = TDREND_REND_RenderSourceHRFilt( Src_p, hrf_left_delta, hrf_right_delta, intp_count, output_buf, subframe_length );
486 : }
487 : }
488 :
489 : /* Populate output variable */
490 10283808 : mvr2r( output_buf[0], output[0] + subframe_idx * subframe_length, subframe_length ); /* Left */
491 10283808 : mvr2r( output_buf[1], output[1] + subframe_idx * subframe_length, subframe_length ); /* Right */
492 :
493 : /* Clear the PoseUpdated and Source position update flags */
494 10283808 : TDREND_Clear_Update_flags( hBinRendererTd );
495 :
496 10283808 : return error;
497 : }
498 :
499 :
500 : /*---------------------------------------------------------------------*
501 : * TDREND_Clear_Update_flags()
502 : *
503 : * Initializes the audio mixer module
504 : *---------------------------------------------------------------------*/
505 :
506 10283808 : static void TDREND_Clear_Update_flags(
507 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd /* i/o: TD renderer handle */
508 : )
509 : {
510 : int16_t i;
511 :
512 10283808 : hBinRendererTd->Listener_p->PoseUpdated = FALSE;
513 :
514 23858655 : for ( i = 0; i < hBinRendererTd->NumOfSrcs; i++ )
515 : {
516 13574847 : hBinRendererTd->Sources[i]->SrcSpatial_p->Updated = FALSE;
517 13574847 : hBinRendererTd->Sources[i]->SrcRend_p->SrcGainUpdated = FALSE;
518 : }
519 :
520 10283808 : return;
521 : }
522 :
523 :
524 : /*---------------------------------------------------------------------*
525 : * TDREND_Update_object_positions()
526 : *
527 : * Update object position(s)
528 : *---------------------------------------------------------------------*/
529 :
530 5792274 : ivas_error TDREND_Update_object_positions(
531 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD Renderer handle */
532 : const int16_t num_src, /* i : number of sources to render */
533 : const IVAS_FORMAT in_format, /* i : Format of input sources */
534 : const ISM_METADATA_HANDLE *hIsmMetaData /* i : Input metadata for ISM objects */
535 : )
536 : {
537 : #ifndef NONBE_1377_REND_DIRATT_CONF
538 : TDREND_DirAtten_t *DirAtten_p;
539 : #endif
540 : int16_t nS;
541 : float Pos[3];
542 : float Dir[3];
543 : ivas_error error;
544 : #ifndef NONBE_1377_REND_DIRATT_CONF
545 : DirAtten_p = hBinRendererTd->DirAtten_p;
546 : #endif
547 :
548 : /* For each source, write the frame data to the source object*/
549 13299663 : for ( nS = 0; nS < num_src; nS++ )
550 : {
551 7507389 : if ( in_format == ISM_FORMAT || in_format == MASA_ISM_FORMAT || in_format == SBA_ISM_FORMAT )
552 : {
553 : /* Update the source positions */
554 : /* Source position and direction */
555 5876853 : angles_to_vec( hIsmMetaData[nS]->radius, hIsmMetaData[nS]->azimuth, hIsmMetaData[nS]->elevation, Pos );
556 5876853 : angles_to_vec( 1.0f, hIsmMetaData[nS]->yaw, hIsmMetaData[nS]->pitch, Dir );
557 :
558 5876853 : if ( ( error = TDREND_MIX_SRC_SetPos( hBinRendererTd, nS, Pos ) ) != IVAS_ERR_OK )
559 : {
560 0 : return error;
561 : }
562 :
563 : #ifndef NONBE_1377_REND_DIRATT_CONF
564 : if ( ( error = TDREND_MIX_SRC_SetDirAtten( hBinRendererTd, nS, DirAtten_p ) ) != IVAS_ERR_OK )
565 : {
566 : return error;
567 : }
568 : #endif
569 5876853 : if ( ( error = TDREND_MIX_SRC_SetGain( hBinRendererTd, nS, hIsmMetaData[nS]->gain ) ) != IVAS_ERR_OK )
570 : {
571 0 : return error;
572 : }
573 :
574 5876853 : if ( hIsmMetaData[nS]->non_diegetic_flag )
575 : {
576 2484 : Pos[0] = 0;
577 2484 : Pos[1] = hIsmMetaData[nS]->azimuth / 90.f;
578 2484 : Pos[2] = 0;
579 2484 : if ( ( error = TDREND_MIX_SRC_SetPos( hBinRendererTd, nS, Pos ) ) != IVAS_ERR_OK )
580 : {
581 0 : return error;
582 : }
583 2484 : hBinRendererTd->Sources[nS]->SrcSpatial_p->PosType = TDREND_POSTYPE_NON_DIEGETIC;
584 : }
585 : else
586 : {
587 5874369 : hBinRendererTd->Sources[nS]->SrcSpatial_p->PosType = TDREND_POSTYPE_ABSOLUTE;
588 : }
589 :
590 5876853 : if ( ( error = TDREND_MIX_SRC_SetDir( hBinRendererTd, nS, Dir ) ) != IVAS_ERR_OK )
591 : {
592 0 : return error;
593 : }
594 : }
595 : }
596 :
597 5792274 : return IVAS_ERR_OK;
598 : }
599 :
600 :
601 : /*---------------------------------------------------------------------*
602 : * TDREND_Update_listener_orientation()
603 : *
604 : * Update listener orientation (s)
605 : *---------------------------------------------------------------------*/
606 :
607 10283808 : ivas_error TDREND_Update_listener_orientation(
608 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD Renderer handle */
609 : const int16_t headRotEnabled, /* i : Headrotation flag */
610 : const IVAS_QUATERNION *headPosition, /* i : Listener orientation */
611 : const IVAS_VECTOR3 *Pos /* i : Listener Position */
612 : )
613 : {
614 : float FrontVec[3];
615 : float UpVec[3];
616 : float Rmat[3][3];
617 : float Pos_p[3];
618 : ivas_error error;
619 :
620 10283808 : if ( headRotEnabled )
621 : {
622 : /* Obtain head rotation matrix */
623 5187447 : QuatToRotMat( *headPosition, Rmat );
624 : /* Apply rotation matrix to looking vector [1;0;0] */
625 5187447 : FrontVec[0] = Rmat[0][0];
626 5187447 : FrontVec[1] = Rmat[0][1];
627 5187447 : FrontVec[2] = Rmat[0][2];
628 : /* Apply rotation matrix to up vector [0;0;1] */
629 5187447 : UpVec[0] = Rmat[2][0];
630 5187447 : UpVec[1] = Rmat[2][1];
631 5187447 : UpVec[2] = Rmat[2][2];
632 5187447 : if ( Pos != NULL )
633 : {
634 : /* Input position */
635 5187447 : Pos_p[0] = ( *Pos ).x;
636 5187447 : Pos_p[1] = ( *Pos ).y;
637 5187447 : Pos_p[2] = ( *Pos ).z;
638 : }
639 : else
640 : {
641 : /* Listener at the origin */
642 0 : Pos_p[0] = 0.0f;
643 0 : Pos_p[1] = 0.0f;
644 0 : Pos_p[2] = 0.0f;
645 : }
646 : }
647 : else
648 : {
649 : /* Oriented with looking vector along the x axis */
650 5096361 : FrontVec[0] = 1.0f;
651 5096361 : FrontVec[1] = 0.0f;
652 5096361 : FrontVec[2] = 0.0f;
653 : /* Oriented with up vector along the z axis */
654 5096361 : UpVec[0] = 0.0f;
655 5096361 : UpVec[1] = 0.0f;
656 5096361 : UpVec[2] = 1.0f;
657 : /* Listener at the origin */
658 5096361 : Pos_p[0] = 0.0f;
659 5096361 : Pos_p[1] = 0.0f;
660 5096361 : Pos_p[2] = 0.0f;
661 : }
662 :
663 : /* Set the listener position and orientation:*/
664 10283808 : TDREND_MIX_LIST_SetPos( hBinRendererTd, Pos_p );
665 10283808 : error = TDREND_MIX_LIST_SetOrient( hBinRendererTd, FrontVec, UpVec );
666 :
667 10283808 : return error;
668 : }
669 :
670 :
671 : /*---------------------------------------------------------------------*
672 : * ivas_td_binaural_open_ext()
673 : *
674 : *
675 : *---------------------------------------------------------------------*/
676 :
677 23382 : ivas_error ivas_td_binaural_open_ext(
678 : TDREND_WRAPPER *pTDRend,
679 : AUDIO_CONFIG inConfig,
680 : RENDER_CONFIG_DATA *hRendCfg, /* i : Renderer configuration */
681 : LSSETUP_CUSTOM_STRUCT *customLsInput,
682 : #ifdef NONBE_1377_REND_DIRATT_CONF
683 : const int32_t outFs, /* i: output sampling rate */
684 : const int16_t object_id /* i: Object ID */
685 : )
686 : #else
687 : const int32_t outFs )
688 : #endif
689 : {
690 : int16_t nchan_transport;
691 : AUDIO_CONFIG transport_config;
692 : IVAS_FORMAT ivas_format;
693 : IVAS_OUTPUT_SETUP hTransSetup;
694 : ivas_error error;
695 :
696 23382 : float *distAtt = NULL;
697 23382 : float *directivity = NULL;
698 :
699 23382 : if ( inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM )
700 : {
701 23238 : if ( ( error = getAudioConfigNumChannels( inConfig, &nchan_transport ) ) != IVAS_ERR_OK )
702 : {
703 0 : return error;
704 : }
705 : }
706 : else
707 : {
708 144 : nchan_transport = customLsInput->num_spk;
709 : }
710 :
711 23382 : transport_config = inConfig;
712 23382 : ivas_format = ( getAudioConfigType( inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) ? MC_FORMAT : ISM_FORMAT;
713 :
714 23382 : hTransSetup.ls_azimuth = NULL;
715 23382 : hTransSetup.ls_elevation = NULL;
716 :
717 23382 : if ( inConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM )
718 : {
719 144 : hTransSetup.ls_azimuth = customLsInput->ls_azimuth;
720 144 : hTransSetup.ls_elevation = customLsInput->ls_elevation;
721 : }
722 :
723 23382 : if ( NULL != hRendCfg )
724 : {
725 : #ifdef NONBE_1377_REND_DIRATT_CONF
726 14592 : directivity = hRendCfg->directivity + 3 * object_id;
727 : #else
728 : directivity = hRendCfg->directivity;
729 : #endif
730 14592 : distAtt = hRendCfg->distAtt;
731 : }
732 :
733 23382 : return ivas_td_binaural_open_unwrap( pTDRend->hHrtfTD, outFs, nchan_transport, ivas_format, transport_config, directivity, distAtt, hTransSetup, &pTDRend->hBinRendererTd, &pTDRend->binaural_latency_ns );
734 : }
735 :
736 :
737 : /*---------------------------------------------------------------------*
738 : * ivas_td_binaural_renderer_ext()
739 : *
740 : * Receives the current frames for the object streams, updates metadata
741 : * and renders the current frame.
742 : *---------------------------------------------------------------------*/
743 :
744 6091464 : ivas_error ivas_td_binaural_renderer_ext(
745 : const TDREND_WRAPPER *pTDRend, /* i : TD Renderer wrapper structure */
746 : const AUDIO_CONFIG inConfig, /* i : Input audio configuration */
747 : const LSSETUP_CUSTOM_STRUCT *customLsInput, /* i : Input custom loudspeaker layout */
748 : const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* i : Combined head and external orientations */
749 : const IVAS_ISM_METADATA *currentPos, /* i : Object position */
750 : const REVERB_HANDLE hReverb, /* i : Reverberator handle */
751 : const int16_t ism_md_subframe_update_ext, /* i : Metadata Delay in subframes to sync with audio delay */
752 : const int32_t output_Fs, /* i : output sampling rate */
753 : const int16_t output_frame, /* i : output frame length */
754 : float output[][L_FRAME48k] /* i/o: SCE channels / Binaural synthesis */
755 : )
756 : {
757 : ISM_METADATA_FRAME hIsmMetaDataFrame;
758 : ISM_METADATA_HANDLE hIsmMetaData[1];
759 : int16_t lfe_idx;
760 : int16_t num_src;
761 : IVAS_FORMAT ivas_format;
762 : IVAS_REND_AudioConfigType inConfigType;
763 : AUDIO_CONFIG transport_config;
764 : ivas_error error;
765 : float *p_output[MAX_OUTPUT_CHANNELS];
766 : int16_t ch;
767 :
768 103554888 : for ( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ )
769 : {
770 97463424 : p_output[ch] = output[ch];
771 : }
772 :
773 6091464 : push_wmops( "ivas_td_binaural_renderer_ext" );
774 :
775 6091464 : inConfigType = getAudioConfigType( inConfig );
776 6091464 : lfe_idx = LFE_CHANNEL;
777 6091464 : hIsmMetaData[0] = NULL;
778 :
779 :
780 6091464 : if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED )
781 : {
782 147144 : ivas_format = MC_FORMAT;
783 147144 : transport_config = inConfig;
784 147144 : if ( inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM )
785 : {
786 69048 : if ( ( error = getAudioConfigNumChannels( inConfig, &num_src ) ) != IVAS_ERR_OK )
787 : {
788 0 : return error;
789 : }
790 : }
791 : else
792 : {
793 78096 : lfe_idx = ( customLsInput->num_lfe > 0 ) ? customLsInput->lfe_idx[0] : -1;
794 78096 : num_src = customLsInput->num_spk + customLsInput->num_lfe;
795 : }
796 : }
797 : else
798 : {
799 5944320 : ivas_format = ISM_FORMAT;
800 5944320 : num_src = 1;
801 5944320 : transport_config = IVAS_AUDIO_CONFIG_ISM1;
802 5944320 : hIsmMetaData[0] = &hIsmMetaDataFrame;
803 5944320 : hIsmMetaData[0]->azimuth = currentPos->azimuth;
804 5944320 : hIsmMetaData[0]->elevation = currentPos->elevation;
805 5944320 : hIsmMetaData[0]->yaw = currentPos->yaw;
806 5944320 : hIsmMetaData[0]->pitch = currentPos->pitch;
807 5944320 : hIsmMetaData[0]->radius = currentPos->radius;
808 5944320 : hIsmMetaData[0]->gain = 1.0f;
809 :
810 5944320 : hIsmMetaData[0]->non_diegetic_flag = currentPos->non_diegetic_flag;
811 : }
812 :
813 6091464 : if ( ( error = ivas_td_binaural_renderer_unwrap( hReverb, transport_config, pTDRend->hBinRendererTd, num_src, lfe_idx, ivas_format, hIsmMetaData, *hCombinedOrientationData,
814 6091464 : ism_md_subframe_update_ext, p_output, output_frame, (int16_t) ( ( output_frame * FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) / output_Fs ) ) ) != IVAS_ERR_OK )
815 : {
816 0 : return error;
817 : }
818 :
819 6091464 : pop_wmops();
820 :
821 6091464 : return IVAS_ERR_OK;
822 : }
823 :
824 :
825 : /*---------------------------------------------------------------------*
826 : * angles_to_vec()
827 : *
828 : * Convert azimuth and elevation angles to position/orientation vector
829 : *---------------------------------------------------------------------*/
830 :
831 11755143 : static void angles_to_vec(
832 : const float radius, /* i : radius */
833 : const float azimuth, /* i : Azimuth angle */
834 : const float elevation, /* i : Elevation angle */
835 : float *vec /* o : Pos/Dir vector */
836 : )
837 : {
838 11755143 : vec[0] = radius * cosf( elevation * PI_OVER_180 ) * cosf( azimuth * PI_OVER_180 );
839 11755143 : vec[1] = radius * cosf( elevation * PI_OVER_180 ) * sinf( azimuth * PI_OVER_180 );
840 11755143 : vec[2] = radius * sinf( elevation * PI_OVER_180 );
841 :
842 11755143 : return;
843 : }
|