Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : #include <stdint.h>
34 : #include "options.h"
35 : #include <math.h>
36 : #include "prot.h"
37 : #include "ivas_prot_rend.h"
38 : #include "wmc_auto.h"
39 : #ifdef DEBUGGING
40 : #include "debug.h"
41 : #endif
42 :
43 :
44 : /*---------------------------------------------------------------------*
45 : * Local function prototypes
46 : *---------------------------------------------------------------------*/
47 :
48 : static void TDREND_SRC_SPATIAL_Dealloc( TDREND_SRC_SPATIAL_t *SrcSpatial_p );
49 :
50 : static void TDREND_SRC_SPATIAL_Init( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_PosType_t PosType );
51 :
52 : static void TDREND_SRC_SPATIAL_SetDirAtten( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_DirAtten_t *DirAtten_p );
53 :
54 : static void TDREND_SRC_SPATIAL_SetDistAtten( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_DistAtten_t *DistAtten_p );
55 :
56 : static void TDREND_SRC_SPATIAL_SetGain( const TDREND_SRC_t *Src_p, const float Gain );
57 :
58 : static float TDREND_SRC_SPATIAL_GetDirGain( const TDREND_DirAtten_t *DirAtten_p, const float *Front_p, const float *RelPos_p );
59 :
60 : static float TDREND_SRC_SPATIAL_GetDistGain( const TDREND_DistAtten_t *DistAtten_p, const float Dist );
61 :
62 : static ivas_error TDREND_SRC_REND_Alloc( TDREND_SRC_REND_t **SrcRend_pp );
63 :
64 : static void TDREND_SRC_REND_Init( TDREND_SRC_REND_t *SrcRend_p );
65 :
66 :
67 : /*-------------------------------------------------------------------*
68 : * TDREND_MIX_SRC_SetPos()
69 : *
70 : * Set source position
71 : --------------------------------------------------------------------*/
72 :
73 2707097 : ivas_error TDREND_MIX_SRC_SetPos(
74 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
75 : const int16_t SrcInd, /* i : Source index */
76 : const float *Vec_p /* i : Position vector */
77 : )
78 : {
79 : TDREND_SRC_SPATIAL_t *SrcSpatial_p;
80 :
81 2707097 : if ( SrcInd > hBinRendererTd->MaxSrcInd )
82 : {
83 0 : return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index!\n" ) );
84 : }
85 : else
86 : {
87 2707097 : SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
88 :
89 2707097 : if ( SrcSpatial_p->Pos_p[0] != Vec_p[0] || SrcSpatial_p->Pos_p[1] != Vec_p[1] || SrcSpatial_p->Pos_p[2] != Vec_p[2] )
90 : {
91 2218488 : mvr2r( Vec_p, SrcSpatial_p->Pos_p, 3 );
92 2218488 : SrcSpatial_p->Updated = TRUE;
93 : }
94 : }
95 :
96 2707097 : return IVAS_ERR_OK;
97 : }
98 :
99 :
100 : /*-------------------------------------------------------------------*
101 : * TDREND_MIX_SRC_SetDir()
102 : *
103 : * Set source direction
104 : --------------------------------------------------------------------*/
105 :
106 2607939 : ivas_error TDREND_MIX_SRC_SetDir(
107 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
108 : const int16_t SrcInd, /* i : Source index */
109 : const float *Vec_p /* i : Direction vector */
110 : )
111 : {
112 : TDREND_SRC_SPATIAL_t *SrcSpatial_p;
113 :
114 : /* Value verification */
115 2607939 : if ( ( Vec_p[0] == 0.0f ) && ( Vec_p[1] == 0.0f ) && ( Vec_p[2] == 0.0f ) )
116 : {
117 0 : return ( IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Zero direction vector. Command is ignored!\n" ) );
118 : }
119 2607939 : if ( SrcInd > hBinRendererTd->MaxSrcInd )
120 : {
121 0 : return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index!\n" ) );
122 : }
123 : else
124 : {
125 2607939 : SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
126 2607939 : TDREND_SPATIAL_VecNormalize( Vec_p, SrcSpatial_p->Front_p );
127 2607939 : SrcSpatial_p->Updated = TRUE;
128 : }
129 :
130 2607939 : return IVAS_ERR_OK;
131 : }
132 :
133 :
134 : /*-------------------------------------------------------------------*
135 : * TDREND_MIX_SRC_SetGain()
136 : *
137 : * Set source gain
138 : --------------------------------------------------------------------*/
139 :
140 2604330 : ivas_error TDREND_MIX_SRC_SetGain(
141 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
142 : const int16_t SrcInd, /* i : Source index */
143 : const float Gain /* i : Gain */
144 : )
145 : {
146 2604330 : TDREND_SRC_SPATIAL_SetGain( hBinRendererTd->Sources[SrcInd], Gain );
147 :
148 2604330 : return IVAS_ERR_OK;
149 : }
150 :
151 :
152 : /*-------------------------------------------------------------------*
153 : * TDREND_MIX_SRC_SetDirAtten()
154 : *
155 : * Set directional attenuation for the mixer.
156 : --------------------------------------------------------------------*/
157 :
158 2643981 : ivas_error TDREND_MIX_SRC_SetDirAtten(
159 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
160 : const int16_t SrcInd, /* i : Source index */
161 : const TDREND_DirAtten_t *DirAtten_p /* i : Directional attenuation specifier */
162 : )
163 : {
164 : TDREND_SRC_SPATIAL_t *SrcSpatial_p;
165 2643981 : if ( SrcInd > hBinRendererTd->MaxSrcInd )
166 : {
167 0 : return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index\n" ) );
168 : }
169 : else
170 : {
171 2643981 : SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
172 2643981 : TDREND_SRC_SPATIAL_SetDirAtten( SrcSpatial_p, DirAtten_p );
173 : }
174 :
175 2643981 : return IVAS_ERR_OK;
176 : }
177 :
178 : /*-------------------------------------------------------------------*
179 : * TDREND_MIX_SRC_SetDistAtten()
180 : *
181 : * Set distance attenuation for the mixer.
182 : --------------------------------------------------------------------*/
183 :
184 39651 : ivas_error TDREND_MIX_SRC_SetDistAtten(
185 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
186 : const int16_t SrcInd, /* i : Source index */
187 : const TDREND_DistAtten_t *DistAtten_p /* i : Distance attenuation specifier */
188 : )
189 : {
190 : TDREND_SRC_SPATIAL_t *SrcSpatial_p;
191 39651 : if ( SrcInd > hBinRendererTd->MaxSrcInd )
192 : {
193 0 : return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index\n" ) );
194 : }
195 : else
196 : {
197 39651 : SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
198 39651 : TDREND_SRC_SPATIAL_SetDistAtten( SrcSpatial_p, DistAtten_p );
199 : }
200 :
201 39651 : return IVAS_ERR_OK;
202 : }
203 :
204 : /*-------------------------------------------------------------------*
205 : * TDREND_MIX_SRC_SetPlayState()
206 : *
207 : * Set play state for the source.
208 : --------------------------------------------------------------------*/
209 :
210 3609 : ivas_error TDREND_MIX_SRC_SetPlayState(
211 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
212 : const int16_t SrcInd, /* i : Source index */
213 : const TDREND_PlayStatus_t PlayStatus /* i : Play state */
214 : )
215 : {
216 3609 : if ( SrcInd > hBinRendererTd->MaxSrcInd )
217 : {
218 0 : return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index\n" ) );
219 : }
220 : else
221 : {
222 3609 : hBinRendererTd->Sources[SrcInd]->SrcRend_p->PlayStatus = PlayStatus;
223 : }
224 3609 : return IVAS_ERR_OK;
225 : }
226 :
227 :
228 : /*-------------------------------------------------------------------*
229 : * TDREND_SRC_REND_Alloc()
230 : *
231 : * Renderer allocation
232 : --------------------------------------------------------------------*/
233 :
234 39651 : static ivas_error TDREND_SRC_REND_Alloc(
235 : TDREND_SRC_REND_t **SrcRend_pp /* i/o: Source object */
236 : )
237 : {
238 : TDREND_SRC_REND_t *SrcRend_p;
239 :
240 39651 : *SrcRend_pp = NULL;
241 :
242 : /* Allocate the TDREND_SRC_REND_t variable */
243 39651 : if ( ( SrcRend_p = (TDREND_SRC_REND_t *) malloc( sizeof( TDREND_SRC_REND_t ) ) ) == NULL )
244 : {
245 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "SrcRend_p allocation error\n" ) );
246 : }
247 :
248 39651 : *SrcRend_pp = SrcRend_p;
249 :
250 39651 : return IVAS_ERR_OK;
251 : }
252 :
253 :
254 : /*-------------------------------------------------------------------*
255 : * TDREND_SRC_REND_Init()
256 : *
257 : * Initialize rendering aspects of source.
258 : --------------------------------------------------------------------*/
259 :
260 39651 : static void TDREND_SRC_REND_Init(
261 : TDREND_SRC_REND_t *SrcRend_p /* i/o: Source object */
262 : )
263 : {
264 : int16_t nC;
265 :
266 : /* Internal state */
267 39651 : SrcRend_p->InputAvailable = FALSE;
268 39651 : SrcRend_p->PlayStatus = TDREND_PLAYSTATUS_PLAYING;
269 : /* SrcGain */
270 79302 : for ( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ )
271 : {
272 39651 : SrcRend_p->SrcGainMin_p[nC] = 0.0f;
273 39651 : SrcRend_p->SrcGain_p[nC] = 1.0f;
274 39651 : SrcRend_p->SrcGainMax_p[nC] = 2.0f;
275 : }
276 39651 : SrcRend_p->SrcGainUpdated = FALSE;
277 :
278 : /* Init directional and distance gains */
279 79302 : for ( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ )
280 : {
281 39651 : SrcRend_p->DirGain_p[nC] = 1.0f;
282 39651 : SrcRend_p->DistGain_p[nC] = 1.0f;
283 : }
284 :
285 :
286 39651 : return;
287 : }
288 :
289 :
290 : /*-------------------------------------------------------------------*
291 : * TDREND_SRC_REND_UpdateFiltersFromSpatialParams()
292 : *
293 : * Update the HR filter due to spatial change.
294 : --------------------------------------------------------------------*/
295 :
296 4816792 : void TDREND_SRC_REND_UpdateFiltersFromSpatialParams(
297 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
298 : TDREND_SRC_REND_t *SrcRend_p, /* i/o: Source object */
299 : TDREND_SRC_SPATIAL_t *SrcSpatial_p, /* i : Spatial aspects of source */
300 : float *hrf_left_prev, /* o : Left filter */
301 : float *hrf_right_prev, /* o : Right filter */
302 : float *hrf_left_delta, /* o : Left filter interpolation delta */
303 : float *hrf_right_delta, /* o : Right filter interpolation delta */
304 : int16_t *intp_count, /* o : Interpolation count */
305 : int16_t *filterlength, /* o : Length of filters */
306 : int16_t *itd, /* o : ITD value */
307 : float *Gain, /* o : Gain value */
308 : TDREND_SRC_t *Src_p /* i/o: Source pointer */
309 : )
310 : {
311 : TDREND_MIX_Listener_t *Listener_p;
312 : TDREND_HRFILT_FiltSet_t *HrFiltSet_p;
313 : float ListRelPos[3], ListRelDist;
314 : float ListRelPosAbs[3]; /* Relative position, ignoring orientation of listener */
315 : float Azim, Elev;
316 : float hrf_left[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
317 : float hrf_right[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
318 : float azim_delta;
319 : float elev_delta;
320 :
321 : /* Evaluate the HR filters from the source and listener positions and orientations */
322 4816792 : Listener_p = hBinRendererTd->Listener_p;
323 4816792 : HrFiltSet_p = hBinRendererTd->HrFiltSet_p;
324 :
325 4816792 : *filterlength = min( HrFiltSet_p->FiltLength, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
326 :
327 4816792 : if ( SrcSpatial_p->PosType == TDREND_POSTYPE_ABSOLUTE )
328 : {
329 :
330 : /* Absolute position */
331 4715472 : TDREND_SPATIAL_VecMapToNewCoordSystem( SrcSpatial_p->Pos_p, Listener_p->Pos, Listener_p->Front, Listener_p->Up, Listener_p->Right, ListRelPos, ListRelPosAbs );
332 4715472 : ListRelDist = TDREND_SPATIAL_VecNorm( ListRelPos );
333 :
334 : /* 2. Evaluate the Elevation and Azimuth angles */
335 4715472 : if ( ( ListRelPos[0] == 0 ) && ( ListRelPos[1] == 0 ) && ( ListRelPos[2] == 0 ) )
336 : {
337 49574 : Elev = 0.0;
338 49574 : Azim = 0.0;
339 : }
340 : else
341 : {
342 4665898 : Elev = _180_OVER_PI * atan2f( ListRelPos[2], sqrtf( ListRelPos[0] * ListRelPos[0] + ListRelPos[1] * ListRelPos[1] ) );
343 : /* Basis set is [front, right, up], which is a left-handed coordinate system. Minus sign here is to change to a positive-left system for azimuth */
344 4665898 : Azim = -1.0f * _180_OVER_PI * (float) atan2f( ListRelPos[1], ListRelPos[0] );
345 : }
346 :
347 4715472 : GetFilterFromAngle( HrFiltSet_p, Elev, Azim, *filterlength, hrf_left, hrf_right, itd );
348 :
349 : /* 6. Evaluate the directional and distance gains */
350 : /* Directional gain */
351 4715472 : *SrcRend_p->DirGain_p = 1.0f;
352 4715472 : if ( SrcSpatial_p->DirAttenEnabled )
353 : {
354 4715472 : *SrcRend_p->DirGain_p = TDREND_SRC_SPATIAL_GetDirGain( &SrcSpatial_p->DirAtten, SrcSpatial_p->Front_p, ListRelPosAbs );
355 : }
356 :
357 : /* Distance gain */
358 4715472 : *SrcRend_p->DistGain_p = 1.0f;
359 4715472 : if ( hBinRendererTd->UseCommonDistAttenModel )
360 : {
361 4715472 : if ( hBinRendererTd->DistAttenEnabled )
362 : {
363 4715472 : SrcSpatial_p->DistAtten.DistAttenModel = hBinRendererTd->DistAttenModel;
364 4715472 : *SrcRend_p->DistGain_p = TDREND_SRC_SPATIAL_GetDistGain( &SrcSpatial_p->DistAtten, ListRelDist );
365 : }
366 : }
367 : else
368 : {
369 0 : if ( SrcSpatial_p->DistAttenEnabled )
370 : {
371 0 : *SrcRend_p->DistGain_p = TDREND_SRC_SPATIAL_GetDistGain( &SrcSpatial_p->DistAtten, ListRelDist );
372 : }
373 : }
374 :
375 : /* Update total gains */
376 4715472 : *Gain = ( *SrcRend_p->SrcGain_p ) * ( *SrcRend_p->DirGain_p ) * ( *SrcRend_p->DistGain_p ) * hBinRendererTd->Gain;
377 :
378 : /* Delta for interpolation, in case the angular step exceeds MAX_ANGULAR_STEP */
379 4715472 : elev_delta = Elev - Src_p->elev_prev;
380 4715472 : azim_delta = Azim - Src_p->azim_prev;
381 4715472 : Src_p->elev_prev = Elev;
382 4715472 : Src_p->azim_prev = Azim;
383 :
384 4715472 : azim_delta = ( azim_delta > 180.0f ) ? ( azim_delta - 360 ) : ( ( azim_delta < -180.0f ) ? ( azim_delta + 360 ) : ( azim_delta ) ); /* map to -180:180 range */
385 4715472 : *intp_count = min( MAX_INTERPOLATION_STEPS, max( (int16_t) ( fabsf( azim_delta ) * MAX_ANGULAR_STEP_INV ), (int16_t) ( fabsf( elev_delta ) * MAX_ANGULAR_STEP_INV ) ) );
386 : }
387 : else /* TDREND_POSTYPE_NON_DIEGETIC */
388 : {
389 101320 : *itd = 0;
390 101320 : *Gain = 1.0f;
391 101320 : set_f( hrf_left, 0.0f, *filterlength );
392 101320 : set_f( hrf_right, 0.0f, *filterlength );
393 101320 : hrf_left[0] = ( SrcSpatial_p->Pos_p[1] + 1.f ) * 0.5f;
394 101320 : hrf_right[0] = 1.f - hrf_left[0];
395 101320 : *intp_count = MAX_INTERPOLATION_STEPS;
396 101320 : Src_p->elev_prev = 0;
397 101320 : Src_p->azim_prev = 360.0f; /* Dummy angle -- sets max interpolation if switching to TDREND_POSTYPE_ABSOLUTE */
398 : }
399 :
400 4816792 : if ( ( *intp_count > 0 ) )
401 : {
402 : /* Set deltas for interpolation */
403 4320375 : v_sub( hrf_left, hrf_left_prev, hrf_left_delta, *filterlength );
404 4320375 : v_multc( hrf_left_delta, 1.0f / *intp_count, hrf_left_delta, *filterlength );
405 4320375 : v_sub( hrf_right, hrf_right_prev, hrf_right_delta, *filterlength );
406 4320375 : v_multc( hrf_right_delta, 1.0f / *intp_count, hrf_right_delta, *filterlength );
407 : }
408 : else
409 : {
410 : /* No interpolation, just set the new filters and reset deltas */
411 496417 : mvr2r( hrf_left, hrf_left_prev, *filterlength );
412 496417 : mvr2r( hrf_right, hrf_right_prev, *filterlength );
413 496417 : set_f( hrf_left_delta, 0.0f, *filterlength );
414 496417 : set_f( hrf_right_delta, 0.0f, *filterlength );
415 : }
416 :
417 4816792 : return;
418 : }
419 :
420 :
421 : /*-------------------------------------------------------------------*
422 : * TDREND_SRC_SPATIAL_Alloc()
423 : *
424 : * Allocatie spatial properties of a source.
425 : --------------------------------------------------------------------*/
426 :
427 39651 : static ivas_error TDREND_SRC_SPATIAL_Alloc(
428 : TDREND_SRC_SPATIAL_t **SrcSpatial_pp /* i/o: Source spatial parameters */
429 : )
430 : {
431 : TDREND_SRC_SPATIAL_t *SrcSpatial_p;
432 :
433 39651 : *SrcSpatial_pp = NULL;
434 :
435 : /* Allocate the TDREND_SRC_t variable */
436 39651 : if ( ( SrcSpatial_p = (TDREND_SRC_SPATIAL_t *) malloc( sizeof( TDREND_SRC_SPATIAL_t ) ) ) == NULL )
437 : {
438 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "TDREND_SRC_SPATIAL_t allocation error\n" ) );
439 : }
440 :
441 39651 : *SrcSpatial_pp = SrcSpatial_p;
442 :
443 39651 : return IVAS_ERR_OK;
444 : }
445 :
446 :
447 : /*-------------------------------------------------------------------*
448 : * TDREND_SRC_SPATIAL_Dealloc()
449 : *
450 : * Deallocate spatial properties of a source.
451 : --------------------------------------------------------------------*/
452 :
453 39651 : static void TDREND_SRC_SPATIAL_Dealloc(
454 : TDREND_SRC_SPATIAL_t *SrcSpatial_p /* i/o: Source spatial parameters */
455 : )
456 : {
457 39651 : if ( SrcSpatial_p == NULL )
458 : {
459 0 : return;
460 : }
461 : /* Free the SrcSpatial_p variable */
462 39651 : free( SrcSpatial_p );
463 39651 : SrcSpatial_p = NULL;
464 :
465 39651 : return;
466 : }
467 :
468 :
469 : /*-------------------------------------------------------------------*
470 : * TDREND_SRC_SPATIAL_Init()
471 : *
472 : * Initialize spatial properties of a source.
473 : --------------------------------------------------------------------*/
474 :
475 39651 : static void TDREND_SRC_SPATIAL_Init(
476 : TDREND_SRC_SPATIAL_t *SrcSpatial_p, /* i/o: Source spatial parameters */
477 : const TDREND_PosType_t PosType /* i : Relative/absolute position type */
478 : )
479 : {
480 : int16_t nC;
481 :
482 : /* Initialize variables */
483 39651 : SrcSpatial_p->Updated = FALSE;
484 :
485 : /* Source position, velocity and direction vectors */
486 39651 : SrcSpatial_p->PosType = PosType;
487 79302 : for ( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ )
488 : {
489 : /* Source position */
490 39651 : TDREND_SPATIAL_VecInit( SrcSpatial_p->Pos_p + nC * 3, 0.0f, 0.0f, 0.0f );
491 :
492 : /* Source direction */
493 39651 : TDREND_SPATIAL_VecInit( SrcSpatial_p->Front_p + nC * 3, 0.0f, 0.0f, 1.0f );
494 : }
495 :
496 : /* Source directional attenuation */
497 39651 : SrcSpatial_p->DirAttenEnabled = FALSE;
498 39651 : SrcSpatial_p->DirAtten.ConeInnerAngle = 360.0f;
499 39651 : SrcSpatial_p->DirAtten.ConeOuterAngle = 360.0f;
500 39651 : SrcSpatial_p->DirAtten.ConeOuterGain = 1.0f;
501 :
502 : /* Source distance attenuation */
503 39651 : SrcSpatial_p->DistAttenEnabled = FALSE;
504 39651 : SrcSpatial_p->DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED;
505 39651 : SrcSpatial_p->DistAtten.RefDist = 1.0f;
506 39651 : SrcSpatial_p->DistAtten.MaxDist = 15.75f; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */
507 39651 : SrcSpatial_p->DistAtten.RollOffFactor = 1.0f;
508 :
509 39651 : return;
510 : }
511 :
512 :
513 : /*-------------------------------------------------------------------*
514 : * TDREND_SRC_SPATIAL_SetDirAtten()
515 : *
516 : * Sets the directional attenuation mode.
517 : --------------------------------------------------------------------*/
518 :
519 2643981 : static void TDREND_SRC_SPATIAL_SetDirAtten(
520 : TDREND_SRC_SPATIAL_t *SrcSpatial_p, /* i/o: Source spatial parameters */
521 : const TDREND_DirAtten_t *DirAtten_p /* i : Directionality specification */
522 : )
523 : {
524 : /* Set directional attenuation */
525 2643981 : SrcSpatial_p->DirAttenEnabled = TRUE;
526 2643981 : SrcSpatial_p->DirAtten.ConeInnerAngle = DirAtten_p->ConeInnerAngle;
527 2643981 : SrcSpatial_p->DirAtten.ConeOuterAngle = DirAtten_p->ConeOuterAngle;
528 2643981 : SrcSpatial_p->DirAtten.ConeOuterGain = DirAtten_p->ConeOuterGain;
529 :
530 2643981 : return;
531 : }
532 :
533 : /*-------------------------------------------------------------------*
534 : * TDREND_SRC_SPATIAL_SetDistAtten()
535 : *
536 : * Sets the distance attenuation.
537 : --------------------------------------------------------------------*/
538 :
539 39651 : static void TDREND_SRC_SPATIAL_SetDistAtten(
540 : TDREND_SRC_SPATIAL_t *SrcSpatial_p,
541 : const TDREND_DistAtten_t *DistAtten_p )
542 : {
543 : /* Set distance attenuation */
544 39651 : SrcSpatial_p->DistAttenEnabled = TRUE;
545 39651 : SrcSpatial_p->DistAtten.DistAttenModel = DistAtten_p->DistAttenModel;
546 39651 : SrcSpatial_p->DistAtten.MaxDist = DistAtten_p->MaxDist;
547 39651 : SrcSpatial_p->DistAtten.RefDist = DistAtten_p->RefDist;
548 39651 : SrcSpatial_p->DistAtten.RollOffFactor = DistAtten_p->RollOffFactor;
549 :
550 39651 : return;
551 : }
552 :
553 :
554 : /*-------------------------------------------------------------------*
555 : * TDREND_SRC_SPATIAL_SetGain()
556 : *
557 : * Set the object gain
558 : --------------------------------------------------------------------*/
559 :
560 2604330 : static void TDREND_SRC_SPATIAL_SetGain(
561 : const TDREND_SRC_t *Src_p, /* i : Directional attenuation specification */
562 : const float Gain /* i : Front-pointing vector */
563 : )
564 : {
565 2604330 : Src_p->SrcRend_p->SrcGain_p[0] = Gain;
566 :
567 2604330 : return;
568 : }
569 :
570 :
571 : /*-------------------------------------------------------------------*
572 : * TDREND_SRC_SPATIAL_GetDirGain()
573 : *
574 : * Returns the gain due to object orientation.
575 : --------------------------------------------------------------------*/
576 :
577 : /*! r: Gain value */
578 4715472 : static float TDREND_SRC_SPATIAL_GetDirGain(
579 : const TDREND_DirAtten_t *DirAtten_p, /* i : Directional attenuation specification */
580 : const float *Front_p, /* i : Front-pointing vector */
581 : const float *RelPos_p /* i : Relative position */
582 : )
583 : {
584 : float DirGain;
585 : float Vec[3];
586 : float ProjCoef, NormRelPos;
587 : float AngleDeg;
588 :
589 4715472 : DirGain = 1.0f;
590 :
591 : /* Note that the front vector is unit norm, thus */
592 : /* Angle = acos ( Proj coeff from projecting -RelPos onto Front / norm(RelPos) ); */
593 4715472 : v_multc( RelPos_p, -1, Vec, 3 );
594 4715472 : ProjCoef = dotp( Vec, Front_p, 3 );
595 4715472 : NormRelPos = TDREND_SPATIAL_VecNorm( RelPos_p );
596 :
597 4715472 : if ( NormRelPos != 0.0f )
598 : {
599 4665898 : AngleDeg = _180_OVER_PI * acosf( ProjCoef / NormRelPos );
600 : }
601 : else
602 : {
603 49574 : AngleDeg = 0.0f;
604 : }
605 :
606 4715472 : if ( 2.0f * AngleDeg <= DirAtten_p->ConeInnerAngle )
607 : {
608 4403421 : DirGain = 1.0f;
609 : }
610 312051 : else if ( 2.0f * AngleDeg <= DirAtten_p->ConeOuterAngle )
611 : {
612 301021 : DirGain = 1.0f - ( 2.0f * AngleDeg - DirAtten_p->ConeInnerAngle ) / ( DirAtten_p->ConeOuterAngle - DirAtten_p->ConeInnerAngle ) * ( 1.0f - DirAtten_p->ConeOuterGain );
613 : }
614 : else
615 : {
616 11030 : DirGain = DirAtten_p->ConeOuterGain;
617 : }
618 :
619 4715472 : return DirGain;
620 : }
621 :
622 :
623 : /*-------------------------------------------------------------------*
624 : * TDREND_SRC_SPATIAL_GetDistGain()
625 : *
626 : * Returns the gain due to distance.
627 : --------------------------------------------------------------------*/
628 :
629 : /*! r: Gain value */
630 4715472 : static float TDREND_SRC_SPATIAL_GetDistGain(
631 : const TDREND_DistAtten_t *DistAtten_p, /* i : Distance attenuation parameters */
632 : const float Dist /* i : Distance value */
633 : )
634 : {
635 : float DistGain;
636 : float Dist2;
637 :
638 4715472 : DistGain = 1.0f;
639 4715472 : Dist2 = Dist;
640 :
641 4715472 : switch ( DistAtten_p->DistAttenModel )
642 : {
643 0 : case TDREND_DIST_ATTEN_MODEL_INV_DIST:
644 0 : DistGain = powf( DistAtten_p->RefDist / Dist2, DistAtten_p->RollOffFactor );
645 0 : break;
646 :
647 4715472 : case TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED:
648 4715472 : if ( Dist2 < DistAtten_p->RefDist )
649 : {
650 1271684 : Dist2 = DistAtten_p->RefDist;
651 : }
652 :
653 4715472 : if ( Dist2 > DistAtten_p->MaxDist )
654 : {
655 56614 : Dist2 = DistAtten_p->MaxDist;
656 : }
657 4715472 : DistGain = powf( DistAtten_p->RefDist / Dist2, DistAtten_p->RollOffFactor );
658 4715472 : break;
659 : }
660 :
661 4715472 : return DistGain;
662 : }
663 :
664 :
665 : /*-------------------------------------------------------------------*
666 : * TDREND_SRC_Alloc()
667 : *
668 : * Allocate a source.
669 : --------------------------------------------------------------------*/
670 :
671 39651 : ivas_error TDREND_SRC_Alloc(
672 : TDREND_SRC_t **Src_pp /* i/o: Source */
673 : )
674 : {
675 : ivas_error error;
676 : TDREND_SRC_t *Src_p;
677 :
678 39651 : *Src_pp = NULL;
679 :
680 : /* Allocate the TDREND_SRC_t variable */
681 39651 : if ( ( Src_p = (TDREND_SRC_t *) malloc( sizeof( TDREND_SRC_t ) ) ) == NULL )
682 : {
683 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, " TDREND_SRC_Alloc: Allocation error\n" ) );
684 : }
685 :
686 39651 : Src_p->SrcSpatial_p = NULL;
687 : /* If source type is dynamic alloc the TDREND_SRC_SPATIAL_t variable */
688 39651 : if ( ( error = TDREND_SRC_SPATIAL_Alloc( &Src_p->SrcSpatial_p ) ) != IVAS_ERR_OK )
689 : {
690 0 : return error;
691 : }
692 :
693 39651 : if ( ( error = TDREND_SRC_REND_Alloc( &Src_p->SrcRend_p ) ) != IVAS_ERR_OK )
694 : {
695 0 : return error;
696 : }
697 :
698 39651 : *Src_pp = Src_p;
699 :
700 39651 : return IVAS_ERR_OK;
701 : }
702 :
703 :
704 : /*-------------------------------------------------------------------*
705 : * TDREND_SRC_Dealloc()
706 : *
707 : * Deallocate a source.
708 : --------------------------------------------------------------------*/
709 :
710 39651 : void TDREND_SRC_Dealloc(
711 : TDREND_SRC_t *Src_p )
712 : {
713 39651 : if ( Src_p == NULL )
714 : {
715 0 : return;
716 : }
717 :
718 : /* Delloc the TDREND_SRC_Spatial_t variable */
719 39651 : TDREND_SRC_SPATIAL_Dealloc( Src_p->SrcSpatial_p );
720 :
721 : /* Delloc the TDREND_SRC_REND__t variable */
722 39651 : free( Src_p->SrcRend_p );
723 39651 : Src_p->SrcRend_p = NULL;
724 :
725 : /* Free the Src_p variable */
726 39651 : free( Src_p );
727 39651 : Src_p = NULL;
728 :
729 39651 : return;
730 : }
731 :
732 :
733 : /*-------------------------------------------------------------------*
734 : * TDREND_SRC_Init()
735 : *
736 : * Initializes a source.
737 : --------------------------------------------------------------------*/
738 :
739 39651 : void TDREND_SRC_Init(
740 : TDREND_SRC_t *Src_p, /* i/o: Source to initialize */
741 : const TDREND_PosType_t PosType /* i : Position type specifier */
742 : )
743 : {
744 : /* Init the TDREND_SRC_Spatial_t variable */
745 39651 : if ( Src_p->SrcSpatial_p != NULL )
746 : {
747 39651 : TDREND_SRC_SPATIAL_Init( Src_p->SrcSpatial_p, PosType );
748 : }
749 :
750 : /* Init the TDREND_SRC_REND_t variable */
751 39651 : TDREND_SRC_REND_Init( Src_p->SrcRend_p );
752 :
753 : /* Reset memory buffers */
754 39651 : Src_p->itd = 0;
755 39651 : Src_p->previtd = 0;
756 39651 : Src_p->filterlength = 1; /* Init to unit impulse of length 1 */
757 39651 : set_f( Src_p->mem_itd, 0.0f, ITD_MEM_LEN );
758 39651 : set_f( Src_p->mem_hrf_left, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 );
759 39651 : set_f( Src_p->mem_hrf_right, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 );
760 :
761 39651 : set_f( Src_p->hrf_left_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
762 39651 : set_f( Src_p->hrf_right_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
763 39651 : Src_p->hrf_left_prev[0] = 1;
764 39651 : Src_p->hrf_right_prev[0] = 1;
765 39651 : Src_p->azim_prev = 0.0f;
766 39651 : Src_p->elev_prev = 0.0f;
767 39651 : Src_p->Gain = 1;
768 39651 : Src_p->prevGain = 1.0f;
769 :
770 39651 : return;
771 : }
|