LCOV - code coverage report
Current view: top level - lib_com - ivas_qspherical_com.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 102 117 87.2 %
Date: 2025-05-23 08:37:30 Functions: 10 10 100.0 %

          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 <assert.h>
      34             : #include <stdint.h>
      35             : #include "options.h"
      36             : #include <math.h>
      37             : #include "ivas_cnst.h"
      38             : #include "ivas_rom_com.h"
      39             : #include "ivas_prot.h"
      40             : #include "prot.h"
      41             : #include "cnst.h"
      42             : #include "wmc_auto.h"
      43             : 
      44             : 
      45             : /*-------------------------------------------------------------------------
      46             :  * ivas_qmetadata_reorder_generic()
      47             :  *
      48             :  *------------------------------------------------------------------------*/
      49             : 
      50    22074223 : uint16_t ivas_qmetadata_reorder_generic(
      51             :     const int16_t signed_value )
      52             : {
      53             :     uint16_t unsigned_value;
      54             : 
      55    22074223 :     if ( signed_value < 0 )
      56             :     {
      57     8863650 :         unsigned_value = ( ( uint16_t ) - ( signed_value + 1 ) << 1 ) + 1;
      58             :     }
      59             :     else
      60             :     {
      61    13210573 :         unsigned_value = (uint16_t) signed_value << 1;
      62             :     }
      63             : 
      64    22074223 :     return unsigned_value;
      65             : }
      66             : 
      67             : 
      68             : /*-------------------------------------------------------------------------
      69             :  * ivas_qmetadata_dereorder_generic()
      70             :  *
      71             :  * Returns the original value of the array "folded" by ReorderGeneric
      72             :  *------------------------------------------------------------------------*/
      73             : 
      74             : /*! r: "Unfolded" value, positive or negative depending on the value of the input */
      75    20850591 : int16_t ivas_qmetadata_dereorder_generic(
      76             :     const uint16_t uns_value /* i  : unsigned value result of ReorderGeneric                                     */
      77             : )
      78             : {
      79    20850591 :     if ( ( uns_value & 1 ) != 0 )
      80             :     {
      81     8388803 :         return -(int16_t) ( uns_value >> 1 ) - 1;
      82             :     }
      83             :     else
      84             :     {
      85    12461788 :         return (int16_t) ( uns_value >> 1 );
      86             :     }
      87             : }
      88             : 
      89             : 
      90             : /*-------------------------------------------------------------------------
      91             :  * ivas_dirac_project_elevation_index()
      92             :  *
      93             :  *
      94             :  *------------------------------------------------------------------------*/
      95             : 
      96             : /*! r: projected elevation index */
      97    11907774 : int16_t ivas_dirac_project_elevation_index(
      98             :     const int16_t el_idx,      /* i  : elevation index                         */
      99             :     const int16_t el_alph,     /* i  : number of elevation symbols             */
     100             :     const int16_t el_alph_proj /* i  : size of projected alphabet              */
     101             : )
     102             : {
     103             :     int16_t el_idx_proj;
     104             : #ifdef DEBUGGING
     105             :     assert( ( el_idx >= 0 ) && ( el_idx < el_alph ) );
     106             :     assert( el_alph == 2 * ( el_alph >> 1 ) + 1 ); /* el_alph of the form 2 * n_points + 1 */
     107             :     assert( el_alph_proj == 2 * ( el_alph_proj >> 1 ) + 1 );
     108             : #endif
     109             : 
     110             :     /* evaluate floor((el_idx / (el_alph - 1)) * (el_alph_proj - 1) + 0.5) using only integer */
     111    11907774 :     el_idx_proj = ( 2 * el_idx * ( el_alph_proj - 1 ) + ( el_alph - 1 ) ) / ( 2 * ( el_alph - 1 ) );
     112             : 
     113             : #ifdef DEBUGGING
     114             :     assert( ( 0 <= el_idx_proj ) && ( el_idx_proj < el_alph_proj ) );
     115             : #endif
     116    11907774 :     return el_idx_proj;
     117             : }
     118             : 
     119             : 
     120             : /*-------------------------------------------------------------------------
     121             :  * ivas_chan_project_elevation_index()
     122             :  *
     123             :  *
     124             :  *------------------------------------------------------------------------*/
     125             : 
     126             : /*! r: projected index in channel mode */
     127      104289 : int16_t ivas_chan_project_elevation_index(
     128             :     const int16_t el_idx,      /* i  : elevation index                 */
     129             :     const int16_t el_alph,     /* i  : number of elevation symbols     */
     130             :     const int16_t el_alph_proj /* i  : size of projected alphabet      */
     131             : )
     132             : {
     133             :     int16_t el_idx_proj;
     134             : #ifdef DEBUGGING
     135             :     assert( ( el_idx >= 0 ) && ( el_idx < el_alph ) );
     136             : #endif
     137             : 
     138             :     /* evaluate floor((el_idx / (el_alph - 1)) * (el_alph_proj - 1) + 0.5) using only integer */
     139      104289 :     if ( el_idx == el_alph - 1 )
     140             :     {
     141        9168 :         el_idx_proj = el_alph_proj - 1;
     142             :     }
     143             :     else
     144             :     {
     145       95121 :         el_idx_proj = ( 2 * el_idx * el_alph_proj + el_alph ) / ( 2 * el_alph );
     146             :     }
     147             : 
     148             : #ifdef DEBUGGING
     149             :     assert( ( 0 <= el_idx_proj ) && ( el_idx_proj < el_alph_proj ) );
     150             : #endif
     151      104289 :     return el_idx_proj;
     152             : }
     153             : 
     154             : 
     155             : /*-------------------------------------------------------------------------
     156             :  * ivas_dirac_project_azimuth_index()
     157             :  *
     158             :  *
     159             :  *------------------------------------------------------------------------*/
     160             : 
     161             : /*! r: projected azimuth index */
     162    14113794 : int16_t ivas_dirac_project_azimuth_index(
     163             :     const int16_t az_idx,      /* i  : azimuth index                           */
     164             :     const int16_t az_alph,     /* i  : number of azimuth symbols               */
     165             :     const int16_t az_alph_proj /* i  : size of projected alphabet              */
     166             : )
     167             : {
     168             :     int16_t az_idx_proj;
     169             : #ifdef DEBUGGING
     170             :     assert( ( az_idx >= 0 ) && ( az_idx < az_alph ) );
     171             : #endif
     172             : 
     173    14113794 :     if ( az_alph_proj == 1 )
     174             :     {
     175        6114 :         return 0;
     176             :     }
     177             : 
     178             :     /* evaluate floor((az_idx / az_alph) * az_alph_proj + 0.5) using only integer */
     179    14107680 :     az_idx_proj = ( 2 * az_idx * az_alph_proj + az_alph ) / ( 2 * az_alph );
     180             : 
     181    14107680 :     if ( az_idx_proj == az_alph_proj )
     182             :     {
     183      274135 :         az_idx_proj = 0;
     184             :     }
     185             : 
     186             : #ifdef DEBUGGING
     187             :     assert( ( 0 <= az_idx_proj ) && ( az_idx_proj < az_alph_proj ) );
     188             : #endif
     189    14107680 :     return az_idx_proj;
     190             : }
     191             : 
     192             : 
     193             : /*-------------------------------------------------------------------------
     194             :  * small_reduction_direction()
     195             :  *
     196             :  * Compute the allocated bit reduction in spherical indexing for bit budget
     197             :  * is exceeded by diff. bits
     198             :  *------------------------------------------------------------------------*/
     199             : 
     200       12046 : void small_reduction_direction(
     201             :     IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure   */
     202             :     uint16_t bits_dir[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES],
     203             :     const int16_t raw_flag[MASA_MAXIMUM_CODING_SUBBANDS],
     204             :     int16_t *diff )
     205             : {
     206             :     int16_t i, j, k;
     207             : 
     208       29766 :     for ( k = 0; ( k < 2 ) && ( *diff > 0 ); k++ )
     209             :     {
     210       83724 :         for ( i = q_direction->cfg.start_band; ( i < q_direction->cfg.nbands ) && ( *diff > 0 ); i++ )
     211             :         {
     212       66004 :             if ( raw_flag[i] == 1 )
     213             :             {
     214      168744 :                 for ( j = 0; ( j < q_direction->cfg.nblocks ) && ( *diff > 0 ); j++ )
     215             :                 {
     216      133777 :                     if ( bits_dir[i][j] > MASA_MIN_BITS_TF )
     217             :                     {
     218       90205 :                         bits_dir[i][j] -= 1;
     219       90205 :                         ( *diff )--;
     220             :                     }
     221             :                 }
     222             :             }
     223             :         }
     224             :     }
     225             : 
     226       12046 :     return;
     227             : }
     228             : 
     229             : 
     230             : /*-----------------------------------------------------------------------*
     231             :  * quantize_phi()
     232             :  *
     233             :  * Quantize azimuth.
     234             :  * Input phi expected to be an angle in degree between 0 and 360.
     235             :  *-----------------------------------------------------------------------*/
     236             : 
     237             : /*! r: index azimuth */
     238     6640316 : int16_t quantize_phi(
     239             :     float phi,                /* i  : azimuth value                                                 */
     240             :     const int16_t flag_delta, /* i  : flag indicating if the azimuth codebook is translated or not  */
     241             :     float *phi_hat,           /* o  : quantized azimuth                                             */
     242             :     const int16_t n           /* i  : azimuth codebook size                                         */
     243             : )
     244             : {
     245             :     int16_t id_phi;
     246             :     float dd;
     247             :     float delta_phi;
     248             : 
     249             : #ifdef DEBUGGING
     250             :     assert( ( phi >= 0.f ) && ( phi <= 360.f ) );
     251             : #endif
     252             : 
     253     6640316 :     delta_phi = 360.0f / (float) n;
     254             : 
     255     6640316 :     if ( n == 1 )
     256             :     {
     257           0 :         *phi_hat = 0;
     258             : 
     259           0 :         return 0;
     260             :     }
     261             : 
     262     6640316 :     if ( ( flag_delta == 1 ) && ( n > 2 ) )
     263             :     {
     264     1563509 :         dd = delta_phi / 2.0f;
     265             :     }
     266             :     else
     267             :     {
     268     5076807 :         dd = 0;
     269             :     }
     270     6640316 :     id_phi = (int16_t) round_f( ( ( phi - 180 - dd ) / (float) delta_phi ) );
     271     6640316 :     assert( fabsf( ( phi - 180 - dd ) / (float) delta_phi ) - abs( id_phi ) <= 0.5 );
     272             : 
     273     6640316 :     if ( id_phi + ( n >> 1 ) < 0 )
     274             :     {
     275       29147 :         id_phi += 1;
     276             :     }
     277             : 
     278     6640316 :     if ( id_phi - ( n >> 1 ) >= 0 )
     279             :     {
     280      512963 :         id_phi = -( n >> 1 );
     281             :     }
     282             : 
     283     6640316 :     if ( id_phi == -( ( n >> 1 ) + ( n % 2 ) ) )
     284             :     {
     285      869065 :         id_phi += ( n % 2 );
     286             :     }
     287             :     else
     288             :     {
     289     5771251 :         if ( id_phi == ( ( n >> 1 ) + ( n % 2 ) ) )
     290             :         {
     291           0 :             if ( n % 2 )
     292             :             {
     293           0 :                 id_phi -= 1;
     294             :             }
     295             :             else
     296             :             {
     297           0 :                 id_phi = -id_phi;
     298             :             }
     299             :         }
     300             :     }
     301             : 
     302     6640316 :     *phi_hat = id_phi * delta_phi + dd + 180;
     303             : 
     304     6640316 :     id_phi += ( n >> 1 );
     305             : 
     306     6640316 :     return id_phi;
     307             : }
     308             : 
     309             : 
     310             : /*-----------------------------------------------------------------------*
     311             :  * companding_azimuth()
     312             :  *
     313             :  * Compand azimuth based on the format
     314             :  *-----------------------------------------------------------------------*/
     315             : 
     316             : /*! r: companded azimuth value */
     317      557543 : float companding_azimuth(
     318             :     const float azi,             /* i  : input azimuth value                        */
     319             :     const MC_LS_SETUP mc_format, /* i  : input channel format                       */
     320             :     const int16_t theta_flag,    /* i  : zero/non zero elevation flag               */
     321             :     const int16_t direction      /* i  : direction of companding (direct or inverse)*/
     322             : )
     323             : {
     324      557543 :     const float pointsA[] = { 0.0f, 60.0f, 110.0f, 150.0f, 180.0f, 0.0f, 50.0f, 90.0f, 150.0f, 180.0f, 0.0f, 30.0f, 80.0f, 150.0f, 180.0f };
     325      557543 :     const float pointsB[] = { 0.0f, 90.0f, 110.0f, 170.0f, 180.0f, 0.0f, 90.0f, 110.0f, 170.0f, 180.0f, 0.0f, 10.0f, 100.0f, 170.0f, 180.0f };
     326             :     const float *pA, *pB;
     327             :     int16_t no_points;
     328             :     float comp_azi;
     329             :     int16_t i, not_done, start;
     330             :     float abs_azi;
     331             : 
     332      557543 :     if ( mc_format == MC_LS_SETUP_5_1 || mc_format == MC_LS_SETUP_5_1_2 || mc_format == MC_LS_SETUP_5_1_4 ) /* 5.1, 5.1+2 or 5.1+4*/
     333             :     {
     334      454733 :         start = 5;
     335             :     }
     336             :     else
     337             :     {
     338      102810 :         start = 0;
     339             :     }
     340             : 
     341             :     /* theta flag 1 is for non zero, larger than a threshold elevation */
     342      557543 :     if ( ( theta_flag == 1 ) && ( ( mc_format == MC_LS_SETUP_5_1_2 ) || ( mc_format == MC_LS_SETUP_5_1_4 ) || ( mc_format == MC_LS_SETUP_7_1_4 ) ) ) /* 5.1+2, 5.1+4 or 7.1+4*/
     343             :     {
     344       46747 :         start = 10;
     345             :     }
     346      557543 :     no_points = 5;
     347             : 
     348      557543 :     pA = &pointsA[start];
     349      557543 :     pB = &pointsB[start];
     350             : 
     351      557543 :     if ( direction == -1 ) /* inverse companding */
     352             :     {
     353      438379 :         pA = &pointsB[start];
     354      438379 :         pB = &pointsA[start];
     355             :     }
     356             :     else
     357             :     {
     358      119164 :         if ( direction != 1 )
     359             :         {
     360           0 :             printf( "Wrong direction in companding" );
     361             :         }
     362             :     }
     363             : 
     364      557543 :     not_done = 1;
     365      557543 :     abs_azi = fabsf( azi );
     366             : 
     367      557543 :     comp_azi = azi;
     368      557543 :     i = 0;
     369     1217152 :     while ( not_done && ( i < no_points - 1 ) )
     370             :     {
     371      659609 :         if ( abs_azi <= pA[i + 1] )
     372             :         {
     373      557543 :             not_done = 0;
     374             :             /* calculate companding */
     375      557543 :             comp_azi = pB[i] + ( pB[i + 1] - pB[i] ) / ( pA[i + 1] - pA[i] ) * ( abs_azi - pA[i] );
     376             :         }
     377             :         else
     378             :         {
     379      102066 :             i++;
     380             :         }
     381             :     }
     382             : 
     383      557543 :     if ( azi < 0 )
     384             :     {
     385      236347 :         comp_azi = -comp_azi;
     386             :     }
     387             : 
     388      557543 :     if ( not_done == 1 )
     389             :     {
     390           0 :         comp_azi = azi;
     391             :     }
     392             : 
     393      557543 :     return comp_azi;
     394             : }
     395             : 
     396             : 
     397             : /*-----------------------------------------------------------------------*
     398             :  * quantize_phi_chan_lbr()
     399             :  *
     400             :  * Quantize azimuth in low-bitrate channel mode.
     401             :  * Input phi expected to be an angle in degree between 0 and 360.
     402             :  *-----------------------------------------------------------------------*/
     403             : 
     404             : /*! r: index azimuth */
     405        2284 : int16_t quantize_phi_chan_lbr(
     406             :     const float phi, /* i  : azimuth value                    */
     407             :     float *phi_hat,  /* o  : quantized azimuth                */
     408             :     const int16_t n  /* i  : azimuth codebook size            */
     409             : )
     410             : {
     411             :     int16_t id_phi;
     412             : 
     413             : #ifdef DEBUGGING
     414             :     assert( ( phi >= -180.f ) && ( phi <= 180.f ) );
     415             :     assert( n <= 9 );
     416             : #endif
     417             : 
     418        2284 :     if ( n <= 1 )
     419             :     {
     420           0 :         *phi_hat = 0;
     421             : 
     422           0 :         return 0;
     423             :     }
     424             : 
     425        2284 :     id_phi = squant( fabsf( phi ), phi_hat, cb_azi_chan, n >> 1 );
     426             : 
     427        2284 :     if ( phi < 0 && id_phi > 0 )
     428             :     {
     429         909 :         id_phi = 2 * id_phi - 1;
     430         909 :         *phi_hat = -*phi_hat;
     431             :     }
     432             :     else
     433             :     {
     434        1375 :         id_phi *= 2;
     435             :     }
     436             : 
     437        2284 :     return id_phi;
     438             : }
     439             : 
     440             : 
     441             : /*-----------------------------------------------------------------------*
     442             :  * quantize_phi_chan_compand()
     443             :  *
     444             :  * Quantize azimuth.
     445             :  * Input phi expected to be an angle in degree between 0 and 360.
     446             :  *-----------------------------------------------------------------------*/
     447             : 
     448             : /*! r: index azimuth */
     449      119164 : int16_t quantize_phi_chan_compand(
     450             :     float phi,                  /* i  : azimuth value                    */
     451             :     float *phi_hat,             /* o  : quantized azimuth                */
     452             :     const int16_t n,            /* i  : azimuth codebook size            */
     453             :     const int16_t theta_flag,   /* i  : flag signaling high elevation    */
     454             :     const MC_LS_SETUP mc_format /* i  : channel format if in MC-mode     */
     455             : )
     456             : {
     457             :     int16_t id_phi;
     458             :     float delta_phi;
     459             : 
     460             : #ifdef DEBUGGING
     461             :     assert( ( phi >= 0.f ) && ( phi <= 360.f ) );
     462             : #endif
     463             : 
     464      119164 :     if ( n <= 1 )
     465             :     {
     466           0 :         *phi_hat = 0;
     467             : 
     468           0 :         return 0;
     469             :     }
     470             : 
     471      119164 :     phi = companding_azimuth( phi - 180, mc_format, theta_flag, 1 );
     472             : 
     473             :     /* quantize companded value */
     474      119164 :     delta_phi = 360.0f / (float) n;
     475      119164 :     id_phi = (int16_t) round_f( ( phi / (float) delta_phi ) );
     476             : 
     477      119164 :     if ( id_phi + ( n >> 1 ) < 0 )
     478             :     {
     479           0 :         id_phi += 1;
     480             :     }
     481      119164 :     if ( id_phi - ( n >> 1 ) >= 0 )
     482             :     {
     483         775 :         id_phi = -( n >> 1 );
     484             :     }
     485             : 
     486      119164 :     if ( id_phi == -( ( n >> 1 ) + ( n % 2 ) ) )
     487             :     {
     488         919 :         id_phi += ( n % 2 );
     489             :     }
     490             :     else
     491             :     {
     492      118245 :         if ( id_phi == ( ( n >> 1 ) + ( n % 2 ) ) )
     493             :         {
     494           0 :             if ( n % 2 )
     495             :             {
     496           0 :                 id_phi -= 1;
     497             :             }
     498             :             else
     499             :             {
     500           0 :                 id_phi = -id_phi;
     501             :             }
     502             :         }
     503             :     }
     504      119164 :     *phi_hat = id_phi * delta_phi;
     505             : 
     506      119164 :     id_phi += ( n >> 1 );
     507             : 
     508             : 
     509      119164 :     *phi_hat = companding_azimuth( *phi_hat, mc_format, theta_flag, -1 ) + 180;
     510             : 
     511      119164 :     return id_phi;
     512             : }

Generated by: LCOV version 1.14