LCOV - code coverage report
Current view: top level - lib_enc - acelp_enc_util_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ e95243e9e67ddeb69dddf129509de1b3d95b402e Lines: 113 128 88.3 %
Date: 2025-09-14 03:13:15 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : 
       6             : #include <stdint.h>
       7             : #include <assert.h>
       8             : #include "options.h"
       9             : //#include "prot_fx.h"
      10             : #include "basop_util.h"
      11             : #include "cnst.h"
      12             : #include "prot_fx.h"     /* Function prototypes                    */
      13             : #include "prot_fx_enc.h" /* Function prototypes                    */
      14             : #include "stat_enc.h"
      15             : #include "rom_com.h"
      16             : #include "rom_com_fx.h"
      17             : #include "rom_enc.h"
      18             : 
      19             : 
      20             : #define _1_Q9 0x200
      21             : 
      22             : 
      23             : /*
      24             :  * E_ACELP_toeplitz_mul_fx
      25             :  *
      26             :  * Parameters:
      27             :  *   R          I: coefficients of Toeplitz matrix    (Q9)
      28             :  *   c          I: input vector Q_xn
      29             :  *   d          O: output vector, exponent = j
      30             :  *
      31             :  * Function:
      32             :  *   Multiplication of Toeplitz matrix with vector c, such that
      33             :  *      d = toeplitz(R)*c
      34             :  *   Vector length is L_SUBFR
      35             :  */
      36      407727 : Word16 E_ACELP_toeplitz_mul_fx(
      37             :     const Word16 R[],     /* Q9 */
      38             :     const Word16 c[],     /* Qx */
      39             :     Word16 d[],           /* exp(j) */
      40             :     const Word16 L_subfr, /* Q0 */
      41             :     const Word16 highrate /* Q0 */
      42             : )
      43             : {
      44             :     static const Word16 step = 4;
      45             :     Word16 k, j, i;
      46             :     Word32 s;
      47             :     Word32 y32[L_SUBFR16k], L_maxloc, L_tot;
      48             : 
      49             : 
      50      407727 :     assert( L_subfr <= L_SUBFR16k );
      51             : 
      52             : 
      53             :     /* first keep the result on 32 bits and find absolute maximum */
      54      407727 :     L_tot = L_deposit_l( 1 );
      55             : 
      56     2038635 :     FOR( k = 0; k < step; k++ )
      57             :     {
      58     1630908 :         L_maxloc = L_deposit_l( 0 );
      59    27725436 :         FOR( i = k; i < L_subfr; i += step )
      60             :         {
      61    26094528 :             s = L_mult( R[i], c[0] ); /* Q10 + Qx */
      62   822385359 :             FOR( j = 1; j < i; j++ )
      63             :             {
      64   796290831 :                 s = L_mac( s, R[i - j], c[j] ); /* Q10 + Qx */
      65             :             }
      66   873758961 :             FOR( ; j < L_subfr; j++ )
      67             :             {
      68   847664433 :                 s = L_mac( s, R[j - i], c[j] ); /* Q10 + Qx */
      69             :             }
      70             : 
      71    26094528 :             y32[i] = s;
      72    26094528 :             move32();
      73    26094528 :             s = L_abs( s );
      74    26094528 :             L_maxloc = L_max( s, L_maxloc ); /* Q10 + Qx */
      75             :         }
      76             :         /* tot += 3*max / 8 */
      77     1630908 :         L_maxloc = L_shr( L_maxloc, 2 );
      78             :         /* Do not warn saturation of L_tot, since its for headroom estimation. */
      79             :         BASOP_SATURATE_WARNING_OFF_EVS
      80     1630908 :         L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/4 */
      81     1630908 :         L_maxloc = L_shr( L_maxloc, 1 );
      82     1630908 :         L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/8 */
      83     1630908 :         if ( highrate )
      84             :         {
      85     1618668 :             L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/8 */
      86             :         }
      87     1630908 :         L_maxloc = L_shr( L_maxloc, 1 );
      88     1630908 :         if ( highrate )
      89             :         {
      90     1618668 :             L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/16 */
      91             :         }
      92             :         BASOP_SATURATE_WARNING_ON_EVS
      93             :     }
      94             : 
      95             :     /* Find the number of right shifts to do on y32[] so that    */
      96             :     /* 6.0 x sumation of max of dn[] in each track not saturate. */
      97             :     /* high-rate: 9.0 x sumation of max of dn[] in each track    */
      98             : 
      99             :     /* Limit exponent to avoid overflows elsewhere. */
     100      407727 :     j = s_min( sub( norm_l( L_tot ), 4 + 16 ), 15 - 16 ); /* 4 -> 16 x tot */
     101             : 
     102      407727 :     Copy_Scale_sig_32_16( y32, d, L_subfr, j ); /* exp(j) */
     103             : 
     104      407727 :     return j;
     105             : }
     106             : 
     107       64061 : void E_ACELP_weighted_code(
     108             :     const Word16 code[], /* i: code                                     Q9*/
     109             :     const Word16 H[],    /* i: impulse response         Q*/
     110             :     Word16 Q,            /* i: Q format of H            */
     111             :     Word16 y[]           /* o: weighted code            Q9*/
     112             : )
     113             : {
     114             :     Word16 i, j, k, one, n, nz[L_SUBFR];
     115             :     Word32 L_tmp;
     116             : 
     117             :     /* Collect nonzeros */
     118       64061 :     n = 0;
     119       64061 :     move16();
     120     4163965 :     FOR( i = 0; i < L_SUBFR; ++i )
     121             :     {
     122     4099904 :         if ( code[i] != 0 )
     123             :         {
     124      527080 :             nz[n++] = i;
     125      527080 :             move16();
     126             :         }
     127             :     }
     128       64061 :     assert( n > 0 );
     129             : 
     130       64061 :     one = shl( 1, Q );
     131       64061 :     Q = sub( 15, Q );
     132             : 
     133             :     /* Generate weighted code */
     134       64061 :     j = nz[0];
     135       64061 :     move16();
     136       64061 :     set16_fx( y, 0, j );
     137     3764663 :     FOR( k = 0; k < L_SUBFR - j; k++ )
     138             :     {
     139     3700602 :         L_tmp = L_mult( code[j], H[k] );           /* Q10 + Q */
     140     3700602 :         y[j + k] = extract_h( L_shl( L_tmp, Q ) ); /* Q9 */
     141             :     }
     142             : 
     143      527080 :     FOR( i = 1; i < n; ++i )
     144             :     {
     145      463019 :         j = nz[i];
     146      463019 :         move16();
     147    13330594 :         FOR( k = 0; k < L_SUBFR - j; k++ )
     148             :         {
     149    12867575 :             L_tmp = L_mult( y[j + k], one );
     150    12867575 :             L_tmp = L_mac( L_tmp, code[j], H[k] );     /* Q10 + Q */
     151    12867575 :             y[j + k] = extract_h( L_shl( L_tmp, Q ) ); /* Q9*/
     152             :         }
     153             :     }
     154       64061 : }
     155             : 
     156      407727 : void E_ACELP_conv(
     157             :     const Word16 xn2[], /* i    Qx*/
     158             :     const Word16 h2[],  /* i    Q12*/
     159             :     Word16 cn2[]        /* o    Q0*/
     160             : )
     161             : {
     162             :     Word16 i, k;
     163             :     Word32 L_tmp;
     164             : #ifndef ISSUE_1867_replace_overflow_libenc
     165             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     166             :     Flag Overflow = 0;
     167             : #endif
     168             : #endif
     169    26502255 :     FOR( k = 0; k < L_SUBFR; k++ )
     170             :     {
     171             :         /*cn2[k] = xn2[k];     */
     172             :         Word64 L_tmp_64;
     173    26094528 :         L_tmp_64 = W_deposit32_l( L_mult( xn2[k], 0x800 ) ); /* 4Q11 */
     174   848072160 :         FOR( i = 0; i < k; i++ )
     175             :         {
     176             :             /*cn2[k]-=cn2[i]*h2[k-i];*/
     177   821977632 :             L_tmp_64 = W_msu0_16_16( L_tmp_64, cn2[i], h2[k - i] ); /*h2 4Q11*/
     178             :         }
     179    26094528 :         L_tmp = W_sat_l( L_tmp_64 ); /* 4Q11 */
     180             : #ifdef ISSUE_1867_replace_overflow_libenc
     181    26094528 :         cn2[k] = round_fx_sat( L_shl_sat( L_tmp, 5 ) ); /* Q0 */
     182             : #else
     183             :         cn2[k] = round_fx_o( L_shl_o( L_tmp, 5, &Overflow ), &Overflow ); /* Q0 */
     184             : #endif
     185             :     }
     186      407727 : }
     187             : 
     188           0 : void E_ACELP_conv_ivas_fx(
     189             :     const Word16 xn2[], /* i    Qnew - 1*/
     190             :     const Word16 h2[],  /* i    Q12*/
     191             :     Word16 cn2[]        /* o    Qnew*/
     192             : )
     193             : {
     194             :     Word16 i, k;
     195             :     Word32 L_tmp;
     196             : #ifndef ISSUE_1867_replace_overflow_libenc
     197             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     198             :     Flag Overflow = 0;
     199             : #endif
     200             : #endif
     201           0 :     FOR( k = 0; k < L_SUBFR; k++ )
     202             :     {
     203             :         /*cn2[k] = xn2[k];     */
     204             :         Word64 L_tmp_64;
     205           0 :         L_tmp_64 = W_deposit32_l( L_mult0( xn2[k], 0x800 ) ); /* Qnew -1 + 12  */
     206           0 :         FOR( i = 0; i < k; i++ )
     207             :         {
     208             :             /*cn2[k]-=cn2[i]*h2[k-i];*/
     209           0 :             L_tmp_64 = W_msu0_16_16( L_tmp_64, cn2[i], h2[k - i] ); /*Qnew + 11*/
     210             :         }
     211           0 :         L_tmp = W_sat_l( L_tmp_64 ); /* Qnew + 11 */
     212             : #ifdef ISSUE_1867_replace_overflow_libenc
     213           0 :         cn2[k] = round_fx_sat( L_shl_sat( L_tmp, 5 ) ); /* Qnew*/
     214             : #else
     215             :         cn2[k] = round_fx_o( L_shl_o( L_tmp, 5, &Overflow ), &Overflow ); /* Qnew*/
     216             : #endif
     217           0 :         move16();
     218             :     }
     219           0 : }
     220      190661 : void E_ACELP_build_code(
     221             :     Word16 nb_pulse,       /* i         Q0*/
     222             :     const Word16 codvec[], /* i         Q0*/
     223             :     const Word16 sign[],   /* i         Q0*/
     224             :     Word16 code[],         /* o         Q9*/
     225             :     Word16 ind[]           /* o         Q0*/
     226             : )
     227             : {
     228             :     Word16 i, k, val, index, track, tmp, vec[4];
     229             : 
     230      190661 :     set16_fx( code, 0, L_SUBFR );
     231      190661 :     set16_fx( ind, -1, NPMAXPT * 4 );
     232             : 
     233             :     /* use vec to store point counter */
     234      190661 :     vec[0] = NPMAXPT * 0 - 1;
     235      190661 :     move16();
     236      190661 :     vec[1] = NPMAXPT * 1 - 1;
     237      190661 :     move16();
     238      190661 :     vec[2] = NPMAXPT * 2 - 1;
     239      190661 :     move16();
     240      190661 :     vec[3] = NPMAXPT * 3 - 1;
     241      190661 :     move16();
     242             : 
     243     1265245 :     FOR( k = 0; k < nb_pulse; ++k )
     244             :     {
     245     1074584 :         i = codvec[k]; /* read pulse position   Q0*/
     246     1074584 :         move16();
     247     1074584 :         val = sign[i]; /* read sign             Q0*/
     248     1074584 :         move16();
     249             : 
     250     1074584 :         index = shr( i, 2 );       /* pos of pulse (0..15) */
     251     1074584 :         track = s_and( i, 4 - 1 ); /* i % 4;  */
     252             : 
     253     1074584 :         tmp = add( code[i], _1_Q9 ); /* Q9 */
     254     1074584 :         if ( val <= 0 )
     255             :         {
     256      542646 :             tmp = sub( code[i], _1_Q9 ); /* Q9 */
     257             :         }
     258     1074584 :         code[i] = tmp; /* Q9 */
     259     1074584 :         move16();
     260             : 
     261     1074584 :         if ( val <= 0 )
     262             :         {
     263      542646 :             index = add( index, 16 ); /* Q0 */
     264             :         }
     265             : 
     266             :         /* Calculate Current Store Index (we started at -1) so we increment first */
     267     1074584 :         i = add( vec[track], 1 ); /* Q0 */
     268             :         /* Save Next Store Index */
     269     1074584 :         vec[track] = i; /* Q0 */
     270     1074584 :         move16();
     271             : 
     272     1074584 :         ind[i] = index; /* Q0 */
     273     1074584 :         move16();
     274             :     }
     275      190661 : }
     276             : 
     277     2173053 : void E_ACELP_setup_pulse_search_pos(
     278             :     const PulseConfig *config, /* i: pulse configuration                  */
     279             :     Word16 k,                  /* i: interation number                  Q0*/
     280             :     UWord8 ipos[]              /* o: pulse search positions             Q0*/
     281             : )
     282             : {
     283             :     Word16 restpulses, iPulse;
     284             : 
     285             :     /* copy search order from hash-table */
     286     2173053 :     assert( config->nb_pulse + ( k * 4 ) <= 40 );
     287             : 
     288     2173053 :     copyWord8( (const Word8 *) E_ROM_tipos + ( k * 4 ), (Word8 *) ipos, config->nb_pulse );
     289             : 
     290             :     /* if all tracks do not have equal number of pulses */
     291     2173053 :     restpulses = s_and( config->nb_pulse, 3 );
     292             : 
     293     2173053 :     IF( restpulses )
     294             :     {
     295     1594465 :         SWITCH( config->codetrackpos )
     296             :         {
     297      897943 :             case TRACKPOS_FIXED_FIRST: /* fixed track positions, starting from left */
     298             :                 /* add tracks from left */
     299     2712964 :                 FOR( iPulse = 0; iPulse < restpulses; iPulse++ )
     300             :                 {
     301     1815021 :                     ipos[config->nb_pulse - restpulses + iPulse] = (UWord8) iPulse; /* Q0 */
     302     1815021 :                     move16();
     303             :                 }
     304             :                 /* Put the same track on the next position, because the 1-pulse search
     305             :                  * will access it to determine if this could be in any track. */
     306      897943 :                 ipos[config->nb_pulse] = ipos[config->nb_pulse - 1]; /* Q0 */
     307      897943 :                 move16();
     308      897943 :                 BREAK;
     309           0 :             case TRACKPOS_FIXED_EVEN: /* fixed track positions, odd tracks */
     310             :                 /* odd tracks, switch order for every iteration */
     311           0 :                 ipos[config->nb_pulse - restpulses] = (UWord8) s_and( lshl( k, 1 ), 2 );                            /* Q0 */
     312           0 :                 move16();                                                                                           /* 0 for even k, 2 for odd */
     313           0 :                 ipos[config->nb_pulse - restpulses + 1] = (UWord8) s_xor( ipos[config->nb_pulse - restpulses], 2 ); /* Q0 */
     314           0 :                 move16();                                                                                           /* 2 for even k, 0 for odd */
     315           0 :                 BREAK;
     316      293930 :             case TRACKPOS_FIXED_TWO: /* two tracks instead of four */
     317             :                 /* Put the next track on the next position, because the 1-pulse search
     318             :                  * will access it to determine if this could be in any track. */
     319      293930 :                 ipos[config->nb_pulse] = (UWord8) s_and( add( ipos[config->nb_pulse - 1], 1 ), 3 ); /* Q0 */
     320      293930 :                 move16();
     321      293930 :                 BREAK;
     322      402592 :             default: /* one or three free track positions */
     323             :                 /* copy an extra position from table - 1pulse search will access this */
     324      402592 :                 ipos[config->nb_pulse] = E_ROM_tipos[add( shl( k, 2 ), config->nb_pulse )]; /* Q0 */
     325      402592 :                 move16();
     326      402592 :                 BREAK;
     327             :         }
     328      578588 :     }
     329     2173053 : }

Generated by: LCOV version 1.14