LCOV - code coverage report
Current view: top level - lib_com - re8_ppv_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 53 53 100.0 %
Date: 2025-05-03 01:55:50 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include "options.h" /* Compilation switches                   */
       6             : #include "cnst.h"    /* Common constants                       */
       7             : #include "prot_fx.h" /* Function prototypes                    */
       8             : #include "stl.h"
       9             : 
      10             : /*-------------------------------------------------------------------*
      11             :  * Local function prototypes
      12             :  *-------------------------------------------------------------------*/
      13             : 
      14             : static void nearest_neighbor_2D8_fx( const Word32 x[], Word16 y[] );
      15             : static Word32 compute_error_2D8_fx( const Word32 x[], const Word16 y[] );
      16             : 
      17             : /*--------------------------------------------------------------*
      18             :  * RE8_PPV:
      19             :  *
      20             :  * NEAREST NEIGHBOR SEARCH IN INFINITE LATTICE RE8
      21             :  * the algorithm is based on the definition of RE8 as
      22             :  *     RE8 = (2D8) U (2D8+[1,1,1,1,1,1,1,1])
      23             :  * it applies the coset decoding of Sloane and Conway
      24             :  * --------------------------------------------------------------*/
      25             : 
      26     2411654 : void re8_PPV_fx(
      27             :     const Word32 x[], /* i  : point in R^8                                                                      Q15 */
      28             :     Word16 y[]        /* o  : point in RE8 (8-dimensional integer vector)       Q0*/
      29             : )
      30             : {
      31             :     Word16 i, y0[8];
      32             :     Word32 e0, e1, x1[8];
      33             : 
      34             :     /*--------------------------------------------------------------*
      35             :      * find the nearest neighbor y0 of x in 2D8
      36             :      *--------------------------------------------------------------*/
      37     2411654 :     nearest_neighbor_2D8_fx( x, y0 );
      38             : 
      39             :     /*--------------------------------------------------------------*
      40             :      * find the nearest neighbor y1 of x in 2D8+(1,...,1) (by coset decoding)
      41             :      *--------------------------------------------------------------*/
      42             : 
      43    21704886 :     FOR( i = 0; i < 8; i++ )
      44             :     {
      45    19293232 :         x1[i] = L_sub( x[i], QR ); /* Q15 */
      46    19293232 :         move32();
      47             :     }
      48     2411654 :     nearest_neighbor_2D8_fx( x1, y );
      49             : 
      50    21704886 :     FOR( i = 0; i < 8; i++ )
      51             :     {
      52    19293232 :         y[i] = add( y[i], 1 ); /* Q0 */
      53    19293232 :         move16();
      54             :     }
      55             : 
      56             :     /*--------------------------------------------------------------*
      57             :      * compute e0=||x-y0||^2 and e1=||x-y1||^2
      58             :      *--------------------------------------------------------------*/
      59             : 
      60     2411654 :     e0 = compute_error_2D8_fx( x, y0 );
      61     2411654 :     e1 = compute_error_2D8_fx( x, y );
      62             : 
      63             : 
      64             :     /*--------------------------------------------------------------*
      65             :      * select best candidate y0 or y1 to minimize distortion
      66             :      *--------------------------------------------------------------*/
      67     2411654 :     IF( LT_32( e0, e1 ) )
      68             :     {
      69     1371268 :         Copy( y0, y, 8 ); /* Q0 */
      70             :     }
      71             : 
      72     2411654 :     return;
      73             : }
      74             : 
      75             : 
      76             : /*--------------------------------------------------------------*
      77             :  * Nearest_neighbor_2D8(x,y)
      78             :  *
      79             :  * NEAREST NEIGHBOR SEARCH IN INFINITE LATTICE 2D8
      80             :  * algorithm: nn_2D8(x) = 2*nn_D8(x/2)
      81             :  *            nn_D8 = decoding of Z^8 with Wagner rule
      82             :  * (see Conway and Sloane's paper in IT-82)
      83             :  --------------------------------------------------------------*/
      84             : 
      85     4823308 : static void nearest_neighbor_2D8_fx(
      86             :     const Word32 x[], /* i  : point in R^8                                                                      Q15*/
      87             :     Word16 y[]        /* o  : point in 2D8 (8-dimensional integer vector)       Q0*/
      88             : )
      89             : {
      90             :     Word16 i, j;
      91             :     Word16 sum, tmp16, tmp16b;
      92             :     Word32 s, e, em;
      93             : 
      94             :     /*--------------------------------------------------------------*
      95             :      * round x into 2Z^8 i.e. compute y=(y1,...,y8) such that yi = 2[xi/2]
      96             :      *   where [.] is the nearest integer operator
      97             :      *   in the mean time, compute sum = y1+...+y8
      98             :      *--------------------------------------------------------------*/
      99     4823308 :     sum = 0;
     100     4823308 :     move16();
     101             : 
     102    43409772 :     FOR( i = 0; i < 8; i++ )
     103             :     {
     104             :         /* round to ..., -2, 0, 2, ... ([-1..1[ --> 0) */
     105    38586464 :         tmp16 = round_fx( L_add( x[i], L_shr( x[i], 31 ) ) );
     106    38586464 :         y[i] = shl( tmp16, 1 ); /* Q0 */
     107    38586464 :         move16();
     108             :         /* sum += y[i] */
     109    38586464 :         sum = add( sum, y[i] ); /* Q0 */
     110             :     }
     111             : 
     112             :     /*--------------------------------------------------------------*
     113             :      * check if y1+...+y8 is a multiple of 4
     114             :      *   if not, y is not round xj in the wrong way where j is defined by
     115             :      *   j = arg max_i | xi -yi|
     116             :      *   (this is called the Wagner rule)
     117             :      *--------------------------------------------------------------*/
     118     4823308 :     IF( s_and( sum, 2 ) != 0 )
     119             :     {
     120             :         /* find j = arg max_i | xi -yi| */
     121     2511008 :         em = L_deposit_l( 0 );
     122     2511008 :         j = 0;
     123     2511008 :         move16();
     124             : 
     125    22599072 :         FOR( i = 0; i < 8; i++ )
     126             :         {
     127             :             /* compute ei = xi-yi */
     128             :             /* e[i]=x[i]-y[i]     */
     129    20088064 :             e = L_msu( x[i], y[i], QR / 2 ); /* Q15 */
     130             : 
     131             :             /* compute |ei| = | xi-yi | */
     132    20088064 :             s = L_abs( e );
     133             : 
     134             :             /* check if |ei| is maximal, if so, set j=i */
     135    20088064 :             if ( LT_32( em, s ) )
     136             :             {
     137     5568005 :                 j = i;
     138     5568005 :                 move16();
     139             :             }
     140    20088064 :             em = L_max( s, em ); /* Q15 */
     141             :         }
     142             : 
     143             :         /* round xj in the "wrong way" */
     144     2511008 :         e = L_msu( x[j], y[j], QR / 2 ); /* Q15 */
     145     2511008 :         tmp16 = extract_h( e );
     146     2511008 :         tmp16b = add( y[j], 2 ); /* Q0 */
     147             : 
     148     2511008 :         if ( tmp16 < 0 )
     149             :         {
     150     1150305 :             tmp16b = sub( tmp16b, 2 + 2 ); /* Q0 */
     151             :         }
     152     2511008 :         y[j] = tmp16b; /* Q0 */
     153     2511008 :         move16();
     154             :     }
     155             : 
     156     4823308 :     return;
     157             : }
     158             : 
     159             : 
     160             : /*--------------------------------------------------------------*
     161             :  * Compute_error_2D8(x,y)
     162             :  *
     163             :  * Compute mean square error between input vector and
     164             :  * (quantized) point in 2D8.
     165             :  --------------------------------------------------------------*/
     166             : 
     167     4823308 : static Word32 compute_error_2D8_fx(                   /* o  : mean squared error                                                        Q15*/
     168             :                                     const Word32 x[], /* i  : input vector                                                                      Q15*/
     169             :                                     const Word16 y[]  /* i  : point in 2D8 (8-dimensional integer vector)       Q0*/
     170             : )
     171             : {
     172             :     Word16 i, hi, lo;
     173             :     Word32 err, Ltmp;
     174             : 
     175     4823308 :     err = L_deposit_l( 0 );
     176    43409772 :     FOR( i = 0; i < 8; i++ )
     177             :     {
     178             :         /*tmp = x[i]-y[i];*/
     179    38586464 :         Ltmp = L_msu( x[i], y[i], 16384 );          /* Q15 */
     180    38586464 :         hi = extract_h( L_shl( Ltmp, 1 ) );         /* Q0 */
     181    38586464 :         lo = extract_l( L_msu( Ltmp, hi, 16384 ) ); /* Q15 */
     182             : 
     183    38586464 :         Ltmp = L_mult( hi, hi );                  /* Q1 */
     184    38586464 :         Ltmp = L_shl( Ltmp, 14 );                 /* Q15 */
     185    38586464 :         Ltmp = L_mac( Ltmp, hi, lo );             /* Q15 */
     186    38586464 :         Ltmp = L_mac0( Ltmp, mult( lo, lo ), 1 ); /* Q15 */
     187             : 
     188             :         /* err+=tmp*tmp */
     189    38586464 :         err = L_add( Ltmp, err ); /* Q15 */
     190             :     }
     191             : 
     192     4823308 :     return ( err );
     193             : }

Generated by: LCOV version 1.14