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 249 : 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 249 : 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 249 : ( *hHeadTrackData )->lrSwitchInterpVal = 0.0f;
81 249 : ( *hHeadTrackData )->lrSwitchedCurrent = 0;
82 249 : ( *hHeadTrackData )->lrSwitchedNext = 0;
83 249 : 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 249 : 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 996 : for ( i = 0; i < 3; i++ )
95 : {
96 747 : set_zero( ( *hHeadTrackData )->Rmat_prev[i], 3 );
97 747 : ( *hHeadTrackData )->Rmat_prev[i][i] = 1.0f;
98 : }
99 :
100 249 : ( *hHeadTrackData )->sr_pose_pred_axis = DEFAULT_AXIS;
101 :
102 249 : set_zero( ( *hHeadTrackData )->chEneIIR[0], MASA_FREQUENCY_BANDS );
103 249 : set_zero( ( *hHeadTrackData )->chEneIIR[1], MASA_FREQUENCY_BANDS );
104 249 : set_zero( ( *hHeadTrackData )->procChEneIIR[0], MASA_FREQUENCY_BANDS );
105 249 : set_zero( ( *hHeadTrackData )->procChEneIIR[1], MASA_FREQUENCY_BANDS );
106 :
107 249 : return IVAS_ERR_OK;
108 : }
109 :
110 :
111 : /*-----------------------------------------------------------------------*
112 : * ivas_headTrack_close()
113 : *
114 : * Deallocate Head-Tracking handle
115 : *-----------------------------------------------------------------------*/
116 :
117 1881 : void ivas_headTrack_close(
118 : HEAD_TRACK_DATA_HANDLE *hHeadTrackData /* i/o: head track handle */
119 : )
120 : {
121 1881 : if ( hHeadTrackData == NULL || *hHeadTrackData == NULL )
122 : {
123 1632 : return;
124 : }
125 :
126 249 : if ( ( *hHeadTrackData )->OrientationTracker != NULL )
127 : {
128 249 : free( ( *hHeadTrackData )->OrientationTracker );
129 249 : ( *hHeadTrackData )->OrientationTracker = NULL;
130 : }
131 :
132 249 : free( ( *hHeadTrackData ) );
133 249 : *hHeadTrackData = NULL;
134 :
135 249 : return;
136 : }
137 :
138 :
139 : /*----------------------------------------------------------------------------------
140 : * QuatToRotMat()
141 : *
142 : * Quaternion handling: calculate rotation matrices in real-space and SHD
143 : *---------------------------------------------------------------------------------*/
144 :
145 2208413 : 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 2208413 : if ( quat.w == -3.0 )
151 : {
152 : IVAS_QUATERNION quat_local;
153 0 : Euler2Quat( deg2rad( quat.x ), deg2rad( quat.y ), deg2rad( quat.z ), &quat_local );
154 0 : QuatToRotMat( quat_local, Rmat );
155 : }
156 : else
157 : {
158 2208413 : Rmat[0][0] = quat.w * quat.w + quat.x * quat.x - quat.y * quat.y - quat.z * quat.z;
159 2208413 : Rmat[0][1] = 2.0f * ( quat.x * quat.y - quat.w * quat.z );
160 2208413 : Rmat[0][2] = 2.0f * ( quat.x * quat.z + quat.w * quat.y );
161 :
162 2208413 : Rmat[1][0] = 2.0f * ( quat.x * quat.y + quat.w * quat.z );
163 2208413 : Rmat[1][1] = quat.w * quat.w - quat.x * quat.x + quat.y * quat.y - quat.z * quat.z;
164 2208413 : Rmat[1][2] = 2.0f * ( quat.y * quat.z - quat.w * quat.x );
165 :
166 2208413 : Rmat[2][0] = 2.0f * ( quat.x * quat.z - quat.w * quat.y );
167 2208413 : Rmat[2][1] = 2.0f * ( quat.y * quat.z + quat.w * quat.x );
168 2208413 : Rmat[2][2] = quat.w * quat.w - quat.x * quat.x - quat.y * quat.y + quat.z * quat.z;
169 : }
170 :
171 2208413 : return;
172 : }
173 :
174 :
175 : /*-------------------------------------------------------------------------
176 : * rad2deg()
177 : *
178 : * Converts normalized radians to degrees
179 : *------------------------------------------------------------------------*/
180 :
181 1368 : float rad2deg(
182 : float radians )
183 : {
184 1380 : while ( radians >= EVS_PI )
185 : {
186 12 : radians = radians - EVS_PI;
187 : }
188 1368 : while ( radians <= -EVS_PI )
189 : {
190 0 : radians = radians + EVS_PI;
191 : }
192 :
193 1368 : return _180_OVER_PI * radians;
194 : }
195 :
196 :
197 : /*-------------------------------------------------------------------------
198 : * rotateAziEle()
199 : *
200 : * Apply rotation to direction parameters azimuth and elevation
201 : *------------------------------------------------------------------------*/
202 :
203 11424191 : 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 11424191 : w = cosf( ele_in * PI_OVER_180 );
218 11424191 : dv[0] = w * cosf( azi_in * PI_OVER_180 );
219 11424191 : dv[1] = w * sinf( azi_in * PI_OVER_180 );
220 11424191 : dv[2] = sinf( ele_in * PI_OVER_180 );
221 :
222 : /*Rotation mtx multiplication*/
223 45696764 : for ( n = 0; n < 3; n++ )
224 : {
225 34272573 : 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 11424191 : *azi = (int16_t) roundf( max( -180.0f, min( 180.0f, atan2f( dv_r[1], dv_r[0] ) * _180_OVER_PI ) ) );
230 11424191 : if ( isPlanar == 0 )
231 : {
232 10727391 : *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 696800 : *ele = 0;
237 : }
238 :
239 11424191 : return;
240 : }
241 :
242 :
243 : /*-------------------------------------------------------------------------
244 : * rotateFrame_shd()
245 : *
246 : * Apply rotation to signals in Spherical Harmonic Domain
247 : *------------------------------------------------------------------------*/
248 :
249 2547 : 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 2547 : shd_rot_max_order = hTransSetup.ambisonics_order;
268 :
269 2547 : tmp = 1.0f / ( subframe_len - 1 );
270 613827 : for ( i = 0; i < subframe_len; i++ )
271 : {
272 611280 : cross_fade[i] = i * tmp;
273 : }
274 :
275 : /* initialize rotation matrices with zeros */
276 43299 : for ( i = 0; i < HEADROT_SHMAT_DIM; i++ )
277 : {
278 40752 : set_zero( SHrotmat_prev[i], HEADROT_SHMAT_DIM );
279 40752 : set_zero( SHrotmat[i], HEADROT_SHMAT_DIM );
280 : }
281 :
282 : /* calculate ambisonics rotation matrices for the previous and current frames */
283 2547 : SHrotmatgen( SHrotmat_prev, hCombinedOrientationData->Rmat_prev[0], shd_rot_max_order );
284 :
285 2547 : SHrotmatgen( SHrotmat, hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx], shd_rot_max_order );
286 :
287 613827 : 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 611280 : m1 = 1;
294 611280 : m2 = 4;
295 2445120 : for ( l = 1; l <= shd_rot_max_order; l++ )
296 : {
297 : /* compute mtx-vector product for this l */
298 11003040 : for ( n = m1; n < m2; n++ )
299 : {
300 9169200 : tmpRot[n - m1] = 0.f;
301 :
302 59905440 : for ( m = m1; m < m2; m++ )
303 : {
304 : /* crossfade with previous rotation gains */
305 50736240 : 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 11003040 : for ( n = m1; n < m2; n++ )
311 : {
312 9169200 : output[n][subframe_idx * subframe_len + i] = tmpRot[n - m1];
313 : }
314 1833840 : m1 = m2;
315 1833840 : 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 10188 : for ( i = 0; i < 3; i++ )
337 : {
338 7641 : mvr2r(
339 7641 : hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i],
340 7641 : hCombinedOrientationData->Rmat_prev[0][i],
341 : 3 );
342 : }
343 :
344 2547 : return;
345 : }
346 :
347 :
348 : /*-------------------------------------------------------------------------
349 : * rotateFrame_sd()
350 : *
351 : * Apply rotation to signals in Spatial Domain
352 : *------------------------------------------------------------------------*/
353 :
354 48000 : 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_CICP_CHANNELS - 1];
370 : float gains[MAX_CICP_CHANNELS][MAX_CICP_CHANNELS];
371 : float gains_prev[MAX_CICP_CHANNELS][MAX_CICP_CHANNELS];
372 : float output_tmp[MAX_CICP_CHANNELS][L_FRAME48k];
373 : float cross_fade[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES];
374 48000 : push_wmops( "rotateFrame_sd" );
375 :
376 48000 : nchan = hTransSetup.nchan_out_woLFE + hTransSetup.num_lfe;
377 48000 : index_lfe = hTransSetup.index_lfe[0];
378 :
379 48000 : tmp = 1.0f / ( subframe_len - 1 );
380 11568000 : for ( i = 0; i < subframe_len; i++ )
381 : {
382 11520000 : cross_fade[i] = i * tmp;
383 : }
384 :
385 336000 : for ( ch_in = 0; ch_in < nchan; ch_in++ )
386 : {
387 : /* zero output and gain buffers */
388 288000 : set_zero( &output_tmp[ch_in][subframe_idx * subframe_len], subframe_len );
389 288000 : set_zero( gains_prev[ch_in], nchan );
390 288000 : set_zero( gains[ch_in], nchan );
391 :
392 : /* set gains to passthrough by default */
393 288000 : gains_prev[ch_in][ch_in] = 1.0f;
394 288000 : gains[ch_in][ch_in] = 1.0f;
395 :
396 : /* skip LFE */
397 288000 : if ( ch_in == index_lfe )
398 : {
399 48000 : continue;
400 : }
401 :
402 : /* input channel index without LFE */
403 240000 : ch_in_woLFE = ( ch_in >= index_lfe ) ? ch_in - 1 : ch_in;
404 :
405 : /* gains for previous subframe rotation */
406 240000 : 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 240000 : if ( hEFAPdata != NULL && ( hTransSetup.ls_azimuth[ch_in_woLFE] != azimuth || hTransSetup.ls_elevation[ch_in_woLFE] != elevation ) )
409 : {
410 201195 : efap_determine_gains( hEFAPdata, tmp_gains, azimuth, elevation, EFAP_MODE_EFAP );
411 1408365 : for ( ch_out = 0; ch_out < nchan; ch_out++ )
412 : {
413 : /* skip LFE */
414 1207170 : if ( ch_out == index_lfe )
415 : {
416 201195 : continue;
417 : }
418 :
419 : /* output channel index without LFE */
420 1005975 : ch_out_woLFE = ( ch_out >= index_lfe ) ? ch_out - 1 : ch_out;
421 :
422 1005975 : gains_prev[ch_in][ch_out] = tmp_gains[ch_out_woLFE];
423 : }
424 : }
425 :
426 : /* gains for current subframe rotation */
427 240000 : 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 240000 : if ( hEFAPdata != NULL && ( hTransSetup.ls_azimuth[ch_in_woLFE] != azimuth || hTransSetup.ls_elevation[ch_in_woLFE] != elevation ) )
430 : {
431 201240 : efap_determine_gains( hEFAPdata, tmp_gains, azimuth, elevation, EFAP_MODE_EFAP );
432 :
433 1408680 : for ( ch_out = 0; ch_out < nchan; ch_out++ )
434 : {
435 : /* skip LFE */
436 1207440 : if ( ch_out == index_lfe )
437 : {
438 201240 : continue;
439 : }
440 :
441 : /* output channel index without LFE */
442 1006200 : ch_out_woLFE = ( ch_out >= index_lfe ) ? ch_out - 1 : ch_out;
443 :
444 1006200 : gains[ch_in][ch_out] = tmp_gains[ch_out_woLFE];
445 : }
446 : }
447 : }
448 :
449 : /* apply panning gains by mtx multiplication */
450 336000 : for ( ch_out = 0; ch_out < nchan; ch_out++ )
451 : {
452 2016000 : for ( ch_in = 0; ch_in < nchan; ch_in++ )
453 : {
454 : /* crossfade with previous rotation gains */
455 416448000 : for ( i = subframe_idx * subframe_len, j = 0; j < subframe_len; i++, j++ )
456 : {
457 414720000 : 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 192000 : for ( i = 0; i < 3; i++ )
464 : {
465 144000 : mvr2r(
466 144000 : hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i],
467 144000 : hCombinedOrientationData->Rmat_prev[0][i],
468 : 3 );
469 : }
470 :
471 : /* copy to output */
472 336000 : for ( ch_out = 0; ch_out < nchan; ch_out++ )
473 : {
474 288000 : mvr2r( &output_tmp[ch_out][subframe_idx * subframe_len], &output[ch_out][subframe_idx * subframe_len], subframe_len );
475 : }
476 :
477 48000 : pop_wmops();
478 48000 : 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 57933 : 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 57933 : int16_t n = 0;
498 57933 : int16_t m = 0;
499 57933 : int16_t i = 0;
500 57933 : int16_t iBand = 0;
501 57933 : 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 57933 : 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 984861 : for ( i = 0; i < HEADROT_SHMAT_DIM; i++ )
510 : {
511 926928 : set_zero( SHrotmat[i], HEADROT_SHMAT_DIM );
512 : }
513 :
514 : /* calculate Ambisonics rotation matrix from the quaternion */
515 57933 : SHrotmatgen( SHrotmat, Rmat, shd_rot_max_order );
516 :
517 : /* rotation by mtx multiplication */
518 289302 : for ( i = 0; i < numTimeSlots; i++ )
519 : {
520 14113509 : 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 13882140 : m1 = 1;
527 13882140 : m2 = 4;
528 55528560 : for ( l = 1; l <= shd_rot_max_order; l++ )
529 : {
530 : /* compute mtx-vector product for this l */
531 249878520 : for ( n = m1; n < m2; n++ )
532 : {
533 208232100 : realRot[n - m1] = 0.f;
534 208232100 : imagRot[n - m1] = 0.f;
535 :
536 1360449720 : for ( m = m1; m < m2; m++ )
537 : {
538 1152217620 : realRot[n - m1] += SHrotmat[n][m] * Cldfb_RealBuffer[m][i][iBand];
539 1152217620 : imagRot[n - m1] += SHrotmat[n][m] * Cldfb_ImagBuffer[m][i][iBand];
540 : }
541 : }
542 : /* write back the result */
543 249878520 : for ( n = m1; n < m2; n++ )
544 : {
545 208232100 : Cldfb_RealBuffer[n][i][iBand] = realRot[n - m1];
546 208232100 : Cldfb_ImagBuffer[n][i][iBand] = imagRot[n - m1];
547 : }
548 41646420 : m1 = m2;
549 41646420 : 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 57933 : return;
574 : }
575 :
576 :
577 : /*-------------------------------------------------------------------------
578 : * rotateFrame_sd_cldfb()
579 : *
580 : * Apply rotation to signals in Spatial Domain and in CLDFB
581 : *------------------------------------------------------------------------*/
582 :
583 24000 : 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_CICP_CHANNELS - 1][MAX_CICP_CHANNELS - 1];
595 : int16_t azimuth, elevation;
596 : float g1;
597 : float realRot[MAX_CICP_CHANNELS - 1][MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX];
598 : float imagRot[MAX_CICP_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 24000 : push_wmops( "rotateFrame_sd_cldfb" );
604 :
605 24000 : nInChannels = hOutputSetup->nchan_out_woLFE;
606 24000 : isPlanar = 1;
607 144000 : for ( n = 0; n < nInChannels; n++ )
608 : {
609 120000 : if ( hOutputSetup->ls_elevation[n] != 0 )
610 : {
611 0 : isPlanar = 0;
612 0 : break;
613 : }
614 : }
615 :
616 : /* rotation of Euler angles */
617 144000 : for ( n = 0; n < nInChannels; n++ )
618 : {
619 120000 : rotateAziEle( hOutputSetup->ls_azimuth[n], hOutputSetup->ls_elevation[n], &azimuth, &elevation, Rmat, isPlanar );
620 120000 : if ( hEFAPdata != NULL && ( hOutputSetup->ls_azimuth[n] != azimuth || hOutputSetup->ls_elevation[n] != elevation ) )
621 : {
622 104685 : efap_determine_gains( hEFAPdata, gains[n], azimuth, elevation, EFAP_MODE_EFAP );
623 : }
624 : else
625 : {
626 15315 : set_zero( gains[n], nInChannels );
627 15315 : gains[n][n] = 1.0f;
628 : }
629 : }
630 :
631 : /* Apply panning gains by mtx multiplication*/
632 144000 : for ( n = 0; n < nInChannels; n++ )
633 : {
634 120000 : set_zero( realRot[n], MAX_PARAM_SPATIAL_SUBFRAMES * nb_band );
635 120000 : set_zero( imagRot[n], MAX_PARAM_SPATIAL_SUBFRAMES * nb_band );
636 720000 : for ( m = 0; m < nInChannels; m++ )
637 : {
638 600000 : g1 = gains[m][n];
639 600000 : p_realRot = realRot[n];
640 600000 : p_imagRot = imagRot[n];
641 600000 : if ( g1 > 0.f )
642 : {
643 1118760 : for ( iBlock = 0; iBlock < numTimeSlots; iBlock++ )
644 : {
645 895008 : p_real = Cldfb_RealBuffer[m][iBlock];
646 895008 : p_imag = Cldfb_ImagBuffer[m][iBlock];
647 45645408 : for ( iBand = 0; iBand < nb_band; iBand++ )
648 : {
649 44750400 : *( p_realRot ) = *p_realRot + g1 * *( p_real++ );
650 44750400 : *( p_imagRot ) = *p_imagRot + g1 * *( p_imag++ );
651 44750400 : p_realRot++;
652 44750400 : p_imagRot++;
653 : }
654 : }
655 : }
656 : }
657 : }
658 :
659 144000 : for ( n = 0; n < nInChannels; n++ )
660 : {
661 120000 : p_realRot = realRot[n];
662 120000 : p_imagRot = imagRot[n];
663 600000 : for ( iBlock = 0; iBlock < numTimeSlots; iBlock++ )
664 : {
665 480000 : p_real = Cldfb_RealBuffer[n][iBlock];
666 480000 : p_imag = Cldfb_ImagBuffer[n][iBlock];
667 24480000 : for ( iBand = 0; iBand < nb_band; iBand++ )
668 : {
669 24000000 : *( p_real++ ) = *( p_realRot++ );
670 24000000 : *( p_imag++ ) = *( p_imagRot++ );
671 : }
672 5280000 : for ( ; iBand < CLDFB_NO_CHANNELS_MAX; iBand++ )
673 : {
674 4800000 : *( p_real++ ) = 0.f;
675 4800000 : *( p_imag++ ) = 0.f;
676 : }
677 : }
678 : }
679 24000 : pop_wmops();
680 :
681 24000 : return;
682 : }
683 :
684 :
685 : /*-----------------------------------------------------------------------*
686 : * ivas_external_orientation_open()
687 : *
688 : * Allocate and initialize external orientation handle
689 : *-----------------------------------------------------------------------*/
690 :
691 93 : 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 93 : identity.w = 1.0f;
701 93 : identity.x = identity.y = identity.z = 0.0f;
702 :
703 : /* Allocate handle */
704 93 : 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 93 : ( *hExtOrientationData )->num_subframes = num_subframes;
709 : /* Enable head rotation and disable external orientation as default */
710 465 : for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
711 : {
712 372 : ( *hExtOrientationData )->enableHeadRotation[i] = 1;
713 372 : ( *hExtOrientationData )->enableExternalOrientation[i] = 0;
714 372 : ( *hExtOrientationData )->enableRotationInterpolation[i] = 0;
715 372 : ( *hExtOrientationData )->numFramesToTargetOrientation[i] = 0;
716 372 : ( *hExtOrientationData )->Quaternions[i] = identity;
717 : }
718 93 : return IVAS_ERR_OK;
719 : }
720 :
721 :
722 : /*-----------------------------------------------------------------------*
723 : * ivas_external_orientation_close()
724 : *
725 : * Deallocate external orientation handle
726 : *-----------------------------------------------------------------------*/
727 :
728 3197 : void ivas_external_orientation_close(
729 : EXTERNAL_ORIENTATION_HANDLE *hExtOrientationData /* i/o: external orientation handle */
730 : )
731 : {
732 3197 : if ( hExtOrientationData == NULL || *hExtOrientationData == NULL )
733 : {
734 3104 : return;
735 : }
736 :
737 93 : free( ( *hExtOrientationData ) );
738 93 : *hExtOrientationData = NULL;
739 :
740 93 : return;
741 : }
742 :
743 :
744 : /*-----------------------------------------------------------------------*
745 : * ivas_combined_orientation_open()
746 : *
747 : * Allocate and initialize combined orientation handle
748 : *-----------------------------------------------------------------------*/
749 :
750 437 : ivas_error ivas_combined_orientation_open(
751 : COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* o : combined orientation handle */
752 : const int32_t fs, /* i : sampling rate */
753 : const int16_t num_subframes /* i : number of subframes */
754 : )
755 : {
756 : int16_t i;
757 : int16_t j;
758 : IVAS_QUATERNION identity;
759 : IVAS_VECTOR3 origo;
760 : int16_t pos_idx;
761 :
762 437 : identity.w = 1.0f;
763 437 : identity.x = identity.y = identity.z = 0.0f;
764 437 : origo.x = origo.y = origo.z = 0.0f;
765 :
766 : /* Allocate handle */
767 437 : if ( ( *hCombinedOrientationData = (COMBINED_ORIENTATION_HANDLE) malloc( sizeof( COMBINED_ORIENTATION_DATA ) ) ) == NULL )
768 : {
769 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for combined orientation memory\n" ) );
770 : }
771 :
772 : /* Initialization */
773 437 : ( *hCombinedOrientationData )->num_subframes = num_subframes;
774 437 : ( *hCombinedOrientationData )->interpolationCoefficient = 1.0f;
775 437 : ( *hCombinedOrientationData )->interpolationIncrement = 1.0f;
776 437 : ( *hCombinedOrientationData )->maximumFramesToTargetOrientation = 500;
777 437 : ( *hCombinedOrientationData )->lrSwitchedNext = 0;
778 437 : ( *hCombinedOrientationData )->lrSwitchedCurrent = 0;
779 437 : ( *hCombinedOrientationData )->lrSwitchInterpVal = 0.0f;
780 437 : ( *hCombinedOrientationData )->isInterpolationOngoing = FALSE;
781 437 : ( *hCombinedOrientationData )->Quaternions_ext_interpolation_start = identity;
782 437 : ( *hCombinedOrientationData )->Quaternions_ext_interpolation_target = identity;
783 :
784 : /* Initialise orientations to identity */
785 2185 : for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
786 : {
787 1748 : ( *hCombinedOrientationData )->enableCombinedOrientation[i] = 0;
788 1748 : ( *hCombinedOrientationData )->Quaternions[i] = identity;
789 1748 : ( *hCombinedOrientationData )->listenerPos[i] = origo;
790 :
791 6992 : for ( j = 0; j < 3; j++ )
792 : {
793 5244 : set_zero( ( *hCombinedOrientationData )->Rmat[i][j], 3 );
794 5244 : ( *hCombinedOrientationData )->Rmat[i][j][j] = 1.0f;
795 : }
796 : }
797 :
798 3933 : for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ )
799 : {
800 13984 : for ( j = 0; j < 3; j++ )
801 : {
802 10488 : set_zero( ( *hCombinedOrientationData )->Rmat_prev[pos_idx][j], 3 );
803 10488 : ( *hCombinedOrientationData )->Rmat_prev[pos_idx][j][j] = 1.0f;
804 : }
805 : }
806 437 : ( *hCombinedOrientationData )->sr_pose_pred_axis = DEFAULT_AXIS;
807 437 : ( *hCombinedOrientationData )->sr_low_res_flag = 0;
808 :
809 437 : ( *hCombinedOrientationData )->Quaternion_prev_extOrientation = identity;
810 437 : ( *hCombinedOrientationData )->Quaternion_frozen_ext = identity;
811 437 : ( *hCombinedOrientationData )->Quaternion_frozen_head = identity;
812 :
813 :
814 437 : set_zero( ( *hCombinedOrientationData )->chEneIIR[0], MASA_FREQUENCY_BANDS );
815 437 : set_zero( ( *hCombinedOrientationData )->chEneIIR[1], MASA_FREQUENCY_BANDS );
816 437 : set_zero( ( *hCombinedOrientationData )->procChEneIIR[0], MASA_FREQUENCY_BANDS );
817 437 : set_zero( ( *hCombinedOrientationData )->procChEneIIR[1], MASA_FREQUENCY_BANDS );
818 :
819 437 : ( *hCombinedOrientationData )->isExtOrientationFrozen = 0;
820 437 : ( *hCombinedOrientationData )->isHeadRotationFrozen = 0;
821 :
822 437 : ( *hCombinedOrientationData )->subframe_idx = 0;
823 437 : ( *hCombinedOrientationData )->subframe_size = (int16_t) ( fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) );
824 437 : ( *hCombinedOrientationData )->cur_subframe_samples_rendered = 0;
825 :
826 437 : return IVAS_ERR_OK;
827 : }
828 :
829 :
830 : /*-----------------------------------------------------------------------*
831 : * ivas_combined_orientation_close()
832 : *
833 : * Deallocate combined orientation handle
834 : *-----------------------------------------------------------------------*/
835 :
836 3197 : void ivas_combined_orientation_close(
837 : COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData /* i/o: combined orientation handle */
838 : )
839 : {
840 3197 : if ( hCombinedOrientationData == NULL || *hCombinedOrientationData == NULL )
841 : {
842 2760 : return;
843 : }
844 :
845 437 : free( ( *hCombinedOrientationData ) );
846 437 : *hCombinedOrientationData = NULL;
847 :
848 437 : return;
849 : }
850 :
851 :
852 : /*-------------------------------------------------------------------------
853 : * combine_external_and_head_orientations_dec()
854 : *
855 : *
856 : *------------------------------------------------------------------------*/
857 :
858 488645 : ivas_error combine_external_and_head_orientations_dec(
859 : HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */
860 : EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
861 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
862 : )
863 : {
864 : ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis;
865 488645 : IVAS_QUATERNION *pHeadRotQuaternion = NULL;
866 488645 : IVAS_VECTOR3 *listenerPos = NULL;
867 :
868 488645 : if ( hHeadTrackData != NULL )
869 : {
870 488645 : pHeadRotQuaternion = hHeadTrackData->Quaternions;
871 488645 : listenerPos = hHeadTrackData->Pos;
872 488645 : sr_pose_pred_axis = hHeadTrackData->sr_pose_pred_axis;
873 : }
874 : else
875 : {
876 0 : sr_pose_pred_axis = DEFAULT_AXIS;
877 : }
878 :
879 488645 : return combine_external_and_head_orientations( pHeadRotQuaternion, listenerPos, sr_pose_pred_axis, hExtOrientationData, hCombinedOrientationData );
880 : }
881 :
882 :
883 : /*-------------------------------------------------------------------------
884 : * combine_external_and_head_orientations_rend()
885 : *
886 : *
887 : *------------------------------------------------------------------------*/
888 :
889 2228280 : ivas_error combine_external_and_head_orientations_rend(
890 : IVAS_REND_HeadRotData *hHeadTrackData, /* i : head track handle */
891 : EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
892 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
893 : )
894 : {
895 : ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis;
896 2228280 : IVAS_QUATERNION *headRotQuaternions = NULL;
897 2228280 : IVAS_VECTOR3 *listenerPos = NULL;
898 : int16_t i;
899 :
900 2228280 : sr_pose_pred_axis = DEFAULT_AXIS;
901 2228280 : if ( hHeadTrackData != NULL )
902 : {
903 2228280 : if ( hHeadTrackData->headRotEnabled )
904 : {
905 360048 : headRotQuaternions = hHeadTrackData->headPositions;
906 360048 : listenerPos = hHeadTrackData->Pos;
907 : }
908 2228280 : sr_pose_pred_axis = hHeadTrackData->sr_pose_pred_axis;
909 : }
910 0 : else if ( hExtOrientationData != NULL )
911 : {
912 : /* Head rotation data not available, use the freezed value or disable */
913 0 : for ( i = 0; i < hExtOrientationData->num_subframes; i++ )
914 : {
915 0 : if ( hExtOrientationData->enableHeadRotation[i] != 2 )
916 : {
917 0 : hExtOrientationData->enableHeadRotation[i] = 0;
918 : }
919 : }
920 : }
921 :
922 2228280 : return combine_external_and_head_orientations( headRotQuaternions, listenerPos, sr_pose_pred_axis, hExtOrientationData, hCombinedOrientationData );
923 : }
924 :
925 :
926 : /*-------------------------------------------------------------------------
927 : * combine_external_and_head_orientations()
928 : *
929 : * Combine the external orientations and the head orientation.
930 : * NOTE that the external orientations are inversed.
931 : *------------------------------------------------------------------------*/
932 :
933 2716925 : ivas_error combine_external_and_head_orientations(
934 : IVAS_QUATERNION *headRotQuaternions, /* i : quaternions for head rotation */
935 : IVAS_VECTOR3 *listenerPos, /* i : listener position */
936 : ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis, /* i : split rend pose prediction axis */
937 : EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
938 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
939 : )
940 : {
941 : int16_t i;
942 : int16_t j;
943 : IVAS_QUATERNION identity;
944 : IVAS_VECTOR3 origo;
945 :
946 2716925 : identity.w = 1.0f;
947 2716925 : identity.x = identity.y = identity.z = 0.0f;
948 2716925 : origo.x = origo.y = origo.z = 0.0f;
949 :
950 : /* Form combined orientations or return if no data available */
951 2716925 : if ( hCombinedOrientationData == NULL )
952 : {
953 1868232 : if ( headRotQuaternions != NULL || hExtOrientationData != NULL )
954 : {
955 0 : return IVAS_ERR_UNEXPECTED_NULL_POINTER;
956 : }
957 : else
958 : {
959 1868232 : return IVAS_ERR_OK;
960 : }
961 : }
962 848693 : else if ( headRotQuaternions == NULL && hExtOrientationData == NULL )
963 : {
964 : /* Reset the combined orientations and rotations */
965 0 : hCombinedOrientationData->isInterpolationOngoing = FALSE;
966 0 : hCombinedOrientationData->interpolationCoefficient = 1.0f;
967 0 : hCombinedOrientationData->interpolationIncrement = 1.0f;
968 0 : hCombinedOrientationData->Quaternions_ext_interpolation_start = identity;
969 0 : hCombinedOrientationData->Quaternions_ext_interpolation_target = identity;
970 0 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
971 : {
972 0 : hCombinedOrientationData->enableCombinedOrientation[i] = 0;
973 0 : hCombinedOrientationData->Quaternions[i] = identity;
974 0 : hCombinedOrientationData->listenerPos[i] = origo;
975 :
976 0 : for ( j = 0; j < 3; j++ )
977 : {
978 0 : set_zero( hCombinedOrientationData->Rmat[i][j], 3 );
979 0 : hCombinedOrientationData->Rmat[i][j][j] = 1.0f;
980 : }
981 : }
982 : }
983 848693 : else if ( hExtOrientationData == NULL && headRotQuaternions != NULL )
984 : {
985 : /* Head rotation only */
986 1707689 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
987 : {
988 1063396 : hCombinedOrientationData->Quaternions[i] = headRotQuaternions[i];
989 : }
990 : }
991 :
992 848693 : if ( hExtOrientationData != NULL )
993 : {
994 : /* External orientations */
995 554800 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
996 : {
997 : /* Check for frozen external orientation */
998 350400 : if ( hExtOrientationData->enableExternalOrientation[i] == 2 )
999 : {
1000 52173 : if ( hCombinedOrientationData->isExtOrientationFrozen != 1 )
1001 : {
1002 93 : hCombinedOrientationData->Quaternion_frozen_ext = hExtOrientationData->Quaternions[i];
1003 93 : hCombinedOrientationData->isExtOrientationFrozen = 1;
1004 : }
1005 : }
1006 : else
1007 : {
1008 298227 : hCombinedOrientationData->Quaternion_frozen_ext = identity;
1009 298227 : hCombinedOrientationData->isExtOrientationFrozen = 0;
1010 : }
1011 :
1012 350400 : if ( hExtOrientationData->enableRotationInterpolation[i] == 1 && hExtOrientationData->enableExternalOrientation[i] > 0 )
1013 : {
1014 182910 : if ( hCombinedOrientationData->isInterpolationOngoing == true && hCombinedOrientationData->interpolationCoefficient <= 1.0f && are_orientations_same( &hCombinedOrientationData->Quaternions_ext_interpolation_target, &hExtOrientationData->Quaternions[i] ) == true )
1015 : {
1016 : /* Continue interpolation */
1017 151908 : QuaternionSlerp( hCombinedOrientationData->Quaternions_ext_interpolation_start, hCombinedOrientationData->Quaternions_ext_interpolation_target, hCombinedOrientationData->interpolationCoefficient, &hCombinedOrientationData->Quaternions[i] );
1018 151908 : hCombinedOrientationData->interpolationCoefficient += hCombinedOrientationData->interpolationIncrement;
1019 : }
1020 : else
1021 : {
1022 : /* Stop interpolation or check for new interpolation */
1023 31002 : hCombinedOrientationData->isInterpolationOngoing = FALSE;
1024 31002 : hCombinedOrientationData->interpolationCoefficient = 1.0f;
1025 31002 : hCombinedOrientationData->interpolationIncrement = 1.0f;
1026 31002 : external_target_interpolation( hExtOrientationData, hCombinedOrientationData, i );
1027 : }
1028 : }
1029 : else
1030 : {
1031 : /* Interpolation disabled, use the current orientation values */
1032 :
1033 : /* Use the most recent external orientation */
1034 167490 : if ( hExtOrientationData->enableExternalOrientation[i] == 1 )
1035 : {
1036 109179 : hCombinedOrientationData->Quaternions[i] = hExtOrientationData->Quaternions[i];
1037 : }
1038 : /* Use the freezed external orientation */
1039 58311 : else if ( hExtOrientationData->enableExternalOrientation[i] == 2 )
1040 : {
1041 38409 : hCombinedOrientationData->Quaternions[i] = hCombinedOrientationData->Quaternion_frozen_ext;
1042 : }
1043 : }
1044 : }
1045 : }
1046 :
1047 848693 : if ( hExtOrientationData != NULL && headRotQuaternions != NULL )
1048 : {
1049 : /* Combine head and external orientations */
1050 554800 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1051 : {
1052 : /* Check for frozen head rotation */
1053 350400 : if ( hExtOrientationData->enableHeadRotation[i] == 2 )
1054 : {
1055 37200 : if ( hCombinedOrientationData->isHeadRotationFrozen != 1 )
1056 : {
1057 186 : hCombinedOrientationData->Quaternion_frozen_head = headRotQuaternions[i];
1058 186 : hCombinedOrientationData->isHeadRotationFrozen = 1;
1059 : }
1060 : }
1061 : else
1062 : {
1063 313200 : hCombinedOrientationData->Quaternion_frozen_head = identity;
1064 313200 : hCombinedOrientationData->isHeadRotationFrozen = 0;
1065 : }
1066 : /* Use the most recent head rotation */
1067 350400 : if ( hExtOrientationData->enableHeadRotation[i] == 1 )
1068 : {
1069 250785 : if ( hExtOrientationData->enableExternalOrientation[i] > 0 )
1070 : {
1071 230883 : QuaternionProduct( hCombinedOrientationData->Quaternions[i], headRotQuaternions[i], &hCombinedOrientationData->Quaternions[i] );
1072 : }
1073 : else
1074 : {
1075 19902 : hCombinedOrientationData->Quaternions[i] = headRotQuaternions[i];
1076 : }
1077 : }
1078 : /* Use the freezed head rotation */
1079 99615 : else if ( hExtOrientationData->enableHeadRotation[i] == 2 )
1080 : {
1081 37200 : if ( hExtOrientationData->enableExternalOrientation[i] > 0 )
1082 : {
1083 37200 : QuaternionProduct( hCombinedOrientationData->Quaternions[i], hCombinedOrientationData->Quaternion_frozen_head, &hCombinedOrientationData->Quaternions[i] );
1084 : }
1085 : else
1086 : {
1087 0 : hCombinedOrientationData->Quaternions[i] = hCombinedOrientationData->Quaternion_frozen_head;
1088 : }
1089 : }
1090 :
1091 : /* Reset the combined orientations to identity */
1092 350400 : if ( hExtOrientationData->enableHeadRotation[i] == 0 && hExtOrientationData->enableExternalOrientation[i] == 0 )
1093 : {
1094 0 : hCombinedOrientationData->Quaternions[i] = identity;
1095 : }
1096 : }
1097 : }
1098 :
1099 848693 : if ( headRotQuaternions != NULL || hExtOrientationData != NULL )
1100 : {
1101 : /* Calculate the combined rotation matrix */
1102 2262489 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1103 : {
1104 1413796 : QuatToRotMat( hCombinedOrientationData->Quaternions[i], hCombinedOrientationData->Rmat[i] );
1105 : }
1106 : }
1107 :
1108 : /* Save the current orientations */
1109 848693 : if ( hExtOrientationData != NULL )
1110 : {
1111 204400 : if ( hExtOrientationData->enableExternalOrientation[hExtOrientationData->num_subframes - 1] > 0 )
1112 : {
1113 192806 : hCombinedOrientationData->Quaternion_prev_extOrientation = hExtOrientationData->Quaternions[hExtOrientationData->num_subframes - 1];
1114 : }
1115 : else
1116 : {
1117 11594 : hCombinedOrientationData->Quaternion_prev_extOrientation = identity;
1118 : }
1119 : }
1120 848693 : if ( headRotQuaternions != NULL )
1121 : {
1122 2262489 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1123 : {
1124 1413796 : hCombinedOrientationData->listenerPos[i] = listenerPos[i];
1125 : }
1126 : }
1127 :
1128 : /* Check if combined orientation is enabled */
1129 848693 : if ( headRotQuaternions != NULL && hExtOrientationData == NULL )
1130 : {
1131 1707689 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1132 : {
1133 1063396 : hCombinedOrientationData->enableCombinedOrientation[i] = 1;
1134 : }
1135 : }
1136 204400 : else if ( headRotQuaternions == NULL && hExtOrientationData != NULL )
1137 : {
1138 0 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1139 : {
1140 0 : if ( hExtOrientationData->enableExternalOrientation[i] > 0 )
1141 : {
1142 0 : hCombinedOrientationData->enableCombinedOrientation[i] = 1;
1143 : }
1144 : else
1145 : {
1146 0 : hCombinedOrientationData->enableCombinedOrientation[i] = 0;
1147 : }
1148 : }
1149 : }
1150 204400 : else if ( headRotQuaternions != NULL && hExtOrientationData != NULL )
1151 : {
1152 554800 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1153 : {
1154 350400 : if ( hExtOrientationData->enableExternalOrientation[i] > 0 || ( hExtOrientationData->enableHeadRotation[i] > 0 ) )
1155 : {
1156 350400 : hCombinedOrientationData->enableCombinedOrientation[i] = 1;
1157 : }
1158 : else
1159 : {
1160 0 : hCombinedOrientationData->enableCombinedOrientation[i] = 0;
1161 : }
1162 : }
1163 : }
1164 : else
1165 : {
1166 0 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1167 : {
1168 0 : hCombinedOrientationData->enableCombinedOrientation[i] = 0;
1169 : }
1170 : }
1171 :
1172 : #ifdef DEBUG_MODE_ORIENTATION
1173 : for ( i = 0; i < hCombinedOrientationData->num_subframes; i++ )
1174 : {
1175 : dbgwrite( &hCombinedOrientationData->enableCombinedOrientation[i], sizeof( int16_t ), 1, 1, "res/dec_orientation_enabled.dat" );
1176 : dbgwrite( &( hCombinedOrientationData->Quaternions[i].w ), sizeof( float ), 1, 1, "res/dec_orientation_quaternion_w.dat" );
1177 : dbgwrite( &( hCombinedOrientationData->Quaternions[i].x ), sizeof( float ), 1, 1, "res/dec_orientation_quaternion_x.dat" );
1178 : dbgwrite( &( hCombinedOrientationData->Quaternions[i].y ), sizeof( float ), 1, 1, "res/dec_orientation_quaternion_y.dat" );
1179 : dbgwrite( &( hCombinedOrientationData->Quaternions[i].z ), sizeof( float ), 1, 1, "res/dec_orientation_quaternion_z.dat" );
1180 : }
1181 : #endif
1182 848693 : hCombinedOrientationData->sr_pose_pred_axis = sr_pose_pred_axis;
1183 848693 : hCombinedOrientationData->subframe_idx = 0;
1184 848693 : hCombinedOrientationData->cur_subframe_samples_rendered = 0;
1185 848693 : hCombinedOrientationData->subframe_idx_start = 0;
1186 848693 : hCombinedOrientationData->cur_subframe_samples_rendered_start = 0;
1187 :
1188 848693 : return IVAS_ERR_OK;
1189 : }
1190 :
1191 :
1192 : /*-------------------------------------------------------------------------
1193 : * external_target_interpolation()
1194 : *
1195 : *
1196 : *------------------------------------------------------------------------*/
1197 :
1198 31002 : static void external_target_interpolation(
1199 : EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */
1200 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientation handle */
1201 : const int16_t i /* i : subframe index */
1202 : )
1203 : {
1204 : /* Sanity check for number of frames */
1205 31002 : hExtOrientationData->numFramesToTargetOrientation[i] = min( hExtOrientationData->numFramesToTargetOrientation[i], hCombinedOrientationData->maximumFramesToTargetOrientation );
1206 31002 : hExtOrientationData->numFramesToTargetOrientation[i] = max( hExtOrientationData->numFramesToTargetOrientation[i], 0 );
1207 :
1208 : /* Interpolate from the current orientation to the target orientation */
1209 31002 : if ( hExtOrientationData->numFramesToTargetOrientation[i] > 0 )
1210 : {
1211 10047 : if ( are_orientations_same( &hCombinedOrientationData->Quaternions_ext_interpolation_target, &hExtOrientationData->Quaternions[i] ) == false )
1212 : {
1213 : /* Target orientation is different from the previous target, update the values */
1214 :
1215 : /* Set the received orientation as the target */
1216 747 : hCombinedOrientationData->Quaternions_ext_interpolation_target = hExtOrientationData->Quaternions[i];
1217 :
1218 : /* Use the most recent external orientation as the starting orientation */
1219 747 : if ( hExtOrientationData->enableExternalOrientation[i] == 1 )
1220 : {
1221 654 : if ( i > 0 )
1222 : {
1223 227 : if ( hExtOrientationData->enableExternalOrientation[i - 1] == 0 )
1224 : {
1225 : IVAS_QUATERNION identity;
1226 62 : identity.w = 1.0f;
1227 62 : identity.x = identity.y = identity.z = 0.0f;
1228 62 : hCombinedOrientationData->Quaternions_ext_interpolation_start = identity;
1229 : }
1230 165 : else if ( hExtOrientationData->enableExternalOrientation[i - 1] == 2 )
1231 : {
1232 0 : hCombinedOrientationData->Quaternions_ext_interpolation_start = hCombinedOrientationData->Quaternion_frozen_ext;
1233 : }
1234 : else
1235 : {
1236 165 : hCombinedOrientationData->Quaternions_ext_interpolation_start = hExtOrientationData->Quaternions[i - 1];
1237 : }
1238 : }
1239 : else
1240 : {
1241 427 : hCombinedOrientationData->Quaternions_ext_interpolation_start = hCombinedOrientationData->Quaternion_prev_extOrientation;
1242 : }
1243 : }
1244 93 : else if ( hExtOrientationData->enableExternalOrientation[i] == 2 )
1245 : {
1246 93 : hCombinedOrientationData->Quaternions_ext_interpolation_start = hCombinedOrientationData->Quaternion_frozen_ext;
1247 : }
1248 :
1249 : /* Calculate the interpolation increment and coefficient */
1250 747 : hCombinedOrientationData->interpolationIncrement = 1.0f / ( (float) hExtOrientationData->numFramesToTargetOrientation[i] * (float) MAX_PARAM_SPATIAL_SUBFRAMES );
1251 747 : hCombinedOrientationData->interpolationCoefficient = hCombinedOrientationData->interpolationIncrement;
1252 : }
1253 :
1254 : /* Interpolate */
1255 10047 : hCombinedOrientationData->isInterpolationOngoing = TRUE;
1256 10047 : QuaternionSlerp( hCombinedOrientationData->Quaternions_ext_interpolation_start, hCombinedOrientationData->Quaternions_ext_interpolation_target, hCombinedOrientationData->interpolationCoefficient, &hCombinedOrientationData->Quaternions[i] );
1257 10047 : hCombinedOrientationData->interpolationCoefficient += hCombinedOrientationData->interpolationIncrement;
1258 : }
1259 : else
1260 : {
1261 : /* Use the target orientation immediately */
1262 20955 : hCombinedOrientationData->isInterpolationOngoing = FALSE;
1263 20955 : hCombinedOrientationData->interpolationCoefficient = 1.0f;
1264 20955 : hCombinedOrientationData->interpolationIncrement = 1.0f;
1265 20955 : hCombinedOrientationData->Quaternions[i] = hExtOrientationData->Quaternions[i];
1266 : }
1267 :
1268 31002 : return;
1269 : }
1270 :
1271 :
1272 : /*-------------------------------------------------------------------------
1273 : * are_orientations_same()
1274 : *
1275 : *
1276 : *------------------------------------------------------------------------*/
1277 :
1278 162609 : static bool are_orientations_same(
1279 : const IVAS_QUATERNION *orientation1,
1280 : const IVAS_QUATERNION *orientation2 )
1281 : {
1282 162609 : bool orientationsAreSame = true;
1283 162609 : float error_margin = 0.05f;
1284 :
1285 162609 : if ( fabsf( orientation1->w - orientation2->w ) > error_margin ||
1286 161610 : fabsf( orientation1->x - orientation2->x ) > error_margin ||
1287 161610 : fabsf( orientation1->y - orientation2->y ) > error_margin ||
1288 161610 : fabsf( orientation1->z - orientation2->z ) > error_margin )
1289 : {
1290 1401 : orientationsAreSame = false;
1291 : }
1292 :
1293 162609 : return orientationsAreSame;
1294 : }
1295 :
1296 :
1297 : /*-----------------------------------------------------------------------*
1298 : * Local Function definitions
1299 : *-----------------------------------------------------------------------*/
1300 :
1301 : /*-------------------------------------------------------------------------
1302 : * Helper functions used by SHrotmatgen,
1303 : * an implementation of the algorithm in
1304 : * Ivanic, J. & Ruedenberg, K., J. Phys. Chem. 100, 6342 (1996)
1305 : *------------------------------------------------------------------------*/
1306 :
1307 28220832 : static float SHrot_p(
1308 : const int16_t i,
1309 : const int16_t l,
1310 : const int16_t a,
1311 : const int16_t b,
1312 : float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM],
1313 : float R_lm1[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM] )
1314 : {
1315 28220832 : float ri1 = 0.0f, rim1 = 0.0f, ri0 = 0.0f, p = 0.0f, R_lm1_1 = 0.0f, R_lm1_2 = 0.0f;
1316 :
1317 28220832 : ri1 = SHrotmat[i + 1 + 1][1 + 1 + 1];
1318 28220832 : rim1 = SHrotmat[i + 1 + 1][-1 + 1 + 1];
1319 28220832 : ri0 = SHrotmat[i + 1 + 1][0 + 1 + 1];
1320 :
1321 28220832 : if ( b == -l )
1322 : {
1323 4622442 : R_lm1_1 = R_lm1[a + l - 1][0];
1324 4622442 : R_lm1_2 = R_lm1[a + l - 1][2 * l - 2];
1325 4622442 : p = ri1 * R_lm1_1 + rim1 * R_lm1_2;
1326 : }
1327 : else
1328 : {
1329 23598390 : if ( b == l )
1330 : {
1331 4622442 : R_lm1_1 = R_lm1[a + l - 1][2 * l - 2];
1332 4622442 : R_lm1_2 = R_lm1[a + l - 1][0];
1333 4622442 : p = ri1 * R_lm1_1 - rim1 * R_lm1_2;
1334 : }
1335 : else
1336 : {
1337 18975948 : R_lm1_1 = R_lm1[a + l - 1][b + l - 1];
1338 18975948 : p = ri0 * R_lm1_1;
1339 : }
1340 : }
1341 :
1342 28220832 : return p;
1343 : }
1344 :
1345 6273300 : static float SHrot_u(
1346 : const int16_t l,
1347 : const int16_t m,
1348 : const int16_t n,
1349 : float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM],
1350 : float R_lm1[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM] )
1351 : {
1352 6273300 : return SHrot_p( 0, l, m, n, SHrotmat, R_lm1 );
1353 : }
1354 :
1355 9418968 : static float SHrot_v(
1356 : const int16_t l,
1357 : const int16_t m,
1358 : const int16_t n,
1359 : float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM],
1360 : float R_lm1[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM] )
1361 : {
1362 :
1363 : float result, d, p0, p1;
1364 :
1365 9418968 : if ( m == 0 )
1366 : {
1367 1572834 : p0 = SHrot_p( 1, l, 1, n, SHrotmat, R_lm1 );
1368 1572834 : p1 = SHrot_p( -1, l, -1, n, SHrotmat, R_lm1 );
1369 1572834 : result = p0 + p1;
1370 : }
1371 : else
1372 : {
1373 7846134 : if ( m > 0 )
1374 : {
1375 3923067 : d = ( m == 1 ) ? 1.0f : 0.0f;
1376 3923067 : p0 = SHrot_p( 1, l, m - 1, n, SHrotmat, R_lm1 );
1377 3923067 : p1 = SHrot_p( -1, l, -m + 1, n, SHrotmat, R_lm1 );
1378 3923067 : result = p0 * sqrtf( 1.0f + d ) - p1 * ( 1.0f - d );
1379 : }
1380 : else
1381 : {
1382 3923067 : d = ( m == -1 ) ? 1.0f : 0.0f;
1383 3923067 : p0 = SHrot_p( 1, l, m + 1, n, SHrotmat, R_lm1 );
1384 3923067 : p1 = SHrot_p( -1, l, -m - 1, n, SHrotmat, R_lm1 );
1385 3923067 : result = p0 * ( 1.0f - d ) + p1 * sqrtf( 1.0f + d );
1386 : }
1387 : }
1388 :
1389 9418968 : return result;
1390 : }
1391 :
1392 1554798 : static float SHrot_w(
1393 : const int16_t l,
1394 : const int16_t m,
1395 : const int16_t n,
1396 : float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM],
1397 : float R_lm1[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM] )
1398 : {
1399 : float result, p0, p1;
1400 :
1401 1554798 : if ( m == 0 )
1402 : {
1403 0 : assert( 0 && "ERROR should not be called\n" );
1404 : return 0.0f;
1405 : }
1406 : else
1407 : {
1408 1554798 : if ( m > 0 )
1409 : {
1410 777399 : p0 = SHrot_p( 1, l, m + 1, n, SHrotmat, R_lm1 );
1411 777399 : p1 = SHrot_p( -1, l, -m - 1, n, SHrotmat, R_lm1 );
1412 777399 : result = p0 + p1;
1413 : }
1414 : else
1415 : {
1416 777399 : p0 = SHrot_p( 1, l, m - 1, n, SHrotmat, R_lm1 );
1417 777399 : p1 = SHrot_p( -1, l, -m + 1, n, SHrotmat, R_lm1 );
1418 777399 : result = p0 - p1;
1419 : }
1420 : }
1421 :
1422 1554798 : return result;
1423 : }
1424 :
1425 :
1426 : /*-------------------------------------------------------------------------
1427 : * rotateFrame_sd_cldfb()
1428 : *
1429 : *
1430 : *------------------------------------------------------------------------*/
1431 :
1432 207117 : void SHrotmatgen(
1433 : float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM], /* o : rotation matrix in SHD */
1434 : float Rmat[3][3], /* i : real-space rotation matrix */
1435 : const int16_t order /* i : ambisonics order */
1436 : )
1437 : {
1438 207117 : int16_t d = 0;
1439 207117 : int16_t band_idx = 0;
1440 : int16_t i, j;
1441 : int16_t l, m, n;
1442 : int16_t absm;
1443 207117 : float sqdenom = 0.0f, sql2mm2 = 0.0f, sqdabsm = 0.0f, sqlabsm = 0.0f;
1444 207117 : float u = 0.0f, v = 0.0f, w = 0.0f;
1445 : float R_lm1[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM];
1446 : float R_l[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM];
1447 :
1448 207117 : SHrotmat[0][0] = 1.0f;
1449 :
1450 207117 : SHrotmat[1][1] = Rmat[1][1];
1451 207117 : SHrotmat[1][2] = Rmat[1][2];
1452 207117 : SHrotmat[1][3] = Rmat[1][0];
1453 :
1454 207117 : SHrotmat[2][1] = Rmat[2][1];
1455 207117 : SHrotmat[2][2] = Rmat[2][2];
1456 207117 : SHrotmat[2][3] = Rmat[2][0];
1457 :
1458 207117 : SHrotmat[3][1] = Rmat[0][1];
1459 207117 : SHrotmat[3][2] = Rmat[0][2];
1460 207117 : SHrotmat[3][3] = Rmat[0][0];
1461 :
1462 828468 : for ( i = 0; i < 2 * 1 + 1; i++ )
1463 : {
1464 2485404 : for ( j = 0; j < 2 * 1 + 1; j++ )
1465 : {
1466 1864053 : R_lm1[i][j] = SHrotmat[i + 1][j + 1];
1467 : }
1468 : }
1469 :
1470 207117 : band_idx = 4;
1471 477261 : for ( l = 2; l <= order; l++ )
1472 : {
1473 270144 : set_zero( &R_l[0][0], HEADROT_SHMAT_DIM2 );
1474 :
1475 1842978 : for ( m = -l; m <= l; m++ )
1476 : {
1477 1572834 : d = ( m == 0 ) ? 1 : 0;
1478 1572834 : absm = (int16_t) abs( m );
1479 1572834 : sql2mm2 = sqrtf( (float) ( l * l - m * m ) );
1480 1572834 : sqdabsm = sqrtf( (float) ( ( 1 + d ) * ( l + absm - 1 ) * ( l + absm ) ) );
1481 1572834 : sqlabsm = sqrtf( (float) ( ( l - absm - 1 ) * ( l - absm ) ) );
1482 :
1483 10991802 : for ( n = -l; n <= l; n++ )
1484 : {
1485 9418968 : if ( abs( n ) == l )
1486 : {
1487 3145668 : sqdenom = sqrtf( (float) ( ( 2 * l ) * ( 2 * l - 1 ) ) );
1488 : }
1489 : else
1490 : {
1491 6273300 : sqdenom = sqrtf( (float) ( l * l - n * n ) );
1492 : }
1493 :
1494 9418968 : u = sql2mm2 / sqdenom;
1495 9418968 : v = sqdabsm / sqdenom * ( 1 - 2 * d ) * 0.5f;
1496 9418968 : w = sqlabsm / sqdenom * ( 1 - d ) * ( -0.5f );
1497 :
1498 9418968 : if ( u != 0 )
1499 : {
1500 6273300 : u = u * SHrot_u( l, m, n, SHrotmat, R_lm1 );
1501 : }
1502 9418968 : if ( v != 0 )
1503 : {
1504 9418968 : v = v * SHrot_v( l, m, n, SHrotmat, R_lm1 );
1505 : }
1506 9418968 : if ( w != 0 )
1507 : {
1508 1554798 : w = w * SHrot_w( l, m, n, SHrotmat, R_lm1 );
1509 : }
1510 9418968 : R_l[m + l][n + l] = u + v + w;
1511 : }
1512 : }
1513 :
1514 1842978 : for ( i = 0; i < 2 * l + 1; i++ )
1515 : {
1516 10991802 : for ( j = 0; j < 2 * l + 1; j++ )
1517 : {
1518 9418968 : SHrotmat[band_idx + i][band_idx + j] = R_l[i][j];
1519 : }
1520 : }
1521 :
1522 1842978 : for ( i = 0; i < 2 * l + 1; i++ )
1523 : {
1524 10991802 : for ( j = 0; j < 2 * l + 1; j++ )
1525 : {
1526 9418968 : R_lm1[i][j] = R_l[i][j];
1527 : }
1528 : }
1529 :
1530 270144 : band_idx += 2 * l + 1;
1531 : }
1532 :
1533 207117 : return;
1534 : }
1535 :
1536 :
1537 : /*-------------------------------------------------------------------------
1538 : * ivas_combined_orientation_update_index()
1539 : *
1540 : * update read index based on the number of rendered samples
1541 : *------------------------------------------------------------------------*/
1542 :
1543 5651421 : void ivas_combined_orientation_update_index(
1544 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientation handle */
1545 : const int16_t samples_rendered /* i : samples rendered since the last call */
1546 : )
1547 : {
1548 5651421 : if ( hCombinedOrientationData != NULL )
1549 : {
1550 1383964 : if ( hCombinedOrientationData->num_subframes == 1 || hCombinedOrientationData->sr_low_res_flag )
1551 : {
1552 : /* only one orientation available anyway or split rendering with low resolution*/
1553 551720 : hCombinedOrientationData->subframe_idx = 0;
1554 : }
1555 : else
1556 : {
1557 832244 : hCombinedOrientationData->cur_subframe_samples_rendered += samples_rendered;
1558 832244 : hCombinedOrientationData->subframe_idx += hCombinedOrientationData->cur_subframe_samples_rendered / hCombinedOrientationData->subframe_size;
1559 832244 : hCombinedOrientationData->cur_subframe_samples_rendered = hCombinedOrientationData->cur_subframe_samples_rendered % hCombinedOrientationData->subframe_size;
1560 832244 : hCombinedOrientationData->subframe_idx = min( hCombinedOrientationData->subframe_idx, hCombinedOrientationData->num_subframes - 1 );
1561 : }
1562 : }
1563 :
1564 5651421 : return;
1565 : }
1566 :
1567 :
1568 : /*-------------------------------------------------------------------------
1569 : * ivas_combined_orientation_update_index()
1570 : *
1571 : * update read index based on the number of rendered samples
1572 : *------------------------------------------------------------------------*/
1573 :
1574 4258437 : void ivas_combined_orientation_set_to_start_index(
1575 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */
1576 : )
1577 : {
1578 4258437 : if ( hCombinedOrientationData != NULL )
1579 : {
1580 1121142 : hCombinedOrientationData->subframe_idx = hCombinedOrientationData->subframe_idx_start;
1581 1121142 : hCombinedOrientationData->cur_subframe_samples_rendered = hCombinedOrientationData->cur_subframe_samples_rendered_start;
1582 : }
1583 :
1584 4258437 : return;
1585 : }
1586 :
1587 :
1588 : /*-------------------------------------------------------------------------
1589 : * ivas_combined_orientation_update_start_index()
1590 : *
1591 : * update start index based on the number of rendered samples
1592 : *------------------------------------------------------------------------*/
1593 :
1594 5110092 : void ivas_combined_orientation_update_start_index(
1595 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientation handle */
1596 : const int16_t samples_rendered /* i : samples rendered since the last call */
1597 : )
1598 : {
1599 5110092 : if ( hCombinedOrientationData != NULL )
1600 : {
1601 849042 : if ( hCombinedOrientationData->num_subframes == 1 || hCombinedOrientationData->sr_low_res_flag )
1602 : {
1603 : /* only one orientation available anyway or split rendering with low resolution*/
1604 567346 : hCombinedOrientationData->subframe_idx = 0;
1605 : }
1606 : else
1607 : {
1608 281696 : hCombinedOrientationData->cur_subframe_samples_rendered_start += samples_rendered;
1609 281696 : hCombinedOrientationData->subframe_idx_start += hCombinedOrientationData->cur_subframe_samples_rendered / hCombinedOrientationData->subframe_size;
1610 281696 : hCombinedOrientationData->cur_subframe_samples_rendered_start = hCombinedOrientationData->cur_subframe_samples_rendered % hCombinedOrientationData->subframe_size;
1611 281696 : hCombinedOrientationData->subframe_idx_start = min( hCombinedOrientationData->subframe_idx, hCombinedOrientationData->num_subframes - 1 );
1612 : }
1613 : }
1614 :
1615 5110092 : return;
1616 : }
|