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