LCOV - code coverage report
Current view: top level - lib_com - ivas_rotation_com.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 4 97 4.1 %
Date: 2025-08-23 01:22:27 Functions: 1 7 14.3 %

          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_fx.h"
      40             : #include "ivas_prot_fx.h"
      41             : #ifdef DEBUGGING
      42             : #include "debug.h"
      43             : #endif
      44             : #include "wmc_auto.h"
      45             : #include "basop_util.h"
      46             : #include "enh64.h"
      47             : /*-------------------------------------------------------------------------
      48             :  * Euler2Quat()
      49             :  *
      50             :  * Calculate corresponding Quaternion from Euler angles in radians
      51             :  *------------------------------------------------------------------------*/
      52           0 : void Euler2Quat_fx(
      53             :     const Word32 yaw,     /* i  : yaw   (x) Q22                      */
      54             :     const Word32 pitch,   /* i  : pitch (y) Q22                      */
      55             :     const Word32 roll,    /* i  : roll  (z) Q22                      */
      56             :     IVAS_QUATERNION *quat /* o  : quaternion describing the rotation Q22*/
      57             : )
      58             : {
      59           0 :     Word16 cr = getCosWord16( extract_l( L_shr_r( roll, 10 ) ) );           // Q14
      60           0 :     Word16 sr = shr( getSinWord16( extract_l( L_shr_r( roll, 10 ) ) ), 1 ); // Q14
      61           0 :     Word16 cp = getCosWord16( extract_l( L_shr_r( pitch, 10 ) ) );
      62           0 :     Word16 sp = shr( getSinWord16( extract_l( L_shr_r( pitch, 10 ) ) ), 1 ); // Q14
      63           0 :     Word16 cy = getCosWord16( extract_l( L_shr_r( yaw, 10 ) ) );
      64           0 :     Word16 sy = shr( getSinWord16( extract_l( L_shr_r( yaw, 10 ) ) ), 1 );                                          // Q14
      65           0 :     quat->w_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( cr, cp ), cy ), Mpy_32_16_1( L_mult0( sr, sp ), sy ) ), 5 ); // Q22
      66           0 :     move32();
      67           0 :     quat->x_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( sr, cp ), cy ), Mpy_32_16_1( L_mult0( cr, sp ), sy ) ), 5 ); // Q22
      68           0 :     move32();
      69           0 :     quat->y_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( sr, cp ), sy ), Mpy_32_16_1( L_mult0( cr, sp ), cy ) ), 5 ); // Q22
      70           0 :     move32();
      71           0 :     quat->z_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( cr, cp ), sy ), Mpy_32_16_1( L_mult0( sr, sp ), cy ) ), 5 ); // Q22
      72           0 :     move32();
      73             : 
      74           0 :     quat->q_fact = Q22;
      75           0 :     move16();
      76             : 
      77           0 :     return;
      78             : }
      79             : 
      80             : 
      81             : /*-------------------------------------------------------------------------
      82             :  * Copy_Quat_fx()
      83             :  *
      84             :  * Quaternion q factor modification
      85             :  *------------------------------------------------------------------------*/
      86           0 : void Copy_Quat_fx(
      87             :     const IVAS_QUATERNION *in_quat, /* i  : quaternion describing the rotation             */
      88             :     IVAS_QUATERNION *out_quat       /* i  : quaternion describing the rotation             */
      89             : )
      90             : {
      91           0 :     out_quat->q_fact = in_quat->q_fact;
      92           0 :     out_quat->w_fx = in_quat->w_fx;
      93           0 :     out_quat->x_fx = in_quat->x_fx;
      94           0 :     out_quat->y_fx = in_quat->y_fx;
      95           0 :     out_quat->z_fx = in_quat->z_fx;
      96           0 :     move16();
      97           0 :     move32();
      98           0 :     move32();
      99           0 :     move32();
     100           0 :     move32();
     101             : 
     102           0 :     return;
     103             : }
     104             : 
     105             : /*-------------------------------------------------------------------------
     106             :  * Scale_Quat_fx()
     107             :  *
     108             :  * Quaternion q factor modification
     109             :  *------------------------------------------------------------------------*/
     110           0 : void modify_Quat_q_fx(
     111             :     const IVAS_QUATERNION *in_quat, /* i  : quaternion describing the rotation             */
     112             :     IVAS_QUATERNION *out_quat,      /* i  : quaternion describing the rotation             */
     113             :     Word16 q_new                    /* i  : quaternion describing the rotation             */
     114             : )
     115             : {
     116           0 :     out_quat->w_fx = L_shl_sat( in_quat->w_fx, sub( q_new, in_quat->q_fact ) ); // q_new
     117           0 :     out_quat->x_fx = L_shl_sat( in_quat->x_fx, sub( q_new, in_quat->q_fact ) ); // q_new
     118           0 :     out_quat->y_fx = L_shl_sat( in_quat->y_fx, sub( q_new, in_quat->q_fact ) ); // q_new
     119           0 :     out_quat->z_fx = L_shl_sat( in_quat->z_fx, sub( q_new, in_quat->q_fact ) ); // q_new
     120           0 :     out_quat->q_fact = q_new;
     121           0 :     return;
     122             : }
     123             : 
     124             : /*-------------------------------------------------------------------------
     125             :  * modify_Rmat_q_fx()
     126             :  *
     127             :  * Rotation matrix q factor modification
     128             :  *------------------------------------------------------------------------*/
     129           0 : void modify_Rmat_q_fx(
     130             :     Word32 Rmat_in[3][3],  /* i  : real-space rotation matrix for this rotation  */
     131             :     Word32 Rmat_out[3][3], /* o  : real-space rotation matrix for this rotation*/
     132             :     Word16 q_cur,          /* i  : current q factor for rotation  matrix            */
     133             :     Word16 q_new           /* i  : target q factor for rotation    matrix         */
     134             : )
     135             : {
     136             :     Word16 j, k;
     137             : 
     138           0 :     FOR( j = 0; j < 3; j++ )
     139             :     {
     140           0 :         FOR( k = 0; k < 3; k++ )
     141             :         {
     142           0 :             Rmat_out[j][k] = L_shl( Rmat_in[j][k], sub( q_new, q_cur ) );
     143           0 :             move32();
     144             :         }
     145             :     }
     146           0 :     return;
     147             : }
     148             : 
     149             : /*-------------------------------------------------------------------------
     150             :  * Quat2EulerDegree()
     151             :  *
     152             :  * Quaternion handling: calculate corresponding Euler angles in degrees
     153             :  *------------------------------------------------------------------------*/
     154           0 : void Quat2EulerDegree_fx(
     155             :     const IVAS_QUATERNION quat, /* i  : quaternion describing the rotation             */
     156             :     Word32 *yaw_fx,             /* o  : yaw                                            */
     157             :     Word32 *pitch_fx,           /* o  : pitch                                          */
     158             :     Word32 *roll_fx             /* o  : roll                                           */
     159             : )
     160             : {
     161           0 :     IF( NE_32( quat.w_fx, L_negate( 12582912 ) /*3.0f in Q22*/ ) )
     162             :     {
     163           0 :         Word32 tmp1 = W_extract_l( W_shr( W_mult0_32_32( quat.w_fx, quat.x_fx ), Q22 ) ); // Q22
     164           0 :         Word32 tmp2 = W_extract_l( W_shr( W_mult0_32_32( quat.y_fx, quat.z_fx ), Q22 ) ); // Q22
     165           0 :         Word32 tmp3 = L_shl( L_add( tmp1, tmp2 ), 1 );                                    // Q22
     166             : 
     167           0 :         Word32 tmp4 = W_extract_l( W_shr( W_mult0_32_32( quat.x_fx, quat.x_fx ), Q22 ) ); // Q22
     168           0 :         Word32 tmp5 = W_extract_l( W_shr( W_mult0_32_32( quat.y_fx, quat.y_fx ), Q22 ) ); // Q22
     169           0 :         Word32 tmp6 = L_shl( L_add( tmp4, tmp5 ), 1 );
     170           0 :         Word32 tmp7 = L_sub( ONE_IN_Q22, tmp6 );
     171             : 
     172           0 :         IF( tmp3 >= -2 && tmp3 <= 2 )
     173             :         {
     174           0 :             tmp3 = 0;
     175             :         }
     176           0 :         IF( tmp7 >= -2 && tmp7 <= 2 )
     177             :         {
     178           0 :             tmp7 = 0;
     179             :         }
     180             : 
     181           0 :         Word16 yaw_fx_16 = BASOP_util_atan2( tmp3, tmp7, 0 ); // Q13
     182           0 :         *yaw_fx = Mpy_32_16_1( 961263669 /*_180_OVER_PI in Q24*/, yaw_fx_16 );
     183             : 
     184             :         Word32 p_fx;
     185           0 :         Word32 tmp8 = W_extract_l( W_shr( W_mult0_32_32( quat.w_fx, quat.y_fx ), Q22 ) ); // Q22
     186           0 :         Word32 tmp9 = W_extract_l( W_shr( W_mult0_32_32( quat.z_fx, quat.x_fx ), Q22 ) ); // Q22
     187           0 :         p_fx = L_shl( L_sub( tmp8, tmp9 ), 1 );
     188           0 :         p_fx = max( L_negate( ONE_IN_Q22 ), min( ONE_IN_Q22, p_fx ) ); // Q22
     189             : 
     190           0 :         Word32 p_fx_sq = W_extract_l( W_shr( W_mult0_32_32( p_fx, p_fx ), Q22 ) );
     191           0 :         Word16 res_exp = 0;
     192           0 :         Word32 one_minus_p_fx_sq = BASOP_Util_Add_Mant32Exp( ONE_IN_Q30, 1, L_negate( p_fx_sq ), 31 - Q22, &res_exp );
     193           0 :         Word32 sqrt_one_minus_p_fx_sq = Sqrt32( one_minus_p_fx_sq, &res_exp );
     194             : 
     195           0 :         Word16 pitch_fx_16 = BASOP_util_atan2( p_fx, sqrt_one_minus_p_fx_sq, ( 31 - Q22 ) - res_exp );
     196             : 
     197           0 :         *pitch_fx = Mpy_32_16_1( 961263669 /*_180_OVER_PI in Q24*/, pitch_fx_16 );
     198             : 
     199           0 :         Word32 tmp10 = W_extract_l( W_shr( W_mult0_32_32( quat.w_fx, quat.z_fx ), Q22 ) ); // Q22
     200           0 :         Word32 tmp11 = W_extract_l( W_shr( W_mult0_32_32( quat.x_fx, quat.y_fx ), Q22 ) ); // Q22
     201           0 :         Word32 tmp12 = L_shl( L_add( tmp10, tmp11 ), 1 );                                  // Q22
     202             : 
     203           0 :         Word32 tmp13 = W_extract_l( W_shr( W_mult0_32_32( quat.y_fx, quat.y_fx ), Q22 ) ); // Q22
     204           0 :         Word32 tmp14 = W_extract_l( W_shr( W_mult0_32_32( quat.z_fx, quat.z_fx ), Q22 ) ); // Q22
     205           0 :         Word32 tmp15 = L_shl( L_add( tmp13, tmp14 ), 1 );                                  // Q22
     206           0 :         Word32 tmp16 = L_sub( ONE_IN_Q22, tmp15 );                                         // Q22
     207             : 
     208           0 :         IF( tmp12 >= -2 && tmp12 <= 2 )
     209             :         {
     210           0 :             tmp12 = 0;
     211             :         }
     212           0 :         IF( tmp16 >= -2 && tmp16 <= 2 )
     213             :         {
     214           0 :             tmp16 = 0;
     215             :         }
     216           0 :         Word16 roll_fx_16 = BASOP_util_atan2( tmp12, tmp16, 0 ); // Q13
     217           0 :         *roll_fx = Mpy_32_16_1( 961263669 /*_180_OVER_PI in Q24*/, roll_fx_16 );
     218             :     }
     219             :     ELSE
     220             :     {
     221             :         /* Euler angles in R_X(roll)*R_Y(pitch)*R_Z(yaw) convention
     222             :          *
     223             :          *  yaw:   rotate scene counter-clockwise in the horizontal plane
     224             :          *  pitch: rotate scene in the median plane, increase elevation with positive values
     225             :          *  roll:  rotate scene from the right ear to the top
     226             :          */
     227           0 :         *yaw_fx = quat.z_fx;
     228           0 :         *pitch_fx = quat.y_fx;
     229           0 :         *roll_fx = quat.x_fx;
     230             :     }
     231             : 
     232           0 :     return;
     233             : }
     234             : 
     235             : 
     236             : /*-------------------------------------------------------------------------
     237             :  * deg2rad()
     238             :  *
     239             :  * Converts degrees to normalized radians
     240             :  *------------------------------------------------------------------------*/
     241         456 : Word32 deg2rad_fx(
     242             :     Word32 degrees // Q22
     243             : )
     244             : {
     245         456 :     WHILE( GE_32( degrees, DEGREE_180 ) )
     246             :     {
     247           0 :         degrees = L_sub( degrees, DEGREE_360 );
     248             :     }
     249         456 :     WHILE( LE_32( degrees, -DEGREE_180 ) )
     250             :     {
     251           0 :         degrees = L_add( degrees, DEGREE_360 );
     252             :     }
     253             : 
     254         456 :     return Mpy_32_32( PI_OVER_180_FX, degrees ); // Q22
     255             : }
     256             : 
     257           0 : float deg2rad(
     258             :     float degrees )
     259             : {
     260           0 :     while ( degrees >= 180.0f )
     261             :     {
     262           0 :         degrees = degrees - 360.0f;
     263             :     }
     264           0 :     while ( degrees <= -180.0f )
     265             :     {
     266           0 :         degrees = degrees + 360.0f;
     267             :     }
     268             : 
     269           0 :     return PI_OVER_180 * degrees;
     270             : }

Generated by: LCOV version 1.14