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_fx.h"
37 : #include "ivas_prot_rend_fx.h"
38 : #include "wmc_auto.h"
39 : #include "ivas_prot_fx.h"
40 :
41 :
42 : /*---------------------------------------------------------------------*
43 : * Local function prototypes
44 : *---------------------------------------------------------------------*/
45 :
46 : static void TDREND_SRC_REND_Init_fx( TDREND_SRC_REND_t *SrcRend_p );
47 : static void TDREND_SRC_SPATIAL_Init_fx( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_PosType_t PosType );
48 : static Word16 TDREND_SRC_SPATIAL_GetDirGain_fx( const TDREND_DirAtten_t *DirAtten_p, const Word32 *Front_p_fx, const Word32 *RelPos_p, const Word16 RelPos_p_e );
49 : static Word16 TDREND_SRC_SPATIAL_GetDistGain_fx( const TDREND_DistAtten_t *DistAtten_p, const Word32 Dist_fx, const Word16 Dist_e );
50 : static void TDREND_SRC_SPATIAL_SetDirAtten_fx( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_DirAtten_t *DirAtten_p );
51 : static void TDREND_SRC_SPATIAL_SetDistAtten( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_DistAtten_t *DistAtten_p );
52 : static ivas_error TDREND_SRC_REND_Alloc( TDREND_SRC_REND_t **SrcRend_pp );
53 : static void TDREND_SRC_SPATIAL_Dealloc( TDREND_SRC_SPATIAL_t *SrcSpatial_p );
54 :
55 : /*-------------------------------------------------------------------*
56 : * TDREND_MIX_SRC_SetPos()
57 : *
58 : * Set source position
59 : --------------------------------------------------------------------*/
60 :
61 411881 : ivas_error TDREND_MIX_SRC_SetPos_fx(
62 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
63 : const Word16 SrcInd, /* i : Source index */
64 : const Word32 *Vec_p /* i : Position vector Q25 */
65 : )
66 : {
67 : TDREND_SRC_SPATIAL_t *SrcSpatial_p;
68 :
69 411881 : IF( GT_16( SrcInd, hBinRendererTd->MaxSrcInd ) )
70 : {
71 0 : return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index!\n" ) );
72 : }
73 : ELSE
74 : {
75 411881 : SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
76 411881 : SrcSpatial_p->Pos_p_fx[0] = L_shr( SrcSpatial_p->Pos_p_fx[0], sub( SrcSpatial_p->q_Pos_p, Q25 ) ); // Q25
77 411881 : move32();
78 411881 : SrcSpatial_p->Pos_p_fx[1] = L_shr( SrcSpatial_p->Pos_p_fx[1], sub( SrcSpatial_p->q_Pos_p, Q25 ) ); // Q25
79 411881 : move32();
80 411881 : SrcSpatial_p->Pos_p_fx[2] = L_shr( SrcSpatial_p->Pos_p_fx[2], sub( SrcSpatial_p->q_Pos_p, Q25 ) ); // Q25
81 411881 : move32();
82 411881 : SrcSpatial_p->q_Pos_p = Q25;
83 411881 : move16();
84 411881 : test();
85 411881 : test();
86 411881 : IF( NE_32( SrcSpatial_p->Pos_p_fx[0], Vec_p[0] ) || NE_32( SrcSpatial_p->Pos_p_fx[1], Vec_p[1] ) || NE_32( SrcSpatial_p->Pos_p_fx[2], Vec_p[2] ) )
87 : {
88 227146 : Copy32( Vec_p, SrcSpatial_p->Pos_p_fx, 3 ); // Q25
89 227146 : SrcSpatial_p->Updated = TRUE;
90 227146 : move16();
91 : }
92 : }
93 :
94 411881 : return IVAS_ERR_OK;
95 : }
96 :
97 :
98 : /*-------------------------------------------------------------------*
99 : * TDREND_MIX_SRC_SetDir()
100 : *
101 : * Set source direction
102 : --------------------------------------------------------------------*/
103 411053 : ivas_error TDREND_MIX_SRC_SetDir_fx(
104 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
105 : const Word16 SrcInd, /* i : Source index */
106 : const Word32 *Vec_p, /* i : Direction vector Vec_p_q */
107 : const Word16 Vec_p_q /* i : Direction vector q */
108 : )
109 : {
110 : TDREND_SRC_SPATIAL_t *SrcSpatial_p;
111 : /* Value verification */
112 411053 : test();
113 411053 : test();
114 411053 : IF( EQ_32( Vec_p[0], 0 ) && EQ_32( Vec_p[1], 0 ) && EQ_32( Vec_p[2], 0 ) )
115 : {
116 0 : return ( IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Zero direction vector. Command is ignored!\n" ) );
117 : }
118 411053 : IF( GT_16( SrcInd, hBinRendererTd->MaxSrcInd ) )
119 : {
120 0 : return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index!\n" ) );
121 : }
122 : ELSE
123 : {
124 411053 : SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
125 411053 : TDREND_SPATIAL_VecNormalize_fx( Vec_p, Vec_p_q, SrcSpatial_p->Front_p_fx );
126 411053 : SrcSpatial_p->Updated = TRUE;
127 411053 : move16();
128 : }
129 411053 : return IVAS_ERR_OK;
130 : }
131 :
132 :
133 : /*-------------------------------------------------------------------*
134 : * TDREND_MIX_SRC_SetDirAtten()
135 : *
136 : * Set directional attenuation for the mixer.
137 : --------------------------------------------------------------------*/
138 1639 : ivas_error TDREND_MIX_SRC_SetDirAtten_fx(
139 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
140 : const Word16 SrcInd, /* i : Source index Q0 */
141 : const TDREND_DirAtten_t *DirAtten_p /* i : Directional attenuation specifier */
142 : )
143 : {
144 : TDREND_SRC_SPATIAL_t *SrcSpatial_p;
145 1639 : IF( GT_16( SrcInd, hBinRendererTd->MaxSrcInd ) )
146 : {
147 0 : return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index\n" ) );
148 : }
149 : ELSE
150 : {
151 1639 : SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
152 1639 : TDREND_SRC_SPATIAL_SetDirAtten_fx( SrcSpatial_p, DirAtten_p );
153 : }
154 :
155 1639 : return IVAS_ERR_OK;
156 : }
157 :
158 : /*-------------------------------------------------------------------*
159 : * TDREND_MIX_SRC_SetDistAtten()
160 : *
161 : * Set distance attenuation for the mixer.
162 : --------------------------------------------------------------------*/
163 :
164 1639 : ivas_error TDREND_MIX_SRC_SetDistAtten(
165 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
166 : const Word16 SrcInd, /* i : Source index */
167 : const TDREND_DistAtten_t *DistAtten_p /* i : Distance attenuation specifier */
168 : )
169 : {
170 : TDREND_SRC_SPATIAL_t *SrcSpatial_p;
171 1639 : IF( GT_16( SrcInd, hBinRendererTd->MaxSrcInd ) )
172 : {
173 0 : return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index\n" ) );
174 : }
175 : ELSE
176 : {
177 1639 : SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p;
178 1639 : TDREND_SRC_SPATIAL_SetDistAtten( SrcSpatial_p, DistAtten_p );
179 : }
180 :
181 1639 : return IVAS_ERR_OK;
182 : }
183 :
184 :
185 : /*-------------------------------------------------------------------*
186 : * TDREND_MIX_SRC_SetPlayState()
187 : *
188 : * Set play state for the source.
189 : --------------------------------------------------------------------*/
190 :
191 275 : ivas_error TDREND_MIX_SRC_SetPlayState(
192 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
193 : const Word16 SrcInd, /* i : Source index Q0 */
194 : const TDREND_PlayStatus_t PlayStatus /* i : Play state */
195 : )
196 : {
197 275 : IF( GT_16( SrcInd, hBinRendererTd->MaxSrcInd ) )
198 : {
199 0 : return ( IVAS_ERROR( IVAS_ERR_INVALID_INDEX, "Index exceeds max index\n" ) );
200 : }
201 : ELSE
202 : {
203 275 : hBinRendererTd->Sources[SrcInd]->SrcRend_p->PlayStatus = PlayStatus;
204 275 : move32();
205 : }
206 275 : return IVAS_ERR_OK;
207 : }
208 :
209 : /*-------------------------------------------------------------------*
210 : * TDREND_SRC_REND_Alloc()
211 : *
212 : * Renderer allocation
213 : --------------------------------------------------------------------*/
214 :
215 1639 : static ivas_error TDREND_SRC_REND_Alloc(
216 : TDREND_SRC_REND_t **SrcRend_pp /* i/o: Source object */
217 : )
218 : {
219 : TDREND_SRC_REND_t *SrcRend_p;
220 :
221 1639 : *SrcRend_pp = NULL;
222 :
223 : /* Allocate the TDREND_SRC_REND_t variable */
224 1639 : IF( ( SrcRend_p = (TDREND_SRC_REND_t *) malloc( sizeof( TDREND_SRC_REND_t ) ) ) == NULL )
225 : {
226 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "SrcRend_p allocation error\n" ) );
227 : }
228 :
229 1639 : *SrcRend_pp = SrcRend_p;
230 :
231 1639 : return IVAS_ERR_OK;
232 : }
233 :
234 :
235 : /*-------------------------------------------------------------------*
236 : * TDREND_SRC_REND_Init()
237 : *
238 : * Initialize rendering aspects of source.
239 : --------------------------------------------------------------------*/
240 1639 : static void TDREND_SRC_REND_Init_fx(
241 : TDREND_SRC_REND_t *SrcRend_p /* i/o: Source object */
242 : )
243 : {
244 : Word16 nC;
245 : /* Internal state */
246 1639 : SrcRend_p->InputAvailable = FALSE;
247 1639 : move16();
248 1639 : SrcRend_p->PlayStatus = TDREND_PLAYSTATUS_PLAYING;
249 1639 : move16();
250 : /* SrcGain */
251 3278 : FOR( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ )
252 : {
253 1639 : SrcRend_p->SrcGainMin_p_fx[nC] = 0; /* Q15 */
254 1639 : move16();
255 1639 : SrcRend_p->SrcGain_p_fx[nC] = ONE_IN_Q14; // Q14
256 1639 : move16();
257 : #ifdef OBJ_EDITING_API
258 1639 : SrcRend_p->SrcGainMax_p_fx[nC] = 32767; // TODO: make it 2, this is one in Q15, i thinki, need to change Q for that
259 : #else
260 : SrcRend_p->SrcGainMax_p_fx[nC] = 32767; /* Q15 */
261 : #endif
262 1639 : move16();
263 : }
264 1639 : SrcRend_p->SrcGainUpdated = FALSE;
265 1639 : move16();
266 : /* Init directional and distance gains */
267 3278 : FOR( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ )
268 : {
269 1639 : SrcRend_p->DirGain_p_fx[nC] = ONE_IN_Q14; // Q14
270 1639 : move16();
271 1639 : SrcRend_p->DistGain_p_fx[nC] = ONE_IN_Q14; // Q14
272 1639 : move16();
273 : }
274 1639 : return;
275 : }
276 :
277 : /*-------------------------------------------------------------------*
278 : * TDREND_SRC_REND_UpdateFiltersFromSpatialParams()
279 : *
280 : * Update the HR filter due to spatial change.
281 : --------------------------------------------------------------------*/
282 :
283 917847 : void TDREND_SRC_REND_UpdateFiltersFromSpatialParams_fx(
284 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
285 : TDREND_SRC_REND_t *SrcRend_p, /* i/o: Source object */
286 : TDREND_SRC_SPATIAL_t *SrcSpatial_p, /* i : Spatial aspects of source */
287 : Word32 *hrf_left_prev,
288 : /* i/o: Left filter */ // exp(hrf_left_prev_e)
289 : Word16 *hrf_left_prev_e,
290 : /* i/o: Left filter exponent */ // Q0
291 : Word32 *hrf_right_prev,
292 : /* i/o: Right filter */ // exp(hrf_right_prev_e)
293 : Word16 *hrf_right_prev_e,
294 : /* i/o: Right filter exponent */ // Q0
295 : Word32 *hrf_left_delta,
296 : /* o : Left filter interpolation delta */ // exp(hrf_left_delta_e)
297 : Word16 *hrf_left_delta_e,
298 : /* o : Left filter interpolation delta exponent */ // Q0
299 : Word32 *hrf_right_delta,
300 : /* o : Right filter interpolation delta */ // exp(hrf_right_delta_e)
301 : Word16 *hrf_right_delta_e,
302 : /* o : Right filter interpolation delta exponent */ // Q0
303 : Word16 *intp_count,
304 : /* o : Interpolation count */ // Q0
305 : Word16 *filterlength,
306 : /* o : Length of filters */ // Q0
307 : Word16 *itd,
308 : /* o : ITD value */ // Q0
309 : Word32 *Gain,
310 : /* o : Gain value */ // Q30
311 : TDREND_SRC_t *Src_p /* i/o: Source pointer */
312 : )
313 : {
314 : TDREND_MIX_Listener_t *Listener_p;
315 : TDREND_HRFILT_FiltSet_t *HrFiltSet_p;
316 : Word32 ListRelPos[3];
317 : Word32 ListRelDist;
318 : Word32 ListRelPosAbs[3]; /* Relative position, ignoring orientation of listener */
319 : Word32 Azim, Elev;
320 : Word32 hrf_left[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
321 : Word32 hrf_right[SFX_SPAT_BIN_MAX_FILTER_LENGTH];
322 : Word16 hrf_left_e, hrf_right_e;
323 : Word32 azim_delta;
324 : Word32 elev_delta;
325 : Word16 ListRelPos_e, ListRelDist_e;
326 :
327 : /* Evaluate the HR filters from the source and listener positions and orientations */
328 917847 : Listener_p = hBinRendererTd->Listener_p;
329 917847 : HrFiltSet_p = hBinRendererTd->HrFiltSet_p;
330 :
331 917847 : *filterlength = s_min( HrFiltSet_p->FiltLength, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); // Q0
332 917847 : move16();
333 917847 : IF( EQ_16( SrcSpatial_p->PosType, TDREND_POSTYPE_ABSOLUTE ) )
334 : {
335 :
336 : /* Absolute position */
337 917019 : TDREND_SPATIAL_VecMapToNewCoordSystem_fx( SrcSpatial_p->Pos_p_fx, Listener_p->Pos_fx, Listener_p->Front_fx, Listener_p->Up_fx, Listener_p->Right_fx, ListRelPos, ListRelPosAbs );
338 917019 : ListRelPos_e = 7; // output q of above function is Q25 + Q30 - 31. so exp will be 62 - Q25 - Q30.
339 917019 : move16();
340 917019 : ListRelDist = TDREND_SPATIAL_VecNorm_fx( ListRelPos, ListRelPos_e, &ListRelDist_e );
341 :
342 : /* 2. Evaluate the Elevation and Azimuth angles */
343 917019 : test();
344 917019 : test();
345 917019 : IF( ( ListRelPos[0] == 0 ) && ( ListRelPos[1] == 0 ) && ( ListRelPos[2] == 0 ) )
346 : {
347 1371 : Elev = 0;
348 1371 : move32();
349 1371 : Azim = 0;
350 1371 : move32();
351 : }
352 : ELSE
353 : {
354 915648 : Word32 tmp1 = Mpy_32_32( ListRelPos[0], ListRelPos[0] ); // exp(2*ListRelPos_e)
355 915648 : Word32 tmp2 = Mpy_32_32( ListRelPos[1], ListRelPos[1] ); // exp(2*ListRelPos_e)
356 915648 : Word32 tmp3 = L_add( tmp1, tmp2 ); // exp(2*ListRelPos_e)
357 915648 : Word16 tmp_e = shl( ListRelPos_e, 1 );
358 915648 : Word32 tmp4 = Sqrt32( tmp3, &tmp_e ); // exp(tmp_e)
359 915648 : Word16 tmp5 = BASOP_util_atan2( ListRelPos[2], tmp4, sub( ListRelPos_e, tmp_e ) ); // Q13
360 915648 : Word32 tmp6 = Mpy_32_16_1( _180_OVER_PI_Q25, tmp5 ); // Q25 + Q13 - Q15 = Q23
361 : /* 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 */
362 915648 : Word16 tmp7 = BASOP_util_atan2( ListRelPos[1], ListRelPos[0], 0 ); // Q13
363 915648 : Word32 tmp8 = L_negate( Mpy_32_16_1( _180_OVER_PI_Q25, tmp7 ) ); // Q25 + Q13 - Q15 = Q23
364 :
365 915648 : Elev = L_shr( tmp6, 1 ); // Q22
366 915648 : Azim = L_shr( tmp8, 1 ); // Q22
367 : }
368 :
369 917019 : GetFilterFromAngle_fx( HrFiltSet_p, Elev, Azim, *filterlength, hrf_left, &hrf_left_e, hrf_right, &hrf_right_e, itd );
370 :
371 : /* 6. Evaluate the directional and distance gains */
372 : /* Directional gain */
373 917019 : *SrcRend_p->DirGain_p_fx = ONE_IN_Q14; // Q14
374 917019 : move16();
375 917019 : IF( SrcSpatial_p->DirAttenEnabled )
376 : {
377 917019 : *SrcRend_p->DirGain_p_fx = TDREND_SRC_SPATIAL_GetDirGain_fx( &SrcSpatial_p->DirAtten, SrcSpatial_p->Front_p_fx, ListRelPosAbs, 6 );
378 : }
379 :
380 : /* Distance gain */
381 917019 : *SrcRend_p->DistGain_p_fx = ONE_IN_Q14; // Q14
382 917019 : move16();
383 917019 : IF( hBinRendererTd->UseCommonDistAttenModel )
384 : {
385 917019 : IF( hBinRendererTd->DistAttenEnabled )
386 : {
387 917019 : SrcSpatial_p->DistAtten.DistAttenModel = hBinRendererTd->DistAttenModel;
388 917019 : move32();
389 917019 : *SrcRend_p->DistGain_p_fx = TDREND_SRC_SPATIAL_GetDistGain_fx( &SrcSpatial_p->DistAtten, ListRelDist, ListRelDist_e ); // Q14
390 917019 : move32();
391 : }
392 : }
393 0 : ELSE IF( SrcSpatial_p->DistAttenEnabled )
394 : {
395 :
396 0 : *SrcRend_p->DistGain_p_fx = TDREND_SRC_SPATIAL_GetDistGain_fx( &SrcSpatial_p->DistAtten, ListRelDist, ListRelDist_e ); // Q14
397 0 : move32();
398 : }
399 :
400 :
401 : /* Update total gains */
402 917019 : *Gain = L_shl( Mpy_32_32( L_shl( L_mult( *SrcRend_p->SrcGain_p_fx, *SrcRend_p->DirGain_p_fx ), 1 ), L_shl( L_mult( *SrcRend_p->DistGain_p_fx, hBinRendererTd->Gain_fx ), 1 ) ), 1 ); // Q30
403 917019 : move32();
404 : /* Delta for interpolation, in case the angular step exceeds MAX_ANGULAR_STEP */
405 917019 : Word32 ele_tmp = Src_p->elev_prev_fx; // Q22
406 917019 : move32();
407 917019 : IF( GT_32( ele_tmp, DEG_180_IN_Q22 ) )
408 : {
409 0 : ele_tmp = L_sub( ele_tmp, DEG_360_IN_Q22 ); // Q22
410 : }
411 917019 : ELSE IF( LT_32( ele_tmp, -DEG_180_IN_Q22 ) )
412 : {
413 0 : ele_tmp = L_add( ele_tmp, DEG_360_IN_Q22 ); // Q22
414 : }
415 917019 : elev_delta = L_sub( Elev, ele_tmp ); // Q22
416 :
417 917019 : Word32 azi_tmp = Src_p->azim_prev_fx; // Q22
418 917019 : IF( GT_32( azi_tmp, DEG_180_IN_Q22 ) )
419 : {
420 3 : azi_tmp = L_sub( azi_tmp, DEG_360_IN_Q22 ); // Q22
421 : }
422 917016 : ELSE IF( LT_32( azi_tmp, -DEG_180_IN_Q22 ) )
423 : {
424 312 : azi_tmp = L_add( azi_tmp, DEG_360_IN_Q22 ); // Q22
425 : }
426 917019 : azim_delta = L_sub( Azim, azi_tmp ); // Q22
427 :
428 917019 : Src_p->elev_prev_fx = Elev; // Q22
429 917019 : move32();
430 917019 : Src_p->azim_prev_fx = Azim; // Q22
431 917019 : move32();
432 :
433 : /* map to -180:180 range */
434 917019 : IF( GT_32( azim_delta, DEG_180_IN_Q22 ) )
435 : {
436 21369 : azim_delta = L_sub( azim_delta, DEG_360_IN_Q22 ); // Q22
437 : }
438 895650 : ELSE IF( LT_32( azim_delta, -DEG_180_IN_Q22 ) )
439 : {
440 2717 : azim_delta = L_add( azim_delta, DEG_360_IN_Q22 ); // Q22
441 : }
442 917019 : Word16 tmp1 = extract_l( Mpy_32_32( L_abs( azim_delta ), 100 << Q9 ) ); // Q22 + Q9 - Q31 = Q0
443 917019 : Word16 tmp2 = extract_l( Mpy_32_32( L_abs( elev_delta ), 100 << Q9 ) ); // Q22 + Q9 - Q31 = Q0
444 917019 : *intp_count = s_min( MAX_INTERPOLATION_STEPS, s_max( tmp1, tmp2 ) ); // Q0
445 917019 : move16();
446 : }
447 : ELSE /* TDREND_POSTYPE_NON_DIEGETIC */
448 : {
449 828 : *itd = 0; // Q0
450 828 : move16();
451 828 : *Gain = ONE_IN_Q30; // Q30
452 828 : move32();
453 828 : set32_fx( hrf_left, 0, *filterlength );
454 828 : set32_fx( hrf_right, 0, *filterlength );
455 828 : hrf_left[0] = L_shr( L_add( SrcSpatial_p->Pos_p_fx[1], ONE_IN_Q25 ), 1 ); // Q25
456 828 : move32();
457 828 : hrf_right[0] = L_sub( ONE_IN_Q25, hrf_left[0] ); // Q25
458 828 : move32();
459 828 : hrf_left_e = 6;
460 828 : move16();
461 828 : hrf_right_e = 6;
462 828 : move16();
463 828 : *intp_count = MAX_INTERPOLATION_STEPS; // Q22
464 828 : move16();
465 828 : Src_p->elev_prev_fx = 0; // Q22
466 828 : move16();
467 828 : Src_p->azim_prev_fx = DEG_360_IN_Q22; /* Dummy angle -- sets max interpolation if switching to TDREND_POSTYPE_ABSOLUTE */ // Q22
468 828 : move16();
469 : }
470 :
471 917847 : test();
472 :
473 917847 : IF( ( *intp_count > 0 ) )
474 : {
475 : /* Set deltas for interpolation */
476 : Word16 tmp_e;
477 791494 : tmp_e = s_max( *hrf_left_prev_e, hrf_left_e );
478 99952283 : FOR( Word16 i = 0; i < *filterlength; i++ )
479 : {
480 99160789 : hrf_left[i] = L_shr( hrf_left[i], sub( tmp_e, hrf_left_e ) ); // exp(tmp_e)
481 99160789 : move32();
482 99160789 : hrf_left_prev[i] = L_shr( hrf_left_prev[i], sub( tmp_e, *hrf_left_prev_e ) ); // exp(tmp_e)
483 99160789 : move32();
484 : }
485 791494 : *hrf_left_prev_e = tmp_e;
486 791494 : move16();
487 791494 : hrf_left_e = tmp_e;
488 791494 : move16();
489 791494 : v_sub_32( hrf_left, hrf_left_prev, hrf_left_delta, *filterlength ); // exp(tmp_e)
490 791494 : *hrf_left_delta_e = tmp_e;
491 791494 : move16();
492 :
493 791494 : Word32 fac = L_deposit_h( div_s( 1, *intp_count ) ); // Q15
494 791494 : v_multc_fixed( hrf_left_delta, fac, hrf_left_delta, *filterlength ); // exp(hrf_left_delta_e)
495 :
496 791494 : tmp_e = s_max( *hrf_right_prev_e, hrf_right_e );
497 99952283 : FOR( Word16 i = 0; i < *filterlength; i++ )
498 : {
499 99160789 : hrf_right[i] = L_shr( hrf_right[i], sub( tmp_e, hrf_right_e ) ); // exp(tmp_e)
500 99160789 : move32();
501 99160789 : hrf_right_prev[i] = L_shr( hrf_right_prev[i], sub( tmp_e, *hrf_right_prev_e ) ); // exp(tmp_e)
502 99160789 : move32();
503 : }
504 791494 : *hrf_right_prev_e = tmp_e;
505 791494 : move16();
506 791494 : hrf_right_e = tmp_e;
507 791494 : move16();
508 791494 : v_sub_32( hrf_right, hrf_right_prev, hrf_right_delta, *filterlength ); // exp(hrf_right_delta_e)
509 791494 : *hrf_right_delta_e = tmp_e;
510 791494 : move16();
511 :
512 791494 : v_multc_fixed( hrf_right_delta, fac, hrf_right_delta, *filterlength ); // exp(hrf_right_delta_e)
513 : }
514 : ELSE
515 : {
516 : /* No interpolation, just set the new filters and reset deltas */
517 126353 : Copy32( hrf_left, hrf_left_prev, *filterlength ); // exp(hrf_left_prev_e)
518 126353 : *hrf_left_prev_e = hrf_left_e;
519 126353 : move16();
520 126353 : Copy32( hrf_right, hrf_right_prev, *filterlength ); // exp(hrf_right_prev_e)
521 126353 : *hrf_right_prev_e = hrf_right_e;
522 126353 : move16();
523 126353 : set32_fx( hrf_left_delta, 0, *filterlength );
524 126353 : set32_fx( hrf_right_delta, 0, *filterlength );
525 126353 : *hrf_left_delta_e = 0;
526 126353 : move16();
527 126353 : *hrf_right_delta_e = 0;
528 126353 : move16();
529 : }
530 :
531 917847 : return;
532 : }
533 :
534 : /*-------------------------------------------------------------------*
535 : * TDREND_SRC_SPATIAL_Alloc()
536 : *
537 : * Allocatie spatial properties of a source.
538 : --------------------------------------------------------------------*/
539 :
540 1639 : static ivas_error TDREND_SRC_SPATIAL_Alloc(
541 : TDREND_SRC_SPATIAL_t **SrcSpatial_pp /* i/o: Source spatial parameters */
542 : )
543 : {
544 : TDREND_SRC_SPATIAL_t *SrcSpatial_p;
545 :
546 1639 : *SrcSpatial_pp = NULL;
547 :
548 : /* Allocate the TDREND_SRC_t variable */
549 1639 : IF( ( SrcSpatial_p = (TDREND_SRC_SPATIAL_t *) malloc( sizeof( TDREND_SRC_SPATIAL_t ) ) ) == NULL )
550 : {
551 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "TDREND_SRC_SPATIAL_t allocation error\n" ) );
552 : }
553 :
554 1639 : *SrcSpatial_pp = SrcSpatial_p;
555 :
556 1639 : return IVAS_ERR_OK;
557 : }
558 :
559 :
560 : /*-------------------------------------------------------------------*
561 : * TDREND_SRC_SPATIAL_Dealloc()
562 : *
563 : * Deallocate spatial properties of a source.
564 : --------------------------------------------------------------------*/
565 :
566 1639 : static void TDREND_SRC_SPATIAL_Dealloc(
567 : TDREND_SRC_SPATIAL_t *SrcSpatial_p /* i/o: Source spatial parameters */
568 : )
569 : {
570 1639 : IF( SrcSpatial_p == NULL )
571 : {
572 0 : return;
573 : }
574 : /* Free the SrcSpatial_p variable */
575 1639 : free( SrcSpatial_p );
576 1639 : SrcSpatial_p = NULL;
577 1639 : return;
578 : }
579 :
580 : /*-------------------------------------------------------------------*
581 : * TDREND_SRC_SPATIAL_Init()
582 : *
583 : * Initialize spatial properties of a source.
584 : --------------------------------------------------------------------*/
585 1639 : static void TDREND_SRC_SPATIAL_Init_fx(
586 : TDREND_SRC_SPATIAL_t *SrcSpatial_p, /* i/o: Source spatial parameters */
587 : const TDREND_PosType_t PosType /* i : Relative/absolute position type */
588 : )
589 : {
590 : Word16 nC; // Q0
591 :
592 : /* Initialize variables */
593 1639 : SrcSpatial_p->Updated = FALSE;
594 :
595 1639 : move16();
596 : /* Source position, velocity and direction vectors */
597 1639 : SrcSpatial_p->PosType = PosType;
598 1639 : move32();
599 3278 : FOR( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ )
600 : {
601 : /* Source position */
602 1639 : TDREND_SPATIAL_VecInit_fx( SrcSpatial_p->Pos_p_fx + nC * 3, 0, 0, 0 ); /*Assuming Q31*/
603 :
604 : /* Source direction */
605 1639 : TDREND_SPATIAL_VecInit_fx( SrcSpatial_p->Front_p_fx + nC * 3, 0, 0, ONE_IN_Q30 ); /*Assuming Q30*/
606 : }
607 :
608 1639 : SrcSpatial_p->q_Pos_p = Q31;
609 1639 : move16();
610 :
611 : /* Source directional attenuation */
612 1639 : SrcSpatial_p->DirAttenEnabled = FALSE; // Q0
613 1639 : move16();
614 1639 : SrcSpatial_p->DirAtten.ConeInnerAngle_fx = DEG_360_IN_Q22; // Q22
615 1639 : move32();
616 1639 : SrcSpatial_p->DirAtten.ConeOuterAngle_fx = DEG_360_IN_Q22; // Q22
617 1639 : move32();
618 1639 : SrcSpatial_p->DirAtten.ConeOuterGain_fx = ONE_IN_Q30; // Q30
619 1639 : move16();
620 :
621 : /* Source distance attenuation */
622 1639 : SrcSpatial_p->DistAttenEnabled = FALSE; // Q0
623 1639 : move16();
624 1639 : SrcSpatial_p->DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED; // Q0
625 1639 : move16();
626 1639 : SrcSpatial_p->DistAtten.RefDist_fx = ONE_IN_Q30; // Q30
627 1639 : move32();
628 1639 : SrcSpatial_p->DistAtten.MaxDist_fx = 2113929216; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ /*15.75 in Q27*/
629 1639 : move32();
630 1639 : SrcSpatial_p->DistAtten.RollOffFactor_fx = ONE_IN_Q30; // Q30
631 1639 : move16();
632 :
633 1639 : return;
634 : }
635 :
636 : /*-------------------------------------------------------------------*
637 : * TDREND_SRC_SPATIAL_SetDirAtten()
638 : *
639 : * Sets the directional attenuation mode.
640 : --------------------------------------------------------------------*/
641 :
642 1639 : static void TDREND_SRC_SPATIAL_SetDirAtten_fx(
643 : TDREND_SRC_SPATIAL_t *SrcSpatial_p, /* i/o: Source spatial parameters */
644 : const TDREND_DirAtten_t *DirAtten_p /* i : Directionality specification */
645 : )
646 : {
647 : /* Set directional attenuation */
648 1639 : SrcSpatial_p->DirAttenEnabled = TRUE; // Q0
649 1639 : SrcSpatial_p->DirAtten.ConeInnerAngle_fx = DirAtten_p->ConeInnerAngle_fx; // Q22
650 1639 : SrcSpatial_p->DirAtten.ConeOuterAngle_fx = DirAtten_p->ConeOuterAngle_fx; // Q22
651 1639 : SrcSpatial_p->DirAtten.ConeOuterGain_fx = DirAtten_p->ConeOuterGain_fx; // Q30
652 1639 : move16();
653 1639 : move16();
654 1639 : move16();
655 1639 : move16();
656 1639 : return;
657 : }
658 :
659 : /*-------------------------------------------------------------------*
660 : * TDREND_SRC_SPATIAL_SetDistAtten()
661 : *
662 : * Sets the distance attenuation.
663 : --------------------------------------------------------------------*/
664 :
665 1639 : static void TDREND_SRC_SPATIAL_SetDistAtten(
666 : TDREND_SRC_SPATIAL_t *SrcSpatial_p,
667 : const TDREND_DistAtten_t *DistAtten_p )
668 : {
669 : /* Set distance attenuation */
670 1639 : SrcSpatial_p->DistAttenEnabled = TRUE;
671 1639 : SrcSpatial_p->DistAtten.DistAttenModel = DistAtten_p->DistAttenModel;
672 1639 : SrcSpatial_p->DistAtten.MaxDist_fx = DistAtten_p->MaxDist_fx;
673 1639 : SrcSpatial_p->DistAtten.RefDist_fx = DistAtten_p->RefDist_fx;
674 1639 : SrcSpatial_p->DistAtten.RollOffFactor_fx = DistAtten_p->RollOffFactor_fx;
675 1639 : move16();
676 1639 : move32();
677 1639 : move32();
678 1639 : move32();
679 :
680 1639 : return;
681 : }
682 :
683 : /*-------------------------------------------------------------------*
684 : * TDREND_SRC_SPATIAL_GetDirGain()
685 : *
686 : * Returns the gain due to object orientation.
687 : --------------------------------------------------------------------*/
688 :
689 : /*! r: Gain value */
690 917019 : static Word16 TDREND_SRC_SPATIAL_GetDirGain_fx( /* o : Directional Gain Output Q14 */
691 : const TDREND_DirAtten_t *DirAtten_p, /* i : Directional attenuation specification */
692 : const Word32 *Front_p_fx, /* i : Front-pointing vector Q30 */
693 : const Word32 *RelPos_p_fx, /* i : Relative position */
694 : const Word16 RelPos_p_e /* i : Relative position exp RelPos_p_e */
695 : )
696 : {
697 : Word16 DirGain_fx; // Q14
698 : Word32 Vec_fx[3];
699 : Word32 ProjCoef_fx;
700 : Word16 ProjCoef_e;
701 : Word32 NormRelPos_fx;
702 : Word16 NormRelPos_e;
703 : Word32 AngleDeg_fx; // Q22
704 :
705 917019 : DirGain_fx = ONE_IN_Q14;
706 917019 : move16();
707 :
708 : /* Note that the front vector is unit norm, thus */
709 : /* Angle = acos ( Proj coeff from projecting -RelPos onto Front / norm(RelPos) ); */
710 3668076 : FOR( Word16 i = 0; i < 3; i++ )
711 : {
712 2751057 : Vec_fx[i] = L_negate( RelPos_p_fx[i] ); // exp(RelPos_p_e)
713 2751057 : move32();
714 : }
715 917019 : ProjCoef_fx = dotp_fixed( Vec_fx, Front_p_fx, 3 ); // exp: RelPos_p_e + 1
716 917019 : ProjCoef_e = add( RelPos_p_e, 1 );
717 917019 : NormRelPos_fx = TDREND_SPATIAL_VecNorm_fx( RelPos_p_fx, RelPos_p_e, &NormRelPos_e ); // exp(NormRelPos_e)
718 :
719 917019 : IF( NormRelPos_fx != 0 )
720 : {
721 : // AngleDeg = _180_OVER_PI * acosf( ProjCoef / NormRelPos );
722 :
723 : Word16 tmp_e1, tmp_e2, tmp_e3, tmp_e4, acosfx;
724 : Word32 tmp1, tmp2, tmp3, tmp4;
725 :
726 : // acos(x/y) = atan( sqrt(1-(x/y)^2) / (x/y) )
727 915648 : tmp1 = L_deposit_h( BASOP_Util_Divide3232_Scale( ProjCoef_fx, NormRelPos_fx, &tmp_e1 ) ); // x/y /* exp(tmp_e1) */
728 915648 : tmp_e1 = add( tmp_e1, sub( ProjCoef_e, NormRelPos_e ) );
729 915648 : tmp2 = Mpy_32_32( tmp1, tmp1 ); // (x/y)^2 /* exp(tmp_e2 */
730 915648 : tmp_e2 = shl( tmp_e1, 1 );
731 915648 : tmp3 = BASOP_Util_Add_Mant32Exp( ONE_IN_Q30, 1, L_negate( tmp2 ), tmp_e2, &tmp_e3 ); // 1 - (x/y)^2 /* exp(tmp_e3) */
732 915648 : tmp_e4 = tmp_e3;
733 915648 : move16();
734 915648 : tmp3 = L_abs( tmp3 ); // for safety: sometimes it can go negative due to slight precision difference between numerator and denominator.
735 915648 : tmp4 = Sqrt32( tmp3, &tmp_e4 ); // sqrt(1 - (x/y)^2) /* exp(tmp_e4) */
736 915648 : acosfx = BASOP_util_atan2( tmp4, tmp1, sub( tmp_e4, tmp_e1 ) ); // 2Q13
737 915648 : AngleDeg_fx = L_shr( Mpy_32_16_1( _180_OVER_PI_Q25, acosfx ), 1 ); // Q22
738 : }
739 : ELSE
740 : {
741 1371 : AngleDeg_fx = 0;
742 1371 : move32();
743 : }
744 :
745 917019 : IF( LE_32( AngleDeg_fx, L_shr( DirAtten_p->ConeInnerAngle_fx, 1 ) ) )
746 : {
747 876284 : DirGain_fx = ONE_IN_Q14; // Q14
748 876284 : move16();
749 : }
750 40735 : ELSE IF( LE_32( AngleDeg_fx, L_shr( DirAtten_p->ConeOuterAngle_fx, 1 ) ) )
751 : {
752 : // DirGain = 1.0f - ( 2.0f * AngleDeg - DirAtten_p->ConeInnerAngle ) / ( DirAtten_p->ConeOuterAngle - DirAtten_p->ConeInnerAngle ) * ( 1.0f - DirAtten_p->ConeOuterGain );
753 : Word32 tmp1, tmp2, tmp3;
754 32873 : tmp1 = L_sub( ONE_IN_Q30, DirAtten_p->ConeOuterGain_fx ); // Q30
755 32873 : tmp2 = L_sub( DirAtten_p->ConeOuterAngle_fx, DirAtten_p->ConeInnerAngle_fx ); // Q22
756 32873 : tmp3 = L_sub( L_shl( AngleDeg_fx, 1 ) /* 2.0f * AngleDeg */, DirAtten_p->ConeInnerAngle_fx ); // Q22
757 32873 : DirGain_fx = sub( ONE_IN_Q14, div_l( Mpy_32_32( tmp1, tmp3 ), extract_h( tmp2 ) ) ); // Q14
758 : }
759 : ELSE
760 : {
761 7862 : DirGain_fx = extract_h( DirAtten_p->ConeOuterGain_fx ); // Q14
762 : }
763 :
764 917019 : return DirGain_fx;
765 : }
766 :
767 :
768 : /*-------------------------------------------------------------------*
769 : * TDREND_SRC_SPATIAL_GetDistGain()
770 : *
771 : * Returns the gain due to distance.
772 : --------------------------------------------------------------------*/
773 :
774 : /*! r: Gain value */
775 917019 : static Word16 TDREND_SRC_SPATIAL_GetDistGain_fx( /* o : Distance gain Q14 */
776 : const TDREND_DistAtten_t *DistAtten_p, /* i : Distance attenuation parameters */
777 : const Word32 Dist_fx, /* i : Distance value Dist_e */
778 : const Word16 Dist_e /* i : Distance value exp */
779 : )
780 : {
781 : Word16 DistGain_fx; // Q14
782 : Word32 Dist2_fx;
783 : Word16 Dist2_e;
784 : Word16 tmp_e;
785 : Word32 tmp32;
786 : Word16 flag;
787 : Word16 Dist_s;
788 : Word16 tmp16;
789 :
790 917019 : DistGain_fx = ONE_IN_Q14; // Q14
791 917019 : move16();
792 917019 : Dist2_fx = Dist_fx;
793 917019 : move32();
794 917019 : Dist2_e = Dist_e;
795 917019 : move16();
796 917019 : tmp32 = 0;
797 917019 : move32();
798 917019 : tmp_e = 0;
799 917019 : move16();
800 :
801 917019 : SWITCH( DistAtten_p->DistAttenModel )
802 : {
803 0 : case TDREND_DIST_ATTEN_MODEL_INV_DIST:
804 : /* DistGain = powf( DistAtten_p->RefDist / Dist2, DistAtten_p->RollOffFactor ); */
805 0 : tmp16 = BASOP_Util_Divide3232_Scale( DistAtten_p->RefDist_fx, Dist2_fx, &Dist_s ); /* tmp16 is Q(15 - Dist_s + Dist2_e - 1) */
806 0 : tmp32 = L_deposit_h( tmp16 ); /* tmp32 is Q(31 - Dist_s + Dist2_e - 1) */
807 : /* tmp32 exponent: 31 - (31 - Dist_s + Dist2_e - 1) = Dist_s - Dist2_e + 1, RollOffFactor_fx exponent: 31 - 30 = 1 */
808 0 : tmp32 = BASOP_Util_fPow( tmp32, add( sub( Dist_s, Dist2_e ), 1 ), DistAtten_p->RollOffFactor_fx, 1, &tmp_e ); /* Q(31 - tmp_e) */
809 0 : BREAK;
810 :
811 917019 : case TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED:
812 917019 : flag = BASOP_Util_Cmp_Mant32Exp( Dist2_fx, Dist2_e, DistAtten_p->RefDist_fx, 1 );
813 917019 : IF( flag < 0 )
814 : {
815 509051 : Dist2_fx = DistAtten_p->RefDist_fx; // Q30
816 509051 : move32();
817 509051 : Dist2_e = 1;
818 509051 : move16();
819 : }
820 917019 : flag = BASOP_Util_Cmp_Mant32Exp( Dist2_fx, Dist2_e, DistAtten_p->MaxDist_fx, 4 );
821 917019 : IF( flag > 0 )
822 : {
823 10473 : Dist2_fx = DistAtten_p->MaxDist_fx; // Q27
824 10473 : move32();
825 10473 : Dist2_e = 4;
826 10473 : move16();
827 : }
828 : /* DistGain = powf( DistAtten_p->RefDist / Dist2, DistAtten_p->RollOffFactor ); */
829 917019 : tmp16 = BASOP_Util_Divide3232_Scale( DistAtten_p->RefDist_fx, Dist2_fx, &Dist_s ); /* tmp16 is Q(15 - Dist_s + Dist2_e - 1) */
830 917019 : tmp32 = L_deposit_h( tmp16 ); /* tmp32 is Q(31 - Dist_s + Dist2_e - 1) */
831 : /* tmp32 exponent: 31 - (31 - Dist_s + Dist2_e - 1) = Dist_s - Dist2_e + 1, RollOffFactor_fx exponent: 31 - 30 = 1 */
832 917019 : tmp32 = BASOP_Util_fPow( tmp32, add( sub( Dist_s, Dist2_e ), 1 ), DistAtten_p->RollOffFactor_fx, 1, &tmp_e ); /* Q(31 - tmp_e) */
833 :
834 917019 : BREAK;
835 : }
836 :
837 917019 : tmp16 = extract_h( L_shr( tmp32, sub( 1, tmp_e ) ) ); // Reducing it to Q14: Go to Q30 and extract_h. right shift by 31-tmp_e-30 = 1-tmp_e
838 917019 : IF( GT_16( tmp16, ONE_IN_Q14 ) )
839 : {
840 512319 : tmp16 = ONE_IN_Q14;
841 : }
842 :
843 917019 : DistGain_fx = tmp16;
844 :
845 917019 : return DistGain_fx;
846 : }
847 :
848 : /*-------------------------------------------------------------------*
849 : * TDREND_SRC_Alloc()
850 : *
851 : * Allocate a source.
852 : --------------------------------------------------------------------*/
853 1639 : ivas_error TDREND_SRC_Alloc(
854 : TDREND_SRC_t **Src_pp /* i/o: Source */
855 : )
856 : {
857 : ivas_error error;
858 : TDREND_SRC_t *Src_p;
859 :
860 1639 : *Src_pp = NULL;
861 :
862 : /* Allocate the TDREND_SRC_t variable */
863 1639 : IF( ( Src_p = (TDREND_SRC_t *) malloc( sizeof( TDREND_SRC_t ) ) ) == NULL )
864 : {
865 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, " TDREND_SRC_Alloc: Allocation error\n" ) );
866 : }
867 :
868 1639 : Src_p->SrcSpatial_p = NULL;
869 : /* If source type is dynamic alloc the TDREND_SRC_SPATIAL_t variable */
870 1639 : IF( NE_32( ( error = TDREND_SRC_SPATIAL_Alloc( &Src_p->SrcSpatial_p ) ), IVAS_ERR_OK ) )
871 : {
872 0 : return error;
873 : }
874 :
875 1639 : IF( NE_32( ( error = TDREND_SRC_REND_Alloc( &Src_p->SrcRend_p ) ), IVAS_ERR_OK ) )
876 : {
877 0 : return error;
878 : }
879 :
880 1639 : *Src_pp = Src_p;
881 :
882 1639 : return IVAS_ERR_OK;
883 : }
884 :
885 : /*-------------------------------------------------------------------*
886 : * TDREND_SRC_Dealloc()
887 : *
888 : * Deallocate a source.
889 : --------------------------------------------------------------------*/
890 :
891 1639 : void TDREND_SRC_Dealloc(
892 : TDREND_SRC_t *Src_p )
893 : {
894 1639 : IF( Src_p == NULL )
895 : {
896 0 : return;
897 : }
898 : /* Delloc the TDREND_SRC_Spatial_t variable */
899 1639 : TDREND_SRC_SPATIAL_Dealloc( Src_p->SrcSpatial_p );
900 : /* Delloc the TDREND_SRC_REND__t variable */
901 1639 : free( Src_p->SrcRend_p );
902 1639 : Src_p->SrcRend_p = NULL;
903 : /* Free the Src_p variable */
904 1639 : free( Src_p );
905 1639 : Src_p = NULL;
906 1639 : return;
907 : }
908 : /*-------------------------------------------------------------------*
909 : * TDREND_SRC_Init()
910 : *
911 : * Initializes a source.
912 : --------------------------------------------------------------------*/
913 1639 : void TDREND_SRC_Init_fx(
914 : TDREND_SRC_t *Src_p, /* i/o: Source to initialize */
915 : const TDREND_PosType_t PosType /* i : Position type specifier */
916 : )
917 : {
918 : /* Init the TDREND_SRC_Spatial_t variable */
919 1639 : IF( Src_p->SrcSpatial_p != NULL )
920 : {
921 1639 : TDREND_SRC_SPATIAL_Init_fx( Src_p->SrcSpatial_p, PosType );
922 : }
923 :
924 : /* Init the TDREND_SRC_REND_t variable */
925 1639 : TDREND_SRC_REND_Init_fx( Src_p->SrcRend_p );
926 :
927 : /* Reset memory buffers */
928 1639 : Src_p->itd = 0; // Q0
929 1639 : move16();
930 1639 : Src_p->previtd = 0; // Q0
931 1639 : move16();
932 1639 : Src_p->filterlength = 1; /* Init to unit impulse of length 1 */ // Q0
933 1639 : move16();
934 1639 : set32_fx( Src_p->mem_itd_fx, 0, ITD_MEM_LEN );
935 1639 : set32_fx( Src_p->mem_hrf_left_fx, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 );
936 1639 : set32_fx( Src_p->mem_hrf_right_fx, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 );
937 :
938 1639 : set32_fx( Src_p->hrf_left_prev_fx, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
939 1639 : set32_fx( Src_p->hrf_right_prev_fx, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH );
940 1639 : Src_p->hrf_left_prev_fx[0] = ONE_IN_Q30; // Q30
941 1639 : move32();
942 1639 : Src_p->hrf_left_prev_e = 1;
943 1639 : move16();
944 1639 : Src_p->hrf_right_prev_fx[0] = ONE_IN_Q30; // Q30
945 1639 : move32();
946 1639 : Src_p->hrf_right_prev_e = 1;
947 1639 : move16();
948 1639 : Src_p->azim_prev_fx = 0; // Q22
949 1639 : move32();
950 1639 : Src_p->elev_prev_fx = 0; // Q22
951 1639 : move32();
952 1639 : Src_p->Gain_fx = ONE_IN_Q30; // Q30
953 1639 : move32();
954 1639 : Src_p->prevGain_fx = ONE_IN_Q30; // Q30
955 1639 : move32();
956 1639 : return;
957 : }
|