Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : #include "ivas_cnst.h"
34 : #include <assert.h>
35 : #include <stdint.h>
36 : #include "options.h"
37 : #include <math.h>
38 : #include "cnst.h"
39 : #include "prot.h"
40 : #include "ivas_prot.h"
41 : #include "ivas_prot_rend.h"
42 : #ifdef DEBUGGING
43 : #include "debug.h"
44 : #endif
45 : #include "wmc_auto.h"
46 :
47 :
48 : /*-----------------------------------------------------------------------*
49 : * Local funtion declarations
50 : *-----------------------------------------------------------------------*/
51 :
52 :
53 : static ivas_error combine_external_and_head_orientations( IVAS_QUATERNION *headRotQuaternions, IVAS_VECTOR3 *listenerPos, ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis, EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData );
54 :
55 : static void external_target_interpolation( EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, const int16_t i );
56 :
57 : static bool are_orientations_same( const IVAS_QUATERNION *orientation1, const IVAS_QUATERNION *orientation2 );
58 :
59 :
60 : /*-----------------------------------------------------------------------*
61 : * ivas_headTrack_open()
62 : *
63 : * Allocate and initialize Head-Tracking handle
64 : *-----------------------------------------------------------------------*/
65 :
66 1115 : ivas_error ivas_headTrack_open(
67 : HEAD_TRACK_DATA_HANDLE *hHeadTrackData /* o : head track handle */
68 : )
69 : {
70 : int16_t i;
71 : ivas_error error;
72 :
73 : /* Allocate Head-Tracking handle */
74 1115 : if ( ( *hHeadTrackData = (HEAD_TRACK_DATA_HANDLE) malloc( sizeof( HEAD_TRACK_DATA ) ) ) == NULL )
75 : {
76 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for head-tracking memory\n" ) );
77 : }
78 :
79 : /* Initialization */
80 1115 : ( *hHeadTrackData )->lrSwitchInterpVal = 0.0f;
81 1115 : ( *hHeadTrackData )->lrSwitchedCurrent = 0;
82 1115 : ( *hHeadTrackData )->lrSwitchedNext = 0;
83 1115 : if ( ( ( *hHeadTrackData )->OrientationTracker = (ivas_orient_trk_state_t *) malloc( sizeof( ivas_orient_trk_state_t ) ) ) == NULL )
84 : {
85 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Orientation tracking" );
86 : }
87 :
88 1115 : if ( ( error = ivas_orient_trk_Init( ( *hHeadTrackData )->OrientationTracker ) ) != IVAS_ERR_OK )
89 : {
90 0 : return error;
91 : }
92 :
93 : /* Initialise Rmat_prev to I, Rmat will be computed later */
94 4460 : for ( i = 0; i < 3; i++ )
95 : {
96 3345 : set_zero( ( *hHeadTrackData )->Rmat_prev[i], 3 );
97 3345 : ( *hHeadTrackData )->Rmat_prev[i][i] = 1.0f;
98 : }
99 :
100 1115 : ( *hHeadTrackData )->sr_pose_pred_axis = DEFAULT_AXIS;
101 :
102 1115 : set_zero( ( *hHeadTrackData )->chEneIIR[0], MASA_FREQUENCY_BANDS );
103 1115 : set_zero( ( *hHeadTrackData )->chEneIIR[1], MASA_FREQUENCY_BANDS );
104 1115 : set_zero( ( *hHeadTrackData )->procChEneIIR[0], MASA_FREQUENCY_BANDS );
105 1115 : set_zero( ( *hHeadTrackData )->procChEneIIR[1], MASA_FREQUENCY_BANDS );
106 :
107 1115 : return IVAS_ERR_OK;
108 : }
109 :
110 :
111 : /*-----------------------------------------------------------------------*
112 : * ivas_headTrack_close()
113 : *
114 : * Deallocate Head-Tracking handle
115 : *-----------------------------------------------------------------------*/
116 :
117 1669 : void ivas_headTrack_close(
118 : HEAD_TRACK_DATA_HANDLE *hHeadTrackData /* i/o: head track handle */
119 : )
120 : {
121 1669 : if ( hHeadTrackData == NULL || *hHeadTrackData == NULL )
122 : {
123 554 : return;
124 : }
125 :
126 1115 : if ( ( *hHeadTrackData )->OrientationTracker != NULL )
127 : {
128 1115 : free( ( *hHeadTrackData )->OrientationTracker );
129 1115 : ( *hHeadTrackData )->OrientationTracker = NULL;
130 : }
131 :
132 1115 : free( ( *hHeadTrackData ) );
133 1115 : *hHeadTrackData = NULL;
134 :
135 1115 : return;
136 : }
137 :
138 :
139 : /*----------------------------------------------------------------------------------
140 : * QuatToRotMat()
141 : *
142 : * Quaternion handling: calculate rotation matrices in real-space and SHD
143 : *---------------------------------------------------------------------------------*/
144 :
145 8264525 : void QuatToRotMat(
146 : const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */
147 : float Rmat[3][3] /* o : real-space rotation matrix for this rotation */
148 : )
149 : {
150 8264525 : if ( quat.w == -3.0 )
151 : {
152 : IVAS_QUATERNION quat_local;
153 3049458 : Euler2Quat( deg2rad( quat.x ), deg2rad( quat.y ), deg2rad( quat.z ), &quat_local );
154 3049458 : QuatToRotMat( quat_local, Rmat );
155 : }
156 : else
157 : {
158 5215067 : Rmat[0][0] = quat.w * quat.w + quat.x * quat.x - quat.y * quat.y - quat.z * quat.z;
159 5215067 : Rmat[0][1] = 2.0f * ( quat.x * quat.y - quat.w * quat.z );
160 5215067 : Rmat[0][2] = 2.0f * ( quat.x * quat.z + quat.w * quat.y );
161 :
162 5215067 : Rmat[1][0] = 2.0f * ( quat.x * quat.y + quat.w * quat.z );
163 5215067 : Rmat[1][1] = quat.w * quat.w - quat.x * quat.x + quat.y * quat.y - quat.z * quat.z;
164 5215067 : Rmat[1][2] = 2.0f * ( quat.y * quat.z - quat.w * quat.x );
165 :
166 5215067 : Rmat[2][0] = 2.0f * ( quat.x * quat.z - quat.w * quat.y );
167 5215067 : Rmat[2][1] = 2.0f * ( quat.y * quat.z + quat.w * quat.x );
168 5215067 : Rmat[2][2] = quat.w * quat.w - quat.x * quat.x - quat.y * quat.y + quat.z * quat.z;
169 : }
170 :
171 8264525 : return;
172 : }
173 :
174 :
175 : /*-------------------------------------------------------------------------
176 : * rad2deg()
177 : *
178 : * Converts normalized radians to degrees
179 : *------------------------------------------------------------------------*/
180 :
181 456 : float rad2deg(
182 : float radians )
183 : {
184 460 : while ( radians >= EVS_PI )
185 : {
186 4 : radians = radians - EVS_PI;
187 : }
188 456 : while ( radians <= -EVS_PI )
189 : {
190 0 : radians = radians + EVS_PI;
191 : }
192 :
193 456 : return _180_OVER_PI * radians;
194 : }
195 :
196 :
197 : /*-------------------------------------------------------------------------
198 : * rotateAziEle()
199 : *
200 : * Apply rotation to direction parameters azimuth and elevation
201 : *------------------------------------------------------------------------*/
202 :
203 37361883 : void rotateAziEle(
204 : float azi_in, /* i : output elevation */
205 : float ele_in, /* i : input elevation */
206 : int16_t *azi, /* o : rotated azimuth */
207 : int16_t *ele, /* o : rotated elevation */
208 : float Rmat[3][3], /* i : real-space rotation matrix */
209 : const int16_t isPlanar /* i : is rotation planar and elevation meaningless? */
210 : )
211 : {
212 : int16_t n;
213 : float dv[3], dv_r[3];
214 : float w;
215 :
216 : /*Conversion spherical to cartesian coordinates*/
217 37361883 : w = cosf( ele_in * PI_OVER_180 );
218 37361883 : dv[0] = w * cosf( azi_in * PI_OVER_180 );
219 37361883 : dv[1] = w * sinf( azi_in * PI_OVER_180 );
220 37361883 : dv[2] = sinf( ele_in * PI_OVER_180 );
221 :
222 : /*Rotation mtx multiplication*/
223 149447532 : for ( n = 0; n < 3; n++ )
224 : {
225 112085649 : dv_r[n] = Rmat[n][0] * dv[0] + Rmat[n][1] * dv[1] + Rmat[n][2] * dv[2];
226 : }
227 :
228 : /*Conversion cartesian to spherical coordinates*/
229 37361883 : *azi = (int16_t) roundf( max( -180.0f, min( 180.0f, atan2f( dv_r[1], dv_r[0] ) * _180_OVER_PI ) ) );
230 37361883 : if ( isPlanar == 0 )
231 : {
232 37113423 : *ele = (int16_t) roundf( max( -90.0f, min( 90.0f, atan2f( dv_r[2], sqrtf( dv_r[0] * dv_r[0] + dv_r[1] * dv_r[1] ) ) * _180_OVER_PI ) ) );
233 : }
234 : else
235 : {
236 248460 : *ele = 0;
237 : }
238 :
239 37361883 : return;
240 : }
241 :
242 :
243 : /*-------------------------------------------------------------------------
244 : * rotateFrame_shd()
245 : *
246 : * Apply rotation to signals in Spherical Harmonic Domain
247 : *------------------------------------------------------------------------*/
248 :
249 92961 : void rotateFrame_shd(
250 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : head and external orientation combined handle */
251 : float *output[], /* i/o: unrotated HOA3 signal buffer in TD */
252 : const int16_t subframe_len, /* i : subframe length per channel */
253 : const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */
254 : const int16_t subframe_idx /* i : subframe index */
255 : )
256 : {
257 : int16_t i, l, n, m;
258 : int16_t m1, m2;
259 : int16_t shd_rot_max_order;
260 :
261 : float tmp;
262 : float tmpRot[2 * HEADROT_ORDER + 1];
263 : float SHrotmat_prev[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM];
264 : float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM];
265 : float cross_fade[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES];
266 :
267 92961 : shd_rot_max_order = hTransSetup.ambisonics_order;
268 :
269 92961 : tmp = 1.0f / ( subframe_len - 1 );
270 22403601 : for ( i = 0; i < subframe_len; i++ )
271 : {
272 22310640 : cross_fade[i] = i * tmp;
273 : }
274 :
275 : /* initialize rotation matrices with zeros */
276 1580337 : for ( i = 0; i < HEADROT_SHMAT_DIM; i++ )
277 : {
278 1487376 : set_zero( SHrotmat_prev[i], HEADROT_SHMAT_DIM );
279 1487376 : set_zero( SHrotmat[i], HEADROT_SHMAT_DIM );
280 : }
281 :
282 : /* calculate ambisonics rotation matrices for the previous and current frames */
283 92961 : SHrotmatgen( SHrotmat_prev, hCombinedOrientationData->Rmat_prev[0], shd_rot_max_order );
284 :
285 92961 : SHrotmatgen( SHrotmat, hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx], shd_rot_max_order );
286 :
287 22403601 : for ( i = 0; i < subframe_len; i++ )
288 : {
289 : /*As the rotation matrix becomes block diagonal in a SH basis, we can
290 : apply each angular-momentum block individually to save complexity. */
291 :
292 : /* loop over l blocks */
293 22310640 : m1 = 1;
294 22310640 : m2 = 4;
295 89242560 : for ( l = 1; l <= shd_rot_max_order; l++ )
296 : {
297 : /* compute mtx-vector product for this l */
298 401591520 : for ( n = m1; n < m2; n++ )
299 : {
300 334659600 : tmpRot[n - m1] = 0.f;
301 :
302 2186442720 : for ( m = m1; m < m2; m++ )
303 : {
304 : /* crossfade with previous rotation gains */
305 1851783120 : tmpRot[n - m1] += cross_fade[i] * SHrotmat[n][m] * output[m][subframe_idx * subframe_len + i] + ( 1 - cross_fade[i] ) * SHrotmat_prev[n][m] * output[m][subframe_idx * subframe_len + i];
306 : }
307 : }
308 :
309 : /* write back the result */
310 401591520 : for ( n = m1; n < m2; n++ )
311 : {
312 334659600 : output[n][subframe_idx * subframe_len + i] = tmpRot[n - m1];
313 : }
314 66931920 : m1 = m2;
315 66931920 : m2 += 2 * ( l + 1 ) + 1;
316 : }
317 :
318 : /* unoptimized code for reference (full matrix multiplication)
319 : for ( n = 0; n < nchan; n++ )
320 : {
321 : tmpRot[n] = 0.f;
322 :
323 : for ( m = 0; m < nchan; m++ )
324 : {
325 : tmpRot[n] += SHrotmat[n][m] * output[m][i];
326 : }
327 : }
328 : for ( n = 0; n < nchan; n++ )
329 : {
330 : output[n][i] = tmpRot[n];
331 : }
332 : */
333 : }
334 :
335 : /* move Rmat to Rmat_prev */
336 371844 : for ( i = 0; i < 3; i++ )
337 : {
338 278883 : mvr2r(
339 278883 : hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i],
340 278883 : hCombinedOrientationData->Rmat_prev[0][i],
341 : 3 );
342 : }
343 :
344 92961 : return;
345 : }
346 :
347 :
348 : /*-------------------------------------------------------------------------
349 : * rotateFrame_sd()
350 : *
351 : * Apply rotation to signals in Spatial Domain
352 : *------------------------------------------------------------------------*/
353 :
354 16000 : void rotateFrame_sd(
355 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : head and external orientation combined handle */
356 : float *output[], /* i/o: unrotated SD signal buffer in TD */
357 : const int16_t subframe_len, /* i : subframe length per channel */
358 : const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */
359 : const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */
360 : const int16_t subframe_idx /* i : subframe index */
361 : )
362 : {
363 : int16_t i, j;
364 : int16_t nchan, index_lfe;
365 : int16_t ch_in, ch_in_woLFE, ch_out, ch_out_woLFE;
366 : int16_t azimuth, elevation;
367 :
368 : float tmp;
369 : float tmp_gains[MAX_LS_CHANNELS - 1];
370 : float gains[MAX_LS_CHANNELS][MAX_LS_CHANNELS];
371 : float gains_prev[MAX_LS_CHANNELS][MAX_LS_CHANNELS];
372 : float output_tmp[MAX_LS_CHANNELS][L_FRAME48k];
373 : float cross_fade[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES];
374 16000 : push_wmops( "rotateFrame_sd" );
375 :
376 16000 : nchan = hTransSetup.nchan_out_woLFE + hTransSetup.num_lfe;
377 16000 : index_lfe = hTransSetup.index_lfe[0];
378 :
379 16000 : tmp = 1.0f / ( subframe_len - 1 );
380 3856000 : for ( i = 0; i < subframe_len; i++ )
381 : {
382 3840000 : cross_fade[i] = i * tmp;
383 : }
384 :
385 112000 : for ( ch_in = 0; ch_in < nchan; ch_in++ )
386 : {
387 : /* zero output and gain buffers */
388 96000 : set_zero( &output_tmp[ch_in][subframe_idx * subframe_len], subframe_len );
389 96000 : set_zero( gains_prev[ch_in], nchan );
390 96000 : set_zero( gains[ch_in], nchan );
391 :
392 : /* set gains to passthrough by default */
393 96000 : gains_prev[ch_in][ch_in] = 1.0f;
394 96000 : gains[ch_in][ch_in] = 1.0f;
395 :
396 : /* skip LFE */
397 96000 : if ( ch_in == index_lfe )
398 : {
399 16000 : continue;
400 : }
401 :
402 : /* input channel index without LFE */
403 80000 : ch_in_woLFE = ( ch_in >= index_lfe ) ? ch_in - 1 : ch_in;
404 :
405 : /* gains for previous subframe rotation */
406 80000 : rotateAziEle( hTransSetup.ls_azimuth[ch_in_woLFE], hTransSetup.ls_elevation[ch_in_woLFE], &azimuth, &elevation, hCombinedOrientationData->Rmat_prev[0], hTransSetup.is_planar_setup );
407 :
408 80000 : if ( hEFAPdata != NULL && ( hTransSetup.ls_azimuth[ch_in_woLFE] != azimuth || hTransSetup.ls_elevation[ch_in_woLFE] != elevation ) )
409 : {
410 67065 : efap_determine_gains( hEFAPdata, tmp_gains, azimuth, elevation, EFAP_MODE_EFAP );
411 469455 : for ( ch_out = 0; ch_out < nchan; ch_out++ )
412 : {
413 : /* skip LFE */
414 402390 : if ( ch_out == index_lfe )
415 : {
416 67065 : continue;
417 : }
418 :
419 : /* output channel index without LFE */
420 335325 : ch_out_woLFE = ( ch_out >= index_lfe ) ? ch_out - 1 : ch_out;
421 :
422 335325 : gains_prev[ch_in][ch_out] = tmp_gains[ch_out_woLFE];
423 : }
424 : }
425 :
426 : /* gains for current subframe rotation */
427 80000 : rotateAziEle( hTransSetup.ls_azimuth[ch_in_woLFE], hTransSetup.ls_elevation[ch_in_woLFE], &azimuth, &elevation, hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx], hTransSetup.is_planar_setup );
428 :
429 80000 : if ( hEFAPdata != NULL && ( hTransSetup.ls_azimuth[ch_in_woLFE] != azimuth || hTransSetup.ls_elevation[ch_in_woLFE] != elevation ) )
430 : {
431 67080 : efap_determine_gains( hEFAPdata, tmp_gains, azimuth, elevation, EFAP_MODE_EFAP );
432 :
433 469560 : for ( ch_out = 0; ch_out < nchan; ch_out++ )
434 : {
435 : /* skip LFE */
436 402480 : if ( ch_out == index_lfe )
437 : {
438 67080 : continue;
439 : }
440 :
441 : /* output channel index without LFE */
442 335400 : ch_out_woLFE = ( ch_out >= index_lfe ) ? ch_out - 1 : ch_out;
443 :
444 335400 : gains[ch_in][ch_out] = tmp_gains[ch_out_woLFE];
445 : }
446 : }
447 : }
448 :
449 : /* apply panning gains by mtx multiplication */
450 112000 : for ( ch_out = 0; ch_out < nchan; ch_out++ )
451 : {
452 672000 : for ( ch_in = 0; ch_in < nchan; ch_in++ )
453 : {
454 : /* crossfade with previous rotation gains */
455 138816000 : for ( i = subframe_idx * subframe_len, j = 0; j < subframe_len; i++, j++ )
456 : {
457 138240000 : output_tmp[ch_out][i] += ( cross_fade[j] ) * gains[ch_in][ch_out] * output[ch_in][i] + ( 1 - cross_fade[j] ) * gains_prev[ch_in][ch_out] * output[ch_in][i];
458 : }
459 : }
460 : }
461 :
462 : /* move Rmat to Rmat_prev */
463 64000 : for ( i = 0; i < 3; i++ )
464 : {
465 48000 : mvr2r(
466 48000 : hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i],
467 48000 : hCombinedOrientationData->Rmat_prev[0][i],
468 : 3 );
469 : }
470 :
471 : /* copy to output */
472 112000 : for ( ch_out = 0; ch_out < nchan; ch_out++ )
473 : {
474 96000 : mvr2r( &output_tmp[ch_out][subframe_idx * subframe_len], &output[ch_out][subframe_idx * subframe_len], subframe_len );
475 : }
476 :
477 16000 : pop_wmops();
478 16000 : return;
479 : }
480 :
481 :
482 : /*-------------------------------------------------------------------------
483 : * rotateFrame_shd_cldfb()
484 : *
485 : * Apply rotation to signals in Spherical Harmonic Domain and in CLDFB
486 : *------------------------------------------------------------------------*/
487 :
488 996388 : void rotateFrame_shd_cldfb(
489 : float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain real part */
490 : float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain imag part */
491 : float Rmat[3][3], /* i : real-space rotation matrix */
492 : const int16_t nInChannels, /* i : number of channels */
493 : const int16_t numTimeSlots, /* i : number of time slots to process */
494 : const int16_t shd_rot_max_order /* i : split-order rotation method */
495 : )
496 : {
497 996388 : int16_t n = 0;
498 996388 : int16_t m = 0;
499 996388 : int16_t i = 0;
500 996388 : int16_t iBand = 0;
501 996388 : int16_t l = 0, m1 = 0, m2 = 0;
502 : float realRot[2 * HEADROT_ORDER + 1], imagRot[2 * HEADROT_ORDER + 1];
503 : float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM];
504 :
505 996388 : assert( ( nInChannels == HOA3_CHANNELS || nInChannels == HOA2_CHANNELS || nInChannels == FOA_CHANNELS ) &&
506 : "Number of channels must correspond to an ambisonics order!" );
507 :
508 : /* initialize rotation matrices with zeros */
509 16938596 : for ( i = 0; i < HEADROT_SHMAT_DIM; i++ )
510 : {
511 15942208 : set_zero( SHrotmat[i], HEADROT_SHMAT_DIM );
512 : }
513 :
514 : /* calculate Ambisonics rotation matrix from the quaternion */
515 996388 : SHrotmatgen( SHrotmat, Rmat, shd_rot_max_order );
516 :
517 : /* rotation by mtx multiplication */
518 4826102 : for ( i = 0; i < numTimeSlots; i++ )
519 : {
520 233612554 : for ( iBand = 0; iBand < CLDFB_NO_CHANNELS_MAX; iBand++ )
521 : {
522 : /*As the rotation matrix becomes block diagonal in a SH basis, we can
523 : apply each angular-momentum block individually to save complexity. */
524 :
525 : /* loop over l blocks */
526 229782840 : m1 = 1;
527 229782840 : m2 = 4;
528 919131360 : for ( l = 1; l <= shd_rot_max_order; l++ )
529 : {
530 : /* compute mtx-vector product for this l */
531 4136091120 : for ( n = m1; n < m2; n++ )
532 : {
533 3446742600 : realRot[n - m1] = 0.f;
534 3446742600 : imagRot[n - m1] = 0.f;
535 :
536 22518718320 : for ( m = m1; m < m2; m++ )
537 : {
538 19071975720 : realRot[n - m1] += SHrotmat[n][m] * Cldfb_RealBuffer[m][i][iBand];
539 19071975720 : imagRot[n - m1] += SHrotmat[n][m] * Cldfb_ImagBuffer[m][i][iBand];
540 : }
541 : }
542 : /* write back the result */
543 4136091120 : for ( n = m1; n < m2; n++ )
544 : {
545 3446742600 : Cldfb_RealBuffer[n][i][iBand] = realRot[n - m1];
546 3446742600 : Cldfb_ImagBuffer[n][i][iBand] = imagRot[n - m1];
547 : }
548 689348520 : m1 = m2;
549 689348520 : m2 += 2 * ( l + 1 ) + 1;
550 : }
551 :
552 : /* unoptimized code for reference (full matrix multiplication)
553 : for (n = 0; n < nInChannels; n++)
554 : {
555 : realRot[n] = 0.f;
556 : imagRot[n] = 0.f;
557 :
558 : for (m = 0; m < nInChannels; m++)
559 : {
560 : realRot[n] += SHrotmat[n][m] * Cldfb_RealBuffer[m][i][iBand];
561 : imagRot[n] += SHrotmat[n][m] * Cldfb_ImagBuffer[m][i][iBand];
562 : }
563 : }
564 : for (n = 0; n < nInChannels; n++)
565 : {
566 : Cldfb_RealBuffer[n][i][iBand] = realRot[n];
567 : Cldfb_ImagBuffer[n][i][iBand] = imagRot[n];
568 : }
569 : */
570 : }
571 : }
572 :
573 996388 : return;
574 : }
575 :
576 :
577 : /*-------------------------------------------------------------------------
578 : * rotateFrame_sd_cldfb()
579 : *
580 : * Apply rotation to signals in Spatial Domain and in CLDFB
581 : *------------------------------------------------------------------------*/
582 :
583 8000 : void rotateFrame_sd_cldfb(
584 : float Rmat[3][3], /* i : real-space rotation matrix */
585 : float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain real part */
586 : float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain imag part */
587 : const IVAS_OUTPUT_SETUP_HANDLE hOutputSetup, /* i : output format setup number of channels */
588 : const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */
589 : const int16_t numTimeSlots, /* i : number of time slots to process */
590 : const int16_t nb_band /* i : number of CLDFB bands to process */
591 : )
592 : {
593 : int16_t iBlock, iBand, m, n;
594 : float gains[MAX_LS_CHANNELS - 1][MAX_LS_CHANNELS - 1];
595 : int16_t azimuth, elevation;
596 : float g1;
597 : float realRot[MAX_LS_CHANNELS - 1][MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX];
598 : float imagRot[MAX_LS_CHANNELS - 1][MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX];
599 : float *p_realRot, *p_imagRot;
600 : float *p_real, *p_imag;
601 : int16_t nInChannels;
602 : int16_t isPlanar;
603 8000 : push_wmops( "rotateFrame_sd_cldfb" );
604 :
605 8000 : nInChannels = hOutputSetup->nchan_out_woLFE;
606 8000 : isPlanar = 1;
607 48000 : for ( n = 0; n < nInChannels; n++ )
608 : {
609 40000 : if ( hOutputSetup->ls_elevation[n] != 0 )
610 : {
611 0 : isPlanar = 0;
612 0 : break;
613 : }
614 : }
615 :
616 : /* rotation of Euler angles */
617 48000 : for ( n = 0; n < nInChannels; n++ )
618 : {
619 40000 : rotateAziEle( hOutputSetup->ls_azimuth[n], hOutputSetup->ls_elevation[n], &azimuth, &elevation, Rmat, isPlanar );
620 40000 : if ( hEFAPdata != NULL && ( hOutputSetup->ls_azimuth[n] != azimuth || hOutputSetup->ls_elevation[n] != elevation ) )
621 : {
622 34895 : efap_determine_gains( hEFAPdata, gains[n], azimuth, elevation, EFAP_MODE_EFAP );
623 : }
624 : else
625 : {
626 5105 : set_zero( gains[n], nInChannels );
627 5105 : gains[n][n] = 1.0f;
628 : }
629 : }
630 :
631 : /* Apply panning gains by mtx multiplication*/
632 48000 : for ( n = 0; n < nInChannels; n++ )
633 : {
634 40000 : set_zero( realRot[n], MAX_PARAM_SPATIAL_SUBFRAMES * nb_band );
635 40000 : set_zero( imagRot[n], MAX_PARAM_SPATIAL_SUBFRAMES * nb_band );
636 240000 : for ( m = 0; m < nInChannels; m++ )
637 : {
638 200000 : g1 = gains[m][n];
639 200000 : p_realRot = realRot[n];
640 200000 : p_imagRot = imagRot[n];
641 200000 : if ( g1 > 0.f )
642 : {
643 372920 : for ( iBlock = 0; iBlock < numTimeSlots; iBlock++ )
644 : {
645 298336 : p_real = Cldfb_RealBuffer[m][iBlock];
646 298336 : p_imag = Cldfb_ImagBuffer[m][iBlock];
647 15215136 : for ( iBand = 0; iBand < nb_band; iBand++ )
648 : {
649 14916800 : *( p_realRot ) = *p_realRot + g1 * *( p_real++ );
650 14916800 : *( p_imagRot ) = *p_imagRot + g1 * *( p_imag++ );
651 14916800 : p_realRot++;
652 14916800 : p_imagRot++;
653 : }
654 : }
655 : }
656 : }
657 : }
658 :
659 48000 : for ( n = 0; n < nInChannels; n++ )
660 : {
661 40000 : p_realRot = realRot[n];
662 40000 : p_imagRot = imagRot[n];
663 200000 : for ( iBlock = 0; iBlock < numTimeSlots; iBlock++ )
664 : {
665 160000 : p_real = Cldfb_RealBuffer[n][iBlock];
666 160000 : p_imag = Cldfb_ImagBuffer[n][iBlock];
667 8160000 : for ( iBand = 0; iBand < nb_band; iBand++ )
668 : {
669 8000000 : *( p_real++ ) = *( p_realRot++ );
670 8000000 : *( p_imag++ ) = *( p_imagRot++ );
671 : }
672 1760000 : for ( ; iBand < CLDFB_NO_CHANNELS_MAX; iBand++ )
673 : {
674 1600000 : *( p_real++ ) = 0.f;
675 1600000 : *( p_imag++ ) = 0.f;
676 : }
677 : }
678 : }
679 8000 : pop_wmops();
680 :
681 8000 : return;
682 : }
683 :
684 :
685 : /*-----------------------------------------------------------------------*
686 : * ivas_external_orientation_open()
687 : *
688 : * Allocate and initialize external orientation handle
689 : *-----------------------------------------------------------------------*/
690 :
691 31 : ivas_error ivas_external_orientation_open(
692 : EXTERNAL_ORIENTATION_HANDLE *hExtOrientationData, /* o : external orientation handle */
693 : const int16_t num_subframes /* i : number of subframes */
694 : )
695 : {
696 :
697 : int16_t i;
698 : IVAS_QUATERNION identity;
699 :
700 31 : identity.w = 1.0f;
701 31 : identity.x = identity.y = identity.z = 0.0f;
702 :
703 : /* Allocate handle */
704 31 : if ( ( *hExtOrientationData = (EXTERNAL_ORIENTATION_HANDLE) malloc( sizeof( EXTERNAL_ORIENTATION_DATA ) ) ) == NULL )
705 : {
706 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for external orientation memory\n" ) );
707 : }
708 31 : ( *hExtOrientationData )->num_subframes = num_subframes;
709 :
710 : /* Enable head rotation and disable external orientation as default */
711 155 : for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
712 : {
713 124 : ( *hExtOrientationData )->enableHeadRotation[i] = 1;
714 124 : ( *hExtOrientationData )->enableExternalOrientation[i] = 0;
715 124 : ( *hExtOrientationData )->enableRotationInterpolation[i] = 0;
716 124 : ( *hExtOrientationData )->numFramesToTargetOrientation[i] = 0;
717 124 : ( *hExtOrientationData )->Quaternions[i] = identity;
718 : }
719 :
720 31 : return IVAS_ERR_OK;
721 : }
722 :
723 :
724 : /*-----------------------------------------------------------------------*
725 : * ivas_external_orientation_close()
726 : *
727 : * Deallocate external orientation handle
728 : *-----------------------------------------------------------------------*/
729 :
730 2335 : void ivas_external_orientation_close(
731 : EXTERNAL_ORIENTATION_HANDLE *hExtOrientationData /* i/o: external orientation handle */
732 : )
733 : {
734 2335 : if ( hExtOrientationData == NULL || *hExtOrientationData == NULL )
735 : {
736 2304 : return;
737 : }
738 :
739 31 : free( ( *hExtOrientationData ) );
740 31 : *hExtOrientationData = NULL;
741 :
742 31 : return;
743 : }
744 :
745 :
746 : /*-----------------------------------------------------------------------*
747 : * ivas_combined_orientation_open()
748 : *
749 : * Allocate and initialize combined orientation handle
750 : *-----------------------------------------------------------------------*/
751 :
752 1209 : ivas_error ivas_combined_orientation_open(
753 : COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* o : combined orientation handle */
754 : const int32_t fs, /* i : sampling rate */
755 : const int16_t num_subframes /* i : number of subframes */
756 : )
757 : {
758 : int16_t i;
759 : int16_t j;
760 : IVAS_QUATERNION identity;
761 : IVAS_VECTOR3 origo;
762 : int16_t pos_idx;
763 :
764 1209 : identity.w = 1.0f;
765 1209 : identity.x = identity.y = identity.z = 0.0f;
766 1209 : origo.x = origo.y = origo.z = 0.0f;
767 :
768 : /* Allocate handle */
769 1209 : if ( ( *hCombinedOrientationData = (COMBINED_ORIENTATION_HANDLE) malloc( sizeof( COMBINED_ORIENTATION_DATA ) ) ) == NULL )
770 : {
771 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for combined orientation memory\n" ) );
772 : }
773 :
774 : /* Initialization */
775 1209 : ( *hCombinedOrientationData )->num_subframes = num_subframes;
776 1209 : ( *hCombinedOrientationData )->interpolationCoefficient = 1.0f;
777 1209 : ( *hCombinedOrientationData )->interpolationIncrement = 1.0f;
778 1209 : ( *hCombinedOrientationData )->maximumFramesToTargetOrientation = 500;
779 1209 : ( *hCombinedOrientationData )->lrSwitchedNext = 0;
780 1209 : ( *hCombinedOrientationData )->lrSwitchedCurrent = 0;
781 1209 : ( *hCombinedOrientationData )->lrSwitchInterpVal = 0.0f;
782 1209 : ( *hCombinedOrientationData )->isInterpolationOngoing = FALSE;
783 1209 : ( *hCombinedOrientationData )->Quaternions_ext_interpolation_start = identity;
784 1209 : ( *hCombinedOrientationData )->Quaternions_ext_interpolation_target = identity;
785 :
786 : /* Initialise orientations to identity */
787 6045 : for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
788 : {
789 4836 : ( *hCombinedOrientationData )->enableCombinedOrientation[i] = 0;
790 4836 : ( *hCombinedOrientationData )->Quaternions[i] = identity;
791 4836 : ( *hCombinedOrientationData )->listenerPos[i] = origo;
792 :
793 19344 : for ( j = 0; j < 3; j++ )
794 : {
795 14508 : set_zero( ( *hCombinedOrientationData )->Rmat[i][j], 3 );
796 14508 : ( *hCombinedOrientationData )->Rmat[i][j][j] = 1.0f;
797 : }
798 : }
799 :
800 10881 : for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ )
801 : {
802 38688 : for ( j = 0; j < 3; j++ )
803 : {
804 29016 : set_zero( ( *hCombinedOrientationData )->Rmat_prev[pos_idx][j], 3 );
805 29016 : ( *hCombinedOrientationData )->Rmat_prev[pos_idx][j][j] = 1.0f;
806 : }
807 : }
808 1209 : ( *hCombinedOrientationData )->sr_pose_pred_axis = DEFAULT_AXIS;
809 1209 : ( *hCombinedOrientationData )->sr_low_res_flag = 0;
810 :
811 1209 : ( *hCombinedOrientationData )->Quaternion_prev_extOrientation = identity;
812 1209 : ( *hCombinedOrientationData )->Quaternion_frozen_ext = identity;
813 1209 : ( *hCombinedOrientationData )->Quaternion_frozen_head = identity;
814 :
815 :
816 1209 : set_zero( ( *hCombinedOrientationData )->chEneIIR[0], MASA_FREQUENCY_BANDS );
817 1209 : set_zero( ( *hCombinedOrientationData )->chEneIIR[1], MASA_FREQUENCY_BANDS );
818 1209 : set_zero( ( *hCombinedOrientationData )->procChEneIIR[0], MASA_FREQUENCY_BANDS );
819 1209 : set_zero( ( *hCombinedOrientationData )->procChEneIIR[1], MASA_FREQUENCY_BANDS );
820 :
821 1209 : ( *hCombinedOrientationData )->isExtOrientationFrozen = 0;
822 1209 : ( *hCombinedOrientationData )->isHeadRotationFrozen = 0;
823 :
824 1209 : ( *hCombinedOrientationData )->subframe_idx = 0;
825 1209 : ( *hCombinedOrientationData )->subframe_size = (int16_t) ( fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) );
826 1209 : ( *hCombinedOrientationData )->cur_subframe_samples_rendered = 0;
827 : #ifdef RTP_S4_251135_CR26253_0016_REV1
828 :
829 7254 : for ( i = 0; i < ( 1 + IVAS_MAX_NUM_OBJECTS ); i++ )
830 : {
831 6045 : ( *hCombinedOrientationData )->isDiegeticInputPI[i] = true;
832 : }
833 1209 : ( *hCombinedOrientationData )->isDiegeticInputPISet = false;
834 : #endif
835 :
836 1209 : return IVAS_ERR_OK;
837 : }
838 :
839 :
840 : /*-----------------------------------------------------------------------*
841 : * ivas_combined_orientation_close()
842 : *
843 : * Deallocate combined orientation handle
844 : *-----------------------------------------------------------------------*/
845 :
846 2335 : void ivas_combined_orientation_close(
847 : COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData /* i/o: combined orientation handle */
848 : )
849 : {
850 2335 : if ( hCombinedOrientationData == NULL || *hCombinedOrientationData == NULL )
851 : {
852 1126 : return;
853 : }
854 :
855 1209 : free( ( *hCombinedOrientationData ) );
856 1209 : *hCombinedOrientationData = NULL;
857 :
858 1209 : return;
859 : }
860 :
861 :
862 : /*-------------------------------------------------------------------------
863 : * combine_external_and_head_orientations_dec()
864 : *
865 : *
866 : *------------------------------------------------------------------------*/
867 :
868 289828 : ivas_error combine_external_and_head_orientations_dec(
869 : HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */
870 : EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
871 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
872 : )
873 : {
874 : ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis;
875 289828 : IVAS_QUATERNION *pHeadRotQuaternion = NULL;
876 289828 : IVAS_VECTOR3 *listenerPos = NULL;
877 :
878 289828 : if ( hHeadTrackData != NULL )
879 : {
880 289828 : pHeadRotQuaternion = hHeadTrackData->Quaternions;
881 289828 : listenerPos = hHeadTrackData->Pos;
882 289828 : sr_pose_pred_axis = hHeadTrackData->sr_pose_pred_axis;
883 : }
884 : else
885 : {
886 0 : sr_pose_pred_axis = DEFAULT_AXIS;
887 : }
888 :
889 289828 : return combine_external_and_head_orientations( pHeadRotQuaternion, listenerPos, sr_pose_pred_axis, hExtOrientationData, hCombinedOrientationData );
890 : }
891 :
892 :
893 : /*-------------------------------------------------------------------------
894 : * combine_external_and_head_orientations_rend()
895 : *
896 : *
897 : *------------------------------------------------------------------------*/
898 :
899 1127806 : ivas_error combine_external_and_head_orientations_rend(
900 : IVAS_REND_HeadRotData *hHeadTrackData, /* i : head track handle */
901 : EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
902 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
903 : )
904 : {
905 : ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis;
906 1127806 : IVAS_QUATERNION *headRotQuaternions = NULL;
907 1127806 : IVAS_VECTOR3 *listenerPos = NULL;
908 : int16_t i;
909 :
910 1127806 : sr_pose_pred_axis = DEFAULT_AXIS;
911 1127806 : if ( hHeadTrackData->headRotEnabled )
912 : {
913 180118 : headRotQuaternions = hHeadTrackData->headPositions;
914 180118 : listenerPos = hHeadTrackData->Pos;
915 180118 : sr_pose_pred_axis = hHeadTrackData->sr_pose_pred_axis;
916 : }
917 947688 : else if ( hExtOrientationData != NULL )
918 : {
919 : /* Head rotation data not available, use the freezed value or disable */
920 0 : for ( i = 0; i < hExtOrientationData->num_subframes; i++ )
921 : {
922 0 : if ( hExtOrientationData->enableHeadRotation[i] != 2 )
923 : {
924 0 : hExtOrientationData->enableHeadRotation[i] = 0;
925 : }
926 : }
927 : }
928 :
929 1127806 : return combine_external_and_head_orientations( headRotQuaternions, listenerPos, sr_pose_pred_axis, hExtOrientationData, hCombinedOrientationData );
930 : }
931 :
932 :
933 : /*-------------------------------------------------------------------------
934 : * combine_external_and_head_orientations()
935 : *
936 : * Combine the external orientations and the head orientation.
937 : * NOTE that the external orientations are inversed.
938 : *------------------------------------------------------------------------*/
939 :
940 1417634 : ivas_error combine_external_and_head_orientations(
941 : IVAS_QUATERNION *headRotQuaternions, /* i : quaternions for head rotation */
942 : IVAS_VECTOR3 *listenerPos, /* i : listener position */
943 : ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis, /* i : split rend pose prediction axis */
944 : EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
945 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
946 : )
947 : {
948 : int16_t i;
949 : int16_t j;
950 : IVAS_QUATERNION identity;
951 : IVAS_VECTOR3 origo;
952 :
953 1417634 : identity.w = 1.0f;
954 1417634 : identity.x = identity.y = identity.z = 0.0f;
955 1417634 : origo.x = origo.y = origo.z = 0.0f;
956 :
957 : /* Form combined orientations or return if no data available */
958 1417634 : if ( hCombinedOrientationData == NULL )
959 : {
960 947688 : if ( headRotQuaternions != NULL || hExtOrientationData != NULL )
961 : {
962 0 : return IVAS_ERR_UNEXPECTED_NULL_POINTER;
963 : }
964 : else
965 : {
966 947688 : return IVAS_ERR_OK;
967 : }
968 : }
969 469946 : else if ( headRotQuaternions == NULL && hExtOrientationData == NULL )
970 : {
971 : /* Reset the combined orientations and rotations */
972 0 : hCombinedOrientationData->isInterpolationOngoing = FALSE;
973 0 : hCombinedOrientationData->interpolationCoefficient = 1.0f;
974 0 : hCombinedOrientationData->interpolationIncrement = 1.0f;
975 0 : hCombinedOrientationData->Quaternions_ext_interpolation_start = identity;
976 0 : hCombinedOrientationData->Quaternions_ext_interpolation_target = identity;
977 0 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
978 : {
979 0 : hCombinedOrientationData->enableCombinedOrientation[i] = 0;
980 0 : hCombinedOrientationData->Quaternions[i] = identity;
981 0 : hCombinedOrientationData->listenerPos[i] = origo;
982 :
983 0 : for ( j = 0; j < 3; j++ )
984 : {
985 0 : set_zero( hCombinedOrientationData->Rmat[i][j], 3 );
986 0 : hCombinedOrientationData->Rmat[i][j][j] = 1.0f;
987 : }
988 : }
989 : }
990 469946 : else if ( hExtOrientationData == NULL && headRotQuaternions != NULL )
991 : {
992 : #ifdef RTP_S4_251135_CR26253_0016_REV1
993 : /* Disable head rotation if diegetic PI data indicating non-diegetic audio is received */
994 440746 : if ( hCombinedOrientationData->isDiegeticInputPISet && !hCombinedOrientationData->isDiegeticInputPI[0] && !hCombinedOrientationData->isDiegeticInputPI[1] && !hCombinedOrientationData->isDiegeticInputPI[2] && !hCombinedOrientationData->isDiegeticInputPI[3] && !hCombinedOrientationData->isDiegeticInputPI[4] )
995 : {
996 0 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
997 : {
998 0 : hCombinedOrientationData->Quaternions[i] = identity;
999 : }
1000 : }
1001 : else
1002 : {
1003 : /* Head rotation only */
1004 1723259 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1005 : {
1006 1282513 : hCombinedOrientationData->Quaternions[i] = headRotQuaternions[i];
1007 : }
1008 : }
1009 : #else
1010 : /* Head rotation only */
1011 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1012 : {
1013 : hCombinedOrientationData->Quaternions[i] = headRotQuaternions[i];
1014 : }
1015 : #endif
1016 : }
1017 :
1018 469946 : if ( hExtOrientationData != NULL )
1019 : {
1020 : /* External orientations */
1021 146000 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1022 : {
1023 : /* Check for frozen external orientation */
1024 116800 : if ( hExtOrientationData->enableExternalOrientation[i] == 2 )
1025 : {
1026 17391 : if ( hCombinedOrientationData->isExtOrientationFrozen != 1 )
1027 : {
1028 31 : hCombinedOrientationData->Quaternion_frozen_ext = hExtOrientationData->Quaternions[i];
1029 31 : hCombinedOrientationData->isExtOrientationFrozen = 1;
1030 : }
1031 : }
1032 : else
1033 : {
1034 99409 : hCombinedOrientationData->Quaternion_frozen_ext = identity;
1035 99409 : hCombinedOrientationData->isExtOrientationFrozen = 0;
1036 : }
1037 :
1038 116800 : if ( hExtOrientationData->enableRotationInterpolation[i] == 1 && hExtOrientationData->enableExternalOrientation[i] > 0 )
1039 : {
1040 60970 : if ( hCombinedOrientationData->isInterpolationOngoing == true && hCombinedOrientationData->interpolationCoefficient <= 1.0f && are_orientations_same( &hCombinedOrientationData->Quaternions_ext_interpolation_target, &hExtOrientationData->Quaternions[i] ) == true )
1041 : {
1042 : /* Continue interpolation */
1043 50636 : QuaternionSlerp( hCombinedOrientationData->Quaternions_ext_interpolation_start, hCombinedOrientationData->Quaternions_ext_interpolation_target, hCombinedOrientationData->interpolationCoefficient, &hCombinedOrientationData->Quaternions[i] );
1044 50636 : hCombinedOrientationData->interpolationCoefficient += hCombinedOrientationData->interpolationIncrement;
1045 : }
1046 : else
1047 : {
1048 : /* Stop interpolation or check for new interpolation */
1049 10334 : hCombinedOrientationData->isInterpolationOngoing = FALSE;
1050 10334 : hCombinedOrientationData->interpolationCoefficient = 1.0f;
1051 10334 : hCombinedOrientationData->interpolationIncrement = 1.0f;
1052 10334 : external_target_interpolation( hExtOrientationData, hCombinedOrientationData, i );
1053 : }
1054 : }
1055 : else
1056 : {
1057 : /* Interpolation disabled, use the current orientation values */
1058 :
1059 : /* Use the most recent external orientation */
1060 55830 : if ( hExtOrientationData->enableExternalOrientation[i] == 1 )
1061 : {
1062 36393 : hCombinedOrientationData->Quaternions[i] = hExtOrientationData->Quaternions[i];
1063 : }
1064 : /* Use the freezed external orientation */
1065 19437 : else if ( hExtOrientationData->enableExternalOrientation[i] == 2 )
1066 : {
1067 12803 : hCombinedOrientationData->Quaternions[i] = hCombinedOrientationData->Quaternion_frozen_ext;
1068 : }
1069 : }
1070 : }
1071 : }
1072 :
1073 469946 : if ( hExtOrientationData != NULL && headRotQuaternions != NULL )
1074 : {
1075 : /* Combine head and external orientations */
1076 146000 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1077 : {
1078 : /* Check for frozen head rotation */
1079 116800 : if ( hExtOrientationData->enableHeadRotation[i] == 2 )
1080 : {
1081 12400 : if ( hCombinedOrientationData->isHeadRotationFrozen != 1 )
1082 : {
1083 62 : hCombinedOrientationData->Quaternion_frozen_head = headRotQuaternions[i];
1084 62 : hCombinedOrientationData->isHeadRotationFrozen = 1;
1085 : }
1086 : }
1087 : else
1088 : {
1089 104400 : hCombinedOrientationData->Quaternion_frozen_head = identity;
1090 104400 : hCombinedOrientationData->isHeadRotationFrozen = 0;
1091 : }
1092 : #ifdef RTP_S4_251135_CR26253_0016_REV1
1093 : /* Disable head rotation if diegetic PI data indicating non-diegetic audio is received */
1094 116800 : if ( hCombinedOrientationData->isDiegeticInputPISet && !hCombinedOrientationData->isDiegeticInputPI[0] && !hCombinedOrientationData->isDiegeticInputPI[1] && !hCombinedOrientationData->isDiegeticInputPI[2] && !hCombinedOrientationData->isDiegeticInputPI[3] && !hCombinedOrientationData->isDiegeticInputPI[4] )
1095 : {
1096 0 : continue;
1097 : }
1098 : else
1099 : {
1100 : /* Use the most recent head rotation */
1101 116800 : if ( hExtOrientationData->enableHeadRotation[i] == 1 )
1102 : {
1103 83595 : if ( hExtOrientationData->enableExternalOrientation[i] > 0 )
1104 : {
1105 76961 : QuaternionProduct( hCombinedOrientationData->Quaternions[i], headRotQuaternions[i], &hCombinedOrientationData->Quaternions[i] );
1106 : }
1107 : else
1108 : {
1109 6634 : hCombinedOrientationData->Quaternions[i] = headRotQuaternions[i];
1110 : }
1111 : }
1112 : /* Use the freezed head rotation */
1113 33205 : else if ( hExtOrientationData->enableHeadRotation[i] == 2 )
1114 : {
1115 12400 : if ( hExtOrientationData->enableExternalOrientation[i] > 0 )
1116 : {
1117 12400 : QuaternionProduct( hCombinedOrientationData->Quaternions[i], hCombinedOrientationData->Quaternion_frozen_head, &hCombinedOrientationData->Quaternions[i] );
1118 : }
1119 : else
1120 : {
1121 0 : hCombinedOrientationData->Quaternions[i] = hCombinedOrientationData->Quaternion_frozen_head;
1122 : }
1123 : }
1124 : }
1125 : #else
1126 : /* Use the most recent head rotation */
1127 : if ( hExtOrientationData->enableHeadRotation[i] == 1 )
1128 : {
1129 : if ( hExtOrientationData->enableExternalOrientation[i] > 0 )
1130 : {
1131 : QuaternionProduct( hCombinedOrientationData->Quaternions[i], headRotQuaternions[i], &hCombinedOrientationData->Quaternions[i] );
1132 : }
1133 : else
1134 : {
1135 : hCombinedOrientationData->Quaternions[i] = headRotQuaternions[i];
1136 : }
1137 : }
1138 : /* Use the freezed head rotation */
1139 : else if ( hExtOrientationData->enableHeadRotation[i] == 2 )
1140 : {
1141 : if ( hExtOrientationData->enableExternalOrientation[i] > 0 )
1142 : {
1143 : QuaternionProduct( hCombinedOrientationData->Quaternions[i], hCombinedOrientationData->Quaternion_frozen_head, &hCombinedOrientationData->Quaternions[i] );
1144 : }
1145 : else
1146 : {
1147 : hCombinedOrientationData->Quaternions[i] = hCombinedOrientationData->Quaternion_frozen_head;
1148 : }
1149 : }
1150 : #endif
1151 :
1152 : /* Reset the combined orientations to identity */
1153 116800 : if ( hExtOrientationData->enableHeadRotation[i] == 0 && hExtOrientationData->enableExternalOrientation[i] == 0 )
1154 : {
1155 0 : hCombinedOrientationData->Quaternions[i] = identity;
1156 : }
1157 : }
1158 : }
1159 :
1160 469946 : if ( headRotQuaternions != NULL || hExtOrientationData != NULL )
1161 : {
1162 : /* Calculate the combined rotation matrix */
1163 1869259 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1164 : {
1165 1399313 : QuatToRotMat( hCombinedOrientationData->Quaternions[i], hCombinedOrientationData->Rmat[i] );
1166 : }
1167 : }
1168 :
1169 : /* Save the current orientations */
1170 469946 : if ( hExtOrientationData != NULL )
1171 : {
1172 29200 : if ( hExtOrientationData->enableExternalOrientation[hExtOrientationData->num_subframes - 1] > 0 )
1173 : {
1174 27557 : hCombinedOrientationData->Quaternion_prev_extOrientation = hExtOrientationData->Quaternions[hExtOrientationData->num_subframes - 1];
1175 : }
1176 : else
1177 : {
1178 1643 : hCombinedOrientationData->Quaternion_prev_extOrientation = identity;
1179 : }
1180 : }
1181 469946 : if ( headRotQuaternions != NULL )
1182 : {
1183 1869259 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1184 : {
1185 1399313 : hCombinedOrientationData->listenerPos[i] = listenerPos[i];
1186 : }
1187 : }
1188 :
1189 : /* Check if combined orientation is enabled */
1190 469946 : if ( headRotQuaternions != NULL && hExtOrientationData == NULL )
1191 : {
1192 1723259 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1193 : {
1194 1282513 : hCombinedOrientationData->enableCombinedOrientation[i] = 1;
1195 : }
1196 : }
1197 29200 : else if ( headRotQuaternions == NULL && hExtOrientationData != NULL )
1198 : {
1199 0 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1200 : {
1201 0 : if ( hExtOrientationData->enableExternalOrientation[i] > 0 )
1202 : {
1203 0 : hCombinedOrientationData->enableCombinedOrientation[i] = 1;
1204 : }
1205 : else
1206 : {
1207 0 : hCombinedOrientationData->enableCombinedOrientation[i] = 0;
1208 : }
1209 : }
1210 : }
1211 29200 : else if ( headRotQuaternions != NULL && hExtOrientationData != NULL )
1212 : {
1213 146000 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1214 : {
1215 116800 : if ( hExtOrientationData->enableExternalOrientation[i] > 0 || ( hExtOrientationData->enableHeadRotation[i] > 0 ) )
1216 : {
1217 116800 : hCombinedOrientationData->enableCombinedOrientation[i] = 1;
1218 : }
1219 : else
1220 : {
1221 0 : hCombinedOrientationData->enableCombinedOrientation[i] = 0;
1222 : }
1223 : }
1224 : }
1225 : else
1226 : {
1227 0 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1228 : {
1229 0 : hCombinedOrientationData->enableCombinedOrientation[i] = 0;
1230 : }
1231 : }
1232 :
1233 : #ifdef DEBUG_MODE_ORIENTATION
1234 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1235 : {
1236 : dbgwrite( &hCombinedOrientationData->enableCombinedOrientation[i], sizeof( int16_t ), 1, 1, "res/dec_orientation_enabled.dat" );
1237 : dbgwrite( &( hCombinedOrientationData->Quaternions[i].w ), sizeof( float ), 1, 1, "res/dec_orientation_quaternion_w.dat" );
1238 : dbgwrite( &( hCombinedOrientationData->Quaternions[i].x ), sizeof( float ), 1, 1, "res/dec_orientation_quaternion_x.dat" );
1239 : dbgwrite( &( hCombinedOrientationData->Quaternions[i].y ), sizeof( float ), 1, 1, "res/dec_orientation_quaternion_y.dat" );
1240 : dbgwrite( &( hCombinedOrientationData->Quaternions[i].z ), sizeof( float ), 1, 1, "res/dec_orientation_quaternion_z.dat" );
1241 : }
1242 : #endif
1243 469946 : hCombinedOrientationData->sr_pose_pred_axis = sr_pose_pred_axis;
1244 469946 : hCombinedOrientationData->subframe_idx = 0;
1245 469946 : hCombinedOrientationData->cur_subframe_samples_rendered = 0;
1246 469946 : hCombinedOrientationData->subframe_idx_start = 0;
1247 469946 : hCombinedOrientationData->cur_subframe_samples_rendered_start = 0;
1248 :
1249 : #ifdef IVAS_RTPDUMP
1250 : /* Reset external orientations */
1251 469946 : if ( hExtOrientationData != NULL )
1252 : {
1253 146000 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1254 : {
1255 116800 : hExtOrientationData->Quaternions[i] = identity;
1256 : }
1257 : }
1258 : #endif
1259 469946 : return IVAS_ERR_OK;
1260 : }
1261 :
1262 :
1263 : /*-------------------------------------------------------------------------
1264 : * external_target_interpolation()
1265 : *
1266 : *
1267 : *------------------------------------------------------------------------*/
1268 :
1269 10334 : static void external_target_interpolation(
1270 : EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
1271 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientation handle */
1272 : const int16_t i /* i : subframe index */
1273 : )
1274 : {
1275 : /* Sanity check for number of frames */
1276 10334 : hExtOrientationData->numFramesToTargetOrientation[i] = min( hExtOrientationData->numFramesToTargetOrientation[i], hCombinedOrientationData->maximumFramesToTargetOrientation );
1277 10334 : hExtOrientationData->numFramesToTargetOrientation[i] = max( hExtOrientationData->numFramesToTargetOrientation[i], 0 );
1278 :
1279 : /* Interpolate from the current orientation to the target orientation */
1280 10334 : if ( hExtOrientationData->numFramesToTargetOrientation[i] > 0 )
1281 : {
1282 3349 : if ( are_orientations_same( &hCombinedOrientationData->Quaternions_ext_interpolation_target, &hExtOrientationData->Quaternions[i] ) == false )
1283 : {
1284 : /* Target orientation is different from the previous target, update the values */
1285 :
1286 : /* Set the received orientation as the target */
1287 249 : hCombinedOrientationData->Quaternions_ext_interpolation_target = hExtOrientationData->Quaternions[i];
1288 :
1289 : /* Use the most recent external orientation as the starting orientation */
1290 249 : if ( hExtOrientationData->enableExternalOrientation[i] == 1 )
1291 : {
1292 218 : if ( i > 0 )
1293 : {
1294 141 : if ( hExtOrientationData->enableExternalOrientation[i - 1] == 0 )
1295 : {
1296 : IVAS_QUATERNION identity;
1297 31 : identity.w = 1.0f;
1298 31 : identity.x = identity.y = identity.z = 0.0f;
1299 31 : hCombinedOrientationData->Quaternions_ext_interpolation_start = identity;
1300 : }
1301 110 : else if ( hExtOrientationData->enableExternalOrientation[i - 1] == 2 )
1302 : {
1303 0 : hCombinedOrientationData->Quaternions_ext_interpolation_start = hCombinedOrientationData->Quaternion_frozen_ext;
1304 : }
1305 : else
1306 : {
1307 110 : hCombinedOrientationData->Quaternions_ext_interpolation_start = hExtOrientationData->Quaternions[i - 1];
1308 : }
1309 : }
1310 : else
1311 : {
1312 77 : hCombinedOrientationData->Quaternions_ext_interpolation_start = hCombinedOrientationData->Quaternion_prev_extOrientation;
1313 : }
1314 : }
1315 31 : else if ( hExtOrientationData->enableExternalOrientation[i] == 2 )
1316 : {
1317 31 : hCombinedOrientationData->Quaternions_ext_interpolation_start = hCombinedOrientationData->Quaternion_frozen_ext;
1318 : }
1319 :
1320 : /* Calculate the interpolation increment and coefficient */
1321 249 : hCombinedOrientationData->interpolationIncrement = 1.0f / ( (float) hExtOrientationData->numFramesToTargetOrientation[i] * (float) MAX_PARAM_SPATIAL_SUBFRAMES );
1322 249 : hCombinedOrientationData->interpolationCoefficient = hCombinedOrientationData->interpolationIncrement;
1323 : }
1324 :
1325 : /* Interpolate */
1326 3349 : hCombinedOrientationData->isInterpolationOngoing = TRUE;
1327 3349 : QuaternionSlerp( hCombinedOrientationData->Quaternions_ext_interpolation_start, hCombinedOrientationData->Quaternions_ext_interpolation_target, hCombinedOrientationData->interpolationCoefficient, &hCombinedOrientationData->Quaternions[i] );
1328 3349 : hCombinedOrientationData->interpolationCoefficient += hCombinedOrientationData->interpolationIncrement;
1329 : }
1330 : else
1331 : {
1332 : /* Use the target orientation immediately */
1333 6985 : hCombinedOrientationData->isInterpolationOngoing = FALSE;
1334 6985 : hCombinedOrientationData->interpolationCoefficient = 1.0f;
1335 6985 : hCombinedOrientationData->interpolationIncrement = 1.0f;
1336 6985 : hCombinedOrientationData->Quaternions[i] = hExtOrientationData->Quaternions[i];
1337 : }
1338 :
1339 10334 : return;
1340 : }
1341 :
1342 :
1343 : /*-------------------------------------------------------------------------
1344 : * are_orientations_same()
1345 : *
1346 : *
1347 : *------------------------------------------------------------------------*/
1348 :
1349 54203 : static bool are_orientations_same(
1350 : const IVAS_QUATERNION *orientation1,
1351 : const IVAS_QUATERNION *orientation2 )
1352 : {
1353 54203 : bool orientationsAreSame = true;
1354 54203 : float error_margin = 0.05f;
1355 :
1356 54203 : if ( fabsf( orientation1->w - orientation2->w ) > error_margin ||
1357 53870 : fabsf( orientation1->x - orientation2->x ) > error_margin ||
1358 53870 : fabsf( orientation1->y - orientation2->y ) > error_margin ||
1359 53870 : fabsf( orientation1->z - orientation2->z ) > error_margin )
1360 : {
1361 467 : orientationsAreSame = false;
1362 : }
1363 :
1364 54203 : return orientationsAreSame;
1365 : }
1366 :
1367 :
1368 : /*-----------------------------------------------------------------------*
1369 : * Local Function definitions
1370 : *-----------------------------------------------------------------------*/
1371 :
1372 : /*-------------------------------------------------------------------------
1373 : * Helper functions used by SHrotmatgen,
1374 : * an implementation of the algorithm in
1375 : * Ivanic, J. & Ruedenberg, K., J. Phys. Chem. 100, 6342 (1996)
1376 : *------------------------------------------------------------------------*/
1377 :
1378 274194790 : static float SHrot_p(
1379 : const int16_t i,
1380 : const int16_t l,
1381 : const int16_t a,
1382 : const int16_t b,
1383 : float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM],
1384 : float R_lm1[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM] )
1385 : {
1386 274194790 : float ri1 = 0.0f, rim1 = 0.0f, ri0 = 0.0f, p = 0.0f, R_lm1_1 = 0.0f, R_lm1_2 = 0.0f;
1387 :
1388 274194790 : ri1 = SHrotmat[i + 1 + 1][1 + 1 + 1];
1389 274194790 : rim1 = SHrotmat[i + 1 + 1][-1 + 1 + 1];
1390 274194790 : ri0 = SHrotmat[i + 1 + 1][0 + 1 + 1];
1391 :
1392 274194790 : if ( b == -l )
1393 : {
1394 43740630 : R_lm1_1 = R_lm1[a + l - 1][0];
1395 43740630 : R_lm1_2 = R_lm1[a + l - 1][2 * l - 2];
1396 43740630 : p = ri1 * R_lm1_1 + rim1 * R_lm1_2;
1397 : }
1398 : else
1399 : {
1400 230454160 : if ( b == l )
1401 : {
1402 43740630 : R_lm1_1 = R_lm1[a + l - 1][2 * l - 2];
1403 43740630 : R_lm1_2 = R_lm1[a + l - 1][0];
1404 43740630 : p = ri1 * R_lm1_1 - rim1 * R_lm1_2;
1405 : }
1406 : else
1407 : {
1408 186713530 : R_lm1_1 = R_lm1[a + l - 1][b + l - 1];
1409 186713530 : p = ri0 * R_lm1_1;
1410 : }
1411 : }
1412 :
1413 274194790 : return p;
1414 : }
1415 :
1416 60677450 : static float SHrot_u(
1417 : const int16_t l,
1418 : const int16_t m,
1419 : const int16_t n,
1420 : float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM],
1421 : float R_lm1[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM] )
1422 : {
1423 60677450 : return SHrot_p( 0, l, m, n, SHrotmat, R_lm1 );
1424 : }
1425 :
1426 89869910 : static float SHrot_v(
1427 : const int16_t l,
1428 : const int16_t m,
1429 : const int16_t n,
1430 : float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM],
1431 : float R_lm1[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM] )
1432 : {
1433 :
1434 : float result, d, p0, p1;
1435 :
1436 89869910 : if ( m == 0 )
1437 : {
1438 14596230 : p0 = SHrot_p( 1, l, 1, n, SHrotmat, R_lm1 );
1439 14596230 : p1 = SHrot_p( -1, l, -1, n, SHrotmat, R_lm1 );
1440 14596230 : result = p0 + p1;
1441 : }
1442 : else
1443 : {
1444 75273680 : if ( m > 0 )
1445 : {
1446 37636840 : d = ( m == 1 ) ? 1.0f : 0.0f;
1447 37636840 : p0 = SHrot_p( 1, l, m - 1, n, SHrotmat, R_lm1 );
1448 37636840 : p1 = SHrot_p( -1, l, -m + 1, n, SHrotmat, R_lm1 );
1449 37636840 : result = p0 * sqrtf( 1.0f + d ) - p1 * ( 1.0f - d );
1450 : }
1451 : else
1452 : {
1453 37636840 : d = ( m == -1 ) ? 1.0f : 0.0f;
1454 37636840 : p0 = SHrot_p( 1, l, m + 1, n, SHrotmat, R_lm1 );
1455 37636840 : p1 = SHrot_p( -1, l, -m - 1, n, SHrotmat, R_lm1 );
1456 37636840 : result = p0 * ( 1.0f - d ) + p1 * sqrtf( 1.0f + d );
1457 : }
1458 : }
1459 :
1460 89869910 : return result;
1461 : }
1462 :
1463 16888760 : static float SHrot_w(
1464 : const int16_t l,
1465 : const int16_t m,
1466 : const int16_t n,
1467 : float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM],
1468 : float R_lm1[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM] )
1469 : {
1470 : float result, p0, p1;
1471 :
1472 16888760 : if ( m == 0 )
1473 : {
1474 0 : assert( 0 && "ERROR should not be called\n" );
1475 : return 0.0f;
1476 : }
1477 : else
1478 : {
1479 16888760 : if ( m > 0 )
1480 : {
1481 8444380 : p0 = SHrot_p( 1, l, m + 1, n, SHrotmat, R_lm1 );
1482 8444380 : p1 = SHrot_p( -1, l, -m - 1, n, SHrotmat, R_lm1 );
1483 8444380 : result = p0 + p1;
1484 : }
1485 : else
1486 : {
1487 8444380 : p0 = SHrot_p( 1, l, m - 1, n, SHrotmat, R_lm1 );
1488 8444380 : p1 = SHrot_p( -1, l, -m + 1, n, SHrotmat, R_lm1 );
1489 8444380 : result = p0 - p1;
1490 : }
1491 : }
1492 :
1493 16888760 : return result;
1494 : }
1495 :
1496 :
1497 : /*-------------------------------------------------------------------------
1498 : * rotateFrame_sd_cldfb()
1499 : *
1500 : *
1501 : *------------------------------------------------------------------------*/
1502 :
1503 1254400 : void SHrotmatgen(
1504 : float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM], /* o : rotation matrix in SHD */
1505 : float Rmat[3][3], /* i : real-space rotation matrix */
1506 : const int16_t order /* i : ambisonics order */
1507 : )
1508 : {
1509 1254400 : int16_t d = 0;
1510 1254400 : int16_t band_idx = 0;
1511 : int16_t i, j;
1512 : int16_t l, m, n;
1513 : int16_t absm;
1514 1254400 : float sqdenom = 0.0f, sql2mm2 = 0.0f, sqdabsm = 0.0f, sqlabsm = 0.0f;
1515 1254400 : float u = 0.0f, v = 0.0f, w = 0.0f;
1516 : float R_lm1[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM];
1517 : float R_l[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM];
1518 :
1519 1254400 : SHrotmat[0][0] = 1.0f;
1520 :
1521 1254400 : SHrotmat[1][1] = Rmat[1][1];
1522 1254400 : SHrotmat[1][2] = Rmat[1][2];
1523 1254400 : SHrotmat[1][3] = Rmat[1][0];
1524 :
1525 1254400 : SHrotmat[2][1] = Rmat[2][1];
1526 1254400 : SHrotmat[2][2] = Rmat[2][2];
1527 1254400 : SHrotmat[2][3] = Rmat[2][0];
1528 :
1529 1254400 : SHrotmat[3][1] = Rmat[0][1];
1530 1254400 : SHrotmat[3][2] = Rmat[0][2];
1531 1254400 : SHrotmat[3][3] = Rmat[0][0];
1532 :
1533 5017600 : for ( i = 0; i < 2 * 1 + 1; i++ )
1534 : {
1535 15052800 : for ( j = 0; j < 2 * 1 + 1; j++ )
1536 : {
1537 11289600 : R_lm1[i][j] = SHrotmat[i + 1][j + 1];
1538 : }
1539 : }
1540 :
1541 1254400 : band_idx = 4;
1542 3691110 : for ( l = 2; l <= order; l++ )
1543 : {
1544 2436710 : set_zero( &R_l[0][0], HEADROT_SHMAT_DIM2 );
1545 :
1546 17032940 : for ( m = -l; m <= l; m++ )
1547 : {
1548 14596230 : d = ( m == 0 ) ? 1 : 0;
1549 14596230 : absm = (int16_t) abs( m );
1550 14596230 : sql2mm2 = sqrtf( (float) ( l * l - m * m ) );
1551 14596230 : sqdabsm = sqrtf( (float) ( ( 1 + d ) * ( l + absm - 1 ) * ( l + absm ) ) );
1552 14596230 : sqlabsm = sqrtf( (float) ( ( l - absm - 1 ) * ( l - absm ) ) );
1553 :
1554 104466140 : for ( n = -l; n <= l; n++ )
1555 : {
1556 89869910 : if ( abs( n ) == l )
1557 : {
1558 29192460 : sqdenom = sqrtf( (float) ( ( 2 * l ) * ( 2 * l - 1 ) ) );
1559 : }
1560 : else
1561 : {
1562 60677450 : sqdenom = sqrtf( (float) ( l * l - n * n ) );
1563 : }
1564 :
1565 89869910 : u = sql2mm2 / sqdenom;
1566 89869910 : v = sqdabsm / sqdenom * ( 1 - 2 * d ) * 0.5f;
1567 89869910 : w = sqlabsm / sqdenom * ( 1 - d ) * ( -0.5f );
1568 :
1569 89869910 : if ( u != 0 )
1570 : {
1571 60677450 : u = u * SHrot_u( l, m, n, SHrotmat, R_lm1 );
1572 : }
1573 89869910 : if ( v != 0 )
1574 : {
1575 89869910 : v = v * SHrot_v( l, m, n, SHrotmat, R_lm1 );
1576 : }
1577 89869910 : if ( w != 0 )
1578 : {
1579 16888760 : w = w * SHrot_w( l, m, n, SHrotmat, R_lm1 );
1580 : }
1581 89869910 : R_l[m + l][n + l] = u + v + w;
1582 : }
1583 : }
1584 :
1585 17032940 : for ( i = 0; i < 2 * l + 1; i++ )
1586 : {
1587 104466140 : for ( j = 0; j < 2 * l + 1; j++ )
1588 : {
1589 89869910 : SHrotmat[band_idx + i][band_idx + j] = R_l[i][j];
1590 : }
1591 : }
1592 :
1593 17032940 : for ( i = 0; i < 2 * l + 1; i++ )
1594 : {
1595 104466140 : for ( j = 0; j < 2 * l + 1; j++ )
1596 : {
1597 89869910 : R_lm1[i][j] = R_l[i][j];
1598 : }
1599 : }
1600 :
1601 2436710 : band_idx += 2 * l + 1;
1602 : }
1603 :
1604 1254400 : return;
1605 : }
1606 :
1607 :
1608 : /*-------------------------------------------------------------------------
1609 : * ivas_combined_orientation_update_index()
1610 : *
1611 : * update read index based on the number of rendered samples
1612 : *------------------------------------------------------------------------*/
1613 :
1614 4529302 : void ivas_combined_orientation_update_index(
1615 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientation handle */
1616 : const int16_t samples_rendered /* i : samples rendered since the last call */
1617 : )
1618 : {
1619 4529302 : if ( hCombinedOrientationData != NULL )
1620 : {
1621 2838687 : if ( hCombinedOrientationData->num_subframes == 1 || hCombinedOrientationData->sr_low_res_flag )
1622 : {
1623 : /* only one orientation available anyway or split rendering with low resolution*/
1624 144118 : hCombinedOrientationData->subframe_idx = 0;
1625 : }
1626 : else
1627 : {
1628 2694569 : hCombinedOrientationData->cur_subframe_samples_rendered += samples_rendered;
1629 2694569 : hCombinedOrientationData->subframe_idx += hCombinedOrientationData->cur_subframe_samples_rendered / hCombinedOrientationData->subframe_size;
1630 2694569 : hCombinedOrientationData->cur_subframe_samples_rendered = hCombinedOrientationData->cur_subframe_samples_rendered % hCombinedOrientationData->subframe_size;
1631 2694569 : hCombinedOrientationData->subframe_idx = min( hCombinedOrientationData->subframe_idx, hCombinedOrientationData->num_subframes - 1 );
1632 : }
1633 : }
1634 :
1635 4529302 : return;
1636 : }
1637 :
1638 :
1639 : /*-------------------------------------------------------------------------
1640 : * ivas_combined_orientation_update_index()
1641 : *
1642 : * update read index based on the number of rendered samples
1643 : *------------------------------------------------------------------------*/
1644 :
1645 2761154 : void ivas_combined_orientation_set_to_start_index(
1646 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
1647 : )
1648 : {
1649 2761154 : if ( hCombinedOrientationData != NULL )
1650 : {
1651 1184198 : hCombinedOrientationData->subframe_idx = hCombinedOrientationData->subframe_idx_start;
1652 1184198 : hCombinedOrientationData->cur_subframe_samples_rendered = hCombinedOrientationData->cur_subframe_samples_rendered_start;
1653 : }
1654 :
1655 2761154 : return;
1656 : }
1657 :
1658 :
1659 : /*-------------------------------------------------------------------------
1660 : * ivas_combined_orientation_update_start_index()
1661 : *
1662 : * update start index based on the number of rendered samples
1663 : *------------------------------------------------------------------------*/
1664 :
1665 1838131 : void ivas_combined_orientation_update_start_index(
1666 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientation handle */
1667 : const int16_t samples_rendered /* i : samples rendered since the last call */
1668 : )
1669 : {
1670 1838131 : if ( hCombinedOrientationData != NULL )
1671 : {
1672 508541 : if ( hCombinedOrientationData->num_subframes == 1 || hCombinedOrientationData->sr_low_res_flag )
1673 : {
1674 : /* only one orientation available anyway or split rendering with low resolution*/
1675 152547 : hCombinedOrientationData->subframe_idx = 0;
1676 : }
1677 : else
1678 : {
1679 355994 : hCombinedOrientationData->cur_subframe_samples_rendered_start += samples_rendered;
1680 355994 : hCombinedOrientationData->subframe_idx_start += hCombinedOrientationData->cur_subframe_samples_rendered / hCombinedOrientationData->subframe_size;
1681 355994 : hCombinedOrientationData->cur_subframe_samples_rendered_start = hCombinedOrientationData->cur_subframe_samples_rendered % hCombinedOrientationData->subframe_size;
1682 355994 : hCombinedOrientationData->subframe_idx_start = min( hCombinedOrientationData->subframe_idx, hCombinedOrientationData->num_subframes - 1 );
1683 : }
1684 : }
1685 :
1686 1838131 : return;
1687 : }
|