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