LCOV - code coverage report
Current view: top level - lib_com - re8_util.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 93 93 100.0 %
Date: 2025-05-23 08:37:30 Functions: 4 4 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             : /*====================================================================================
      34             :     EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
      35             :   ====================================================================================*/
      36             : 
      37             : #include <stdint.h>
      38             : #include "options.h"
      39             : #ifdef DEBUGGING
      40             : #include "debug.h"
      41             : #endif
      42             : #include <math.h> /* for ldexp() */
      43             : #include "cnst.h"
      44             : #include "rom_com.h"
      45             : #include "prot.h"
      46             : #include "wmc_auto.h"
      47             : 
      48             : 
      49             : /*-------------------------------------------------------------------*
      50             :  * Local function prototypes
      51             :  *-------------------------------------------------------------------*/
      52             : 
      53             : static int16_t re8_identify_absolute_leader( const int16_t y[] );
      54             : 
      55             : static void re8_coord( const int16_t y[], int16_t k[] );
      56             : 
      57             : 
      58             : /*----------------------------------------------------------------*
      59             :  * re8_vor()
      60             :  *
      61             :  * Multi-rate RE8 indexing by Voronoi extension
      62             :  *----------------------------------------------------------------*/
      63             : 
      64     1960406 : void re8_vor(
      65             :     int16_t y[], /* i  : point in RE8 (8-dimensional integer vector)      */
      66             :     int16_t *n,  /* o  : codebook number n=0,2,3,4,... (scalar integer)   */
      67             :     int16_t k[], /* o  : Voronoi index (integer vector of dimension 8) used only if n>4 */
      68             :     int16_t c[], /* o  : codevector in Q0, Q2, Q3, or Q4 if n<=4, y=c     */
      69             :     int16_t *ka  /* o  : identifier of absolute leader (needed to index c)*/
      70             : )
      71             : {
      72             :     int16_t v[8];
      73             :     int16_t k_mod[8], c_tmp[8];
      74             :     int16_t i, r, m, k_tmp[8], iter, ka_tmp, n_tmp, mask;
      75             :     float sphere;
      76             : 
      77             :     /*----------------------------------------------------------------*
      78             :      * verify if y is in Q0, Q2, Q3 or Q4
      79             :      *   (a fast search is used here:
      80             :      *    the codebooks Q0, Q2, Q3 or Q4 are specified in terms of RE8 absolute leaders
      81             :      *    (see FORinstance Xie and Adoul's paper in ICASSP 96)
      82             :      *    - a unique code identifying the absolute leader related to y is computed
      83             :      *      in re8_identify_absolute_leader()
      84             :      *      this code is searched FORin a pre-defined list which specifies Q0, Q2, Q3 or Q4)
      85             :      *      the absolute leader is identified by ka
      86             :      *    - a translation table maps ka to the codebook number n)
      87             :      *----------------------------------------------------------------*/
      88             : 
      89     1960406 :     *ka = re8_identify_absolute_leader( y );
      90             : 
      91             :     /*----------------------------------------------------------------*
      92             :      * compute codebook number n of Qn (by table look-up)
      93             :      *   at this stage, n=0,2,3,4 or out=100
      94             :      *----------------------------------------------------------------*/
      95             : 
      96     1960406 :     *n = Da_nq[*ka];
      97             : 
      98             :     /*----------------------------------------------------------------*
      99             :      * decompose y into :
     100             :      *     (if n<=4:)
     101             :      *     y = c        where c is in Q0, Q2, Q3 or Q4
     102             :      *   or
     103             :      *     (if n>4:)
     104             :      *     y = m c + v  where c is in Q3 or Q4, v is a Voronoi codevector
     105             :      *                        m=2^r (r integer >=2)
     106             :      *
     107             :      *   in the latter case (if n>4), as a side-product, compute the (Voronoi) index k[] of v
     108             :      *   and replace n by n = n' + 2r where n' = 3 or 4 (c is in Qn') and r is defined above
     109             :      *----------------------------------------------------------------*/
     110             : 
     111     1960406 :     if ( *n <= 4 )
     112             :     {
     113    16771689 :         for ( i = 0; i < 8; i++ )
     114             :         {
     115    14908168 :             c[i] = y[i];
     116             :         }
     117             :     }
     118             :     else
     119             :     {
     120             :         /*------------------------------------------------------------*
     121             :          * initialize r and m=2^r based on || y ||^2/8
     122             :          *------------------------------------------------------------*/
     123             : 
     124       96885 :         sphere = 0.0;
     125      871965 :         for ( i = 0; i < 8; i++ )
     126             :         {
     127      775080 :             sphere += (float) y[i] * (float) y[i];
     128             :         }
     129       96885 :         sphere *= 0.125;
     130       96885 :         r = 1;
     131       96885 :         sphere *= 0.25; /* not counted, merge 0.125*0.25 */
     132       97282 :         while ( sphere > 11.0 )
     133             :         {
     134         397 :             r++;
     135         397 :             sphere *= 0.25;
     136             :         }
     137             :         /*------------------------------------------------------------*
     138             :          * compute the coordinates of y in the RE8 basis
     139             :          *------------------------------------------------------------*/
     140             : 
     141       96885 :         re8_coord( y, k_mod );
     142             : 
     143             :         /*------------------------------------------------------------*
     144             :          * compute m and the mask needed for modulo m (for Voronoi coding)
     145             :          *------------------------------------------------------------*/
     146             : 
     147       96885 :         m = 1 << r;
     148       96885 :         mask = m - 1; /* 0x0..011...1 */
     149             : 
     150             :         /*------------------------------------------------------------*
     151             :          * find the minimal value of r (or equivalently of m) in 2 iterations
     152             :          *------------------------------------------------------------*/
     153             : 
     154      290655 :         for ( iter = 0; iter < 2; iter++ )
     155             :         {
     156             :             /*--------------------------------------------------------*
     157             :              * compute v such that y is in m RE_8 +v (by Voronoi coding)
     158             :              *--------------------------------------------------------*/
     159             : 
     160     1743930 :             for ( i = 0; i < 8; i++ )
     161             :             {
     162     1550160 :                 k_tmp[i] = k_mod[i] & mask;
     163             :             }
     164             : 
     165      193770 :             re8_k2y( k_tmp, m, v );
     166             : 
     167             :             /*--------------------------------------------------------*
     168             :              * compute c = (y-v)/m
     169             :              * (y is in RE8, c is also in RE8 by definition of v)
     170             :              *--------------------------------------------------------*/
     171             : 
     172     1743930 :             for ( i = 0; i < 8; i++ )
     173             :             {
     174     1550160 :                 c_tmp[i] = ( y[i] - v[i] ) / m;
     175             :                 /* M IS A FACTOR OF 2 */
     176             :             }
     177             : 
     178             :             /*--------------------------------------------------------*
     179             :              *  verify if c_tmp is in Q2, Q3 or Q4
     180             :              *--------------------------------------------------------*/
     181             : 
     182      193770 :             ka_tmp = re8_identify_absolute_leader( c_tmp );
     183             : 
     184             :             /*--------------------------------------------------------*
     185             :              * at this stage, n_tmp=2,3,4 or out = 100 -- n=0 is not possible
     186             :              *--------------------------------------------------------*/
     187             : 
     188      193770 :             n_tmp = Da_nq[ka_tmp];
     189             : 
     190      193770 :             if ( n_tmp > 4 )
     191             :             {
     192             :                 /*--------------------------------------------------------*
     193             :                  * if c is not in Q2, Q3, or Q4 (i.e. n_tmp>4), use m = 2^(r+1) instead of 2^r
     194             :                  *--------------------------------------------------------*/
     195             : 
     196       96883 :                 r++;
     197       96883 :                 m = m << 1;
     198       96883 :                 mask = ( ( mask << 1 ) + 1 ); /* mask = m-1; <- this is less complex */
     199             :             }
     200             :             else
     201             :             {
     202             :                 /*--------------------------------------------------------*
     203             :                  * c is in Q2, Q3, or Q4 -> the decomposition of y as y = m c + v is valid
     204             :                  *
     205             :                  * since Q2 is a subset of Q3, indicate n=3 instead of n=2 (this is because
     206             :                  * for n>4, n=n'+2r with n'=3 or 4, so n'=2 is not valid)
     207             :                  *--------------------------------------------------------*/
     208             : 
     209       96887 :                 if ( n_tmp < 3 )
     210             :                 {
     211        9886 :                     n_tmp = 3;
     212             :                 }
     213             : 
     214             :                 /*--------------------------------------------------------*
     215             :                  * save current values into ka, n, k and c
     216             :                  *--------------------------------------------------------*/
     217             : 
     218       96887 :                 *ka = ka_tmp;
     219       96887 :                 *n = n_tmp + 2 * r;
     220      871983 :                 for ( i = 0; i < 8; i++ )
     221             :                 {
     222      775096 :                     k[i] = k_tmp[i];
     223      775096 :                     c[i] = c_tmp[i];
     224             :                 }
     225             : 
     226             :                 /*--------------------------------------------------------*
     227             :                  * try  m = 2^(r-1) instead of 2^r to be sure that m is minimal
     228             :                  *--------------------------------------------------------*/
     229             : 
     230       96887 :                 r--;
     231       96887 :                 m = m >> 1;
     232       96887 :                 mask = mask >> 1;
     233             :             }
     234             :         }
     235             :     }
     236             : 
     237     1960406 :     return;
     238             : }
     239             : 
     240             : /*-----------------------------------------------------------------------*
     241             :  * re8_identify_absolute_leader()
     242             :  *
     243             :  * Identify the absolute leader related to y using a pre-defined table which
     244             :  * specifies the codebooks Q0, Q2, Q3 and Q4
     245             :  -----------------------------------------------------------------------*/
     246             : 
     247             : /*! r: integer indicating if y if in Q0, Q2, Q3 or Q4 (or if y is an outlier) */
     248     2154176 : static int16_t re8_identify_absolute_leader(
     249             :     const int16_t y[] /* i  : point in RE8 (8-dimensional integer vector)                              */
     250             : )
     251             : {
     252             :     int16_t i, id, nb, pos, ka;
     253             :     int32_t s, C[8], tmp;
     254             : 
     255             :     /*-----------------------------------------------------------------------*
     256             :      * compute the RE8 shell number s = (y1^2+...+y8^2)/8 and C=(y1^2, ..., y8^2)
     257             :      *-----------------------------------------------------------------------*/
     258             : 
     259     2154176 :     s = 0;
     260    19387584 :     for ( i = 0; i < 8; i++ )
     261             :     {
     262    17233408 :         C[i] = y[i] * y[i];
     263    17233408 :         s += C[i];
     264             :     }
     265     2154176 :     s >>= 3;
     266             : 
     267             :     /*-----------------------------------------------------------------------*
     268             :      * compute the index 0 <= ka <= NB_LEADER+1 which identifies an absolute leader of Q0, Q2, Q3 or Q4
     269             :      *
     270             :      * by default, ka=index of last element of the table (to indicate an outlier)
     271             :      *-----------------------------------------------------------------------*/
     272             : 
     273     2154176 :     ka = NB_LEADER + 1;
     274     2154176 :     if ( s == 0 )
     275             :     {
     276             :         /*-------------------------------------------------------------------*
     277             :          * if s=0, y=0 i.e. y is in Q0 -> ka=index of element indicating Q0
     278             :          *-------------------------------------------------------------------*/
     279             : 
     280      212396 :         ka = NB_LEADER;
     281             :     }
     282             :     else
     283             :     {
     284             :         /*-------------------------------------------------------------------*
     285             :          * the maximal value of s for y in  Q0, Q2, Q3 or Q4 is NB_SPHERE
     286             :          *   if s> NB_SPHERE, y is an outlier (the value of ka is set correctly)
     287             :          *-------------------------------------------------------------------*/
     288             : 
     289     1941780 :         if ( s <= NB_SPHERE )
     290             :         {
     291             :             /*---------------------------------------------------------------*
     292             :              * compute the unique identifier id of the absolute leader related to y:
     293             :              * s = (y1^4 + ... + y8^4)/8
     294             :              *---------------------------------------------------------------*/
     295             : 
     296     1941135 :             tmp = 0;
     297    17470215 :             for ( i = 0; i < 8; i++ )
     298             :             {
     299    15529080 :                 tmp += C[i] * C[i];
     300             :             }
     301     1941135 :             id = (int16_t) ( tmp >> 3 );
     302             : 
     303             :             /*---------------------------------------------------------------*
     304             :              * search for id in table Da_id
     305             :              * (containing all possible values of id if y is in Q2, Q3 or Q4)
     306             :              * this search is focused based on the shell number s so that
     307             :              * only the id's related to the shell of number s are checked
     308             :              *---------------------------------------------------------------*/
     309             : 
     310     1941135 :             nb = Da_nb[s - 1];   /* get the number of absolute leaders used on the shell of number s */
     311     1941135 :             pos = Da_pos[s - 1]; /* get the position of the first absolute leader of shell s in Da_id */
     312     3378912 :             for ( i = 0; i < nb; i++ )
     313             :             {
     314     3185789 :                 if ( id == Da_id[pos] )
     315             :                 {
     316     1748012 :                     ka = pos; /* get ka */
     317     1748012 :                     break;
     318             :                 }
     319     1437777 :                 pos++;
     320             :             }
     321             :         }
     322             :     }
     323             : 
     324     2154176 :     return ( ka );
     325             : }
     326             : 
     327             : /*-------------------------------------------------------------------------
     328             :  * re8_coord()
     329             :  *
     330             :  * COMPUTATION OF RE8 COORDINATES
     331             :  -----------------------------------------------------------------------*/
     332             : 
     333       96885 : static void re8_coord(
     334             :     const int16_t *y, /* i  : 8-dimensional point y[0..7] in RE8 */
     335             :     int16_t *k        /* o  : coordinates k[0..7]                */
     336             : )
     337             : {
     338             :     int16_t i, tmp, sum;
     339             : 
     340             :     /*---------------------------------------------------------------*
     341             :      * compute k = y M^-1
     342             :      *   M = 1/4 [ 1          ]
     343             :      *           [-1  2       ]
     344             :      *           [ |    \     ]
     345             :      *           [-1       2  ]
     346             :      *           [ 5 -2 _ -2 4]
     347             :      *
     348             :      *---------------------------------------------------------------*/
     349             : 
     350       96885 :     k[7] = y[7];
     351       96885 :     tmp = y[7];
     352       96885 :     sum = 5 * y[7];
     353      678195 :     for ( i = 6; i >= 1; i-- )
     354             :     {
     355             :         /* apply factor 2/4 from M^-1 */
     356      581310 :         k[i] = ( y[i] - tmp ) >> 1;
     357      581310 :         sum -= y[i];
     358             :     }
     359             : 
     360             :     /* apply factor 1/4 from M^-1 */
     361       96885 :     k[0] = ( y[0] + sum ) >> 2;
     362             : 
     363       96885 :     return;
     364             : }
     365             : 
     366             : 
     367             : /*-------------------------------------------------------------------------
     368             :  * re8_k2y()
     369             :  *
     370             :  * Voronoi indexing (index decoding) k -> y
     371             :  -----------------------------------------------------------------------*/
     372             : 
     373      455865 : void re8_k2y(
     374             :     const int16_t *k, /* i  : Voronoi index k[0..7]                                   */
     375             :     const int16_t m,  /* i  : Voronoi modulo (m = 2^r = 1<<r, where r is integer >=2) */
     376             :     int16_t *y        /* o  : 8-dimensional point y[0..7] in RE8                      */
     377             : )
     378             : {
     379             :     int16_t i, lm, v[8], tmp, sum, *ptr1, *ptr2;
     380             :     float z[8];
     381             : 
     382             :     /*---------------------------------------------------------------*
     383             :      * compute y = k M and z=(y-a)/m, where
     384             :      *   M = [4        ]
     385             :      *       [2 2      ]
     386             :      *       [|   \    ]
     387             :      *       [2     2  ]
     388             :      *       [1 1 _ 1 1]
     389             :      *   a=(2,0,...,0)
     390             :      *---------------------------------------------------------------*/
     391             : 
     392     4102785 :     for ( i = 0; i < 8; i++ )
     393             :     {
     394     3646920 :         y[i] = k[7];
     395             :     }
     396             : 
     397      455865 :     sum = 0;
     398     3191055 :     for ( i = 6; i >= 1; i-- )
     399             :     {
     400     2735190 :         tmp = 2 * k[i];
     401     2735190 :         sum += tmp;
     402     2735190 :         y[i] += tmp;
     403             :     }
     404      455865 :     y[0] += ( 4 * k[0] + sum );
     405             : 
     406             :     /* find log2(m) */
     407      825730 :     for ( lm = 0; lm < 31; lm++ )
     408             :     {
     409      825730 :         if ( ( m >> lm ) & 0x0001 )
     410             :         {
     411      455865 :             break;
     412             :         }
     413             :     }
     414             : 
     415      455865 :     z[0] = (float) ldexp( y[0] - 2, -lm );
     416     3646920 :     for ( i = 1; i < 8; i++ )
     417             :     {
     418     3191055 :         z[i] = (float) ldexp( y[i], -lm );
     419             :     }
     420             : 
     421             :     /*---------------------------------------------------------------*
     422             :      * find nearest neighbor v of z in infinite RE8
     423             :      *---------------------------------------------------------------*/
     424             : 
     425      455865 :     re8_PPV( z, v );
     426             : 
     427             :     /*---------------------------------------------------------------*
     428             :      * compute y -= m v
     429             :      *---------------------------------------------------------------*/
     430             : 
     431      455865 :     ptr1 = y;
     432      455865 :     ptr2 = v;
     433     4102785 :     for ( i = 0; i < 8; i++ )
     434             :     {
     435     3646920 :         *ptr1++ -= m * *ptr2++;
     436             :     }
     437             : 
     438      455865 :     return;
     439             : }

Generated by: LCOV version 1.14