LCOV - code coverage report
Current view: top level - lib_enc - acelp_enc_util_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ 43b7b28dcb1471ff5d355252c4b8f37ee7ecc268 Lines: 113 128 88.3 %
Date: 2025-11-02 02:02:47 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_enc.h"
      17             : 
      18             : 
      19             : #define _1_Q9 0x200
      20             : 
      21             : 
      22             : /*
      23             :  * E_ACELP_toeplitz_mul_fx
      24             :  *
      25             :  * Parameters:
      26             :  *   R          I: coefficients of Toeplitz matrix    (Q9)
      27             :  *   c          I: input vector Q_xn
      28             :  *   d          O: output vector, exponent = j
      29             :  *
      30             :  * Function:
      31             :  *   Multiplication of Toeplitz matrix with vector c, such that
      32             :  *      d = toeplitz(R)*c
      33             :  *   Vector length is L_SUBFR
      34             :  */
      35      407667 : Word16 E_ACELP_toeplitz_mul_fx(
      36             :     const Word16 R[],     /* Q9 */
      37             :     const Word16 c[],     /* Qx */
      38             :     Word16 d[],           /* exp(j) */
      39             :     const Word16 L_subfr, /* Q0 */
      40             :     const Word16 highrate /* Q0 */
      41             : )
      42             : {
      43             :     static const Word16 step = 4;
      44             :     Word16 k, j, i;
      45             :     Word32 s;
      46             :     Word32 y32[L_SUBFR16k], L_maxloc, L_tot;
      47             : 
      48             : 
      49      407667 :     assert( L_subfr <= L_SUBFR16k );
      50             : 
      51             : 
      52             :     /* first keep the result on 32 bits and find absolute maximum */
      53      407667 :     L_tot = L_deposit_l( 1 );
      54             : 
      55     2038335 :     FOR( k = 0; k < step; k++ )
      56             :     {
      57     1630668 :         L_maxloc = L_deposit_l( 0 );
      58    27721356 :         FOR( i = k; i < L_subfr; i += step )
      59             :         {
      60    26090688 :             s = L_mult( R[i], c[0] ); /* Q10 + Qx */
      61   822264339 :             FOR( j = 1; j < i; j++ )
      62             :             {
      63   796173651 :                 s = L_mac( s, R[i - j], c[j] ); /* Q10 + Qx */
      64             :             }
      65   873630381 :             FOR( ; j < L_subfr; j++ )
      66             :             {
      67   847539693 :                 s = L_mac( s, R[j - i], c[j] ); /* Q10 + Qx */
      68             :             }
      69             : 
      70    26090688 :             y32[i] = s;
      71    26090688 :             move32();
      72    26090688 :             s = L_abs( s );
      73    26090688 :             L_maxloc = L_max( s, L_maxloc ); /* Q10 + Qx */
      74             :         }
      75             :         /* tot += 3*max / 8 */
      76     1630668 :         L_maxloc = L_shr( L_maxloc, 2 );
      77             :         /* Do not warn saturation of L_tot, since its for headroom estimation. */
      78             :         BASOP_SATURATE_WARNING_OFF_EVS
      79     1630668 :         L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/4 */
      80     1630668 :         L_maxloc = L_shr( L_maxloc, 1 );
      81     1630668 :         L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/8 */
      82     1630668 :         if ( highrate )
      83             :         {
      84     1618428 :             L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/8 */
      85             :         }
      86     1630668 :         L_maxloc = L_shr( L_maxloc, 1 );
      87     1630668 :         if ( highrate )
      88             :         {
      89     1618428 :             L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/16 */
      90             :         }
      91             :         BASOP_SATURATE_WARNING_ON_EVS
      92             :     }
      93             : 
      94             :     /* Find the number of right shifts to do on y32[] so that    */
      95             :     /* 6.0 x sumation of max of dn[] in each track not saturate. */
      96             :     /* high-rate: 9.0 x sumation of max of dn[] in each track    */
      97             : 
      98             :     /* Limit exponent to avoid overflows elsewhere. */
      99      407667 :     j = s_min( sub( norm_l( L_tot ), 4 + 16 ), 15 - 16 ); /* 4 -> 16 x tot */
     100             : 
     101      407667 :     Copy_Scale_sig_32_16( y32, d, L_subfr, j ); /* exp(j) */
     102             : 
     103      407667 :     return j;
     104             : }
     105             : 
     106       64061 : void E_ACELP_weighted_code(
     107             :     const Word16 code[], /* i: code                                     Q9*/
     108             :     const Word16 H[],    /* i: impulse response         Q*/
     109             :     Word16 Q,            /* i: Q format of H            */
     110             :     Word16 y[]           /* o: weighted code            Q9*/
     111             : )
     112             : {
     113             :     Word16 i, j, k, one, n, nz[L_SUBFR];
     114             :     Word32 L_tmp;
     115             : 
     116             :     /* Collect nonzeros */
     117       64061 :     n = 0;
     118       64061 :     move16();
     119     4163965 :     FOR( i = 0; i < L_SUBFR; ++i )
     120             :     {
     121     4099904 :         if ( code[i] != 0 )
     122             :         {
     123      527082 :             nz[n++] = i;
     124      527082 :             move16();
     125             :         }
     126             :     }
     127       64061 :     assert( n > 0 );
     128             : 
     129       64061 :     one = shl( 1, Q );
     130       64061 :     Q = sub( 15, Q );
     131             : 
     132             :     /* Generate weighted code */
     133       64061 :     j = nz[0];
     134       64061 :     move16();
     135       64061 :     set16_fx( y, 0, j );
     136     3764687 :     FOR( k = 0; k < L_SUBFR - j; k++ )
     137             :     {
     138     3700626 :         L_tmp = L_mult( code[j], H[k] );           /* Q10 + Q */
     139     3700626 :         y[j + k] = extract_h( L_shl( L_tmp, Q ) ); /* Q9 */
     140             :     }
     141             : 
     142      527082 :     FOR( i = 1; i < n; ++i )
     143             :     {
     144      463021 :         j = nz[i];
     145      463021 :         move16();
     146    13330268 :         FOR( k = 0; k < L_SUBFR - j; k++ )
     147             :         {
     148    12867247 :             L_tmp = L_mult( y[j + k], one );
     149    12867247 :             L_tmp = L_mac( L_tmp, code[j], H[k] );     /* Q10 + Q */
     150    12867247 :             y[j + k] = extract_h( L_shl( L_tmp, Q ) ); /* Q9*/
     151             :         }
     152             :     }
     153       64061 : }
     154             : 
     155      407667 : void E_ACELP_conv(
     156             :     const Word16 xn2[], /* i    Qx*/
     157             :     const Word16 h2[],  /* i    Q12*/
     158             :     Word16 cn2[]        /* o    Q0*/
     159             : )
     160             : {
     161             :     Word16 i, k;
     162             :     Word32 L_tmp;
     163             : 
     164    26498355 :     FOR( k = 0; k < L_SUBFR; k++ )
     165             :     {
     166             :         /*cn2[k] = xn2[k];     */
     167             :         Word64 L_tmp_64;
     168    26090688 :         L_tmp_64 = W_deposit32_l( L_mult( xn2[k], 0x800 ) ); /* 4Q11 */
     169   847947360 :         FOR( i = 0; i < k; i++ )
     170             :         {
     171             :             /*cn2[k]-=cn2[i]*h2[k-i];*/
     172   821856672 :             L_tmp_64 = W_msu0_16_16( L_tmp_64, cn2[i], h2[k - i] ); /*h2 4Q11*/
     173             :         }
     174    26090688 :         L_tmp = W_sat_l( L_tmp_64 );                    /* 4Q11 */
     175    26090688 :         cn2[k] = round_fx_sat( L_shl_sat( L_tmp, 5 ) ); /* Q0 */
     176             :     }
     177      407667 : }
     178             : 
     179           0 : void E_ACELP_conv_ivas_fx(
     180             :     const Word16 xn2[], /* i    Qnew - 1*/
     181             :     const Word16 h2[],  /* i    Q12*/
     182             :     Word16 cn2[]        /* o    Qnew*/
     183             : )
     184             : {
     185             :     Word16 i, k;
     186             :     Word32 L_tmp;
     187             : 
     188           0 :     FOR( k = 0; k < L_SUBFR; k++ )
     189             :     {
     190             :         /*cn2[k] = xn2[k];     */
     191             :         Word64 L_tmp_64;
     192           0 :         L_tmp_64 = W_deposit32_l( L_mult0( xn2[k], 0x800 ) ); /* Qnew -1 + 12  */
     193           0 :         FOR( i = 0; i < k; i++ )
     194             :         {
     195             :             /*cn2[k]-=cn2[i]*h2[k-i];*/
     196           0 :             L_tmp_64 = W_msu0_16_16( L_tmp_64, cn2[i], h2[k - i] ); /*Qnew + 11*/
     197             :         }
     198           0 :         L_tmp = W_sat_l( L_tmp_64 );                    /* Qnew + 11 */
     199           0 :         cn2[k] = round_fx_sat( L_shl_sat( L_tmp, 5 ) ); /* Qnew*/
     200           0 :         move16();
     201             :     }
     202           0 : }
     203      190581 : void E_ACELP_build_code(
     204             :     Word16 nb_pulse,       /* i         Q0*/
     205             :     const Word16 codvec[], /* i         Q0*/
     206             :     const Word16 sign[],   /* i         Q0*/
     207             :     Word16 code[],         /* o         Q9*/
     208             :     Word16 ind[]           /* o         Q0*/
     209             : )
     210             : {
     211             :     Word16 i, k, val, index, track, tmp, vec[4];
     212             : 
     213      190581 :     set16_fx( code, 0, L_SUBFR );
     214      190581 :     set16_fx( ind, -1, NPMAXPT * 4 );
     215             : 
     216             :     /* use vec to store point counter */
     217      190581 :     vec[0] = NPMAXPT * 0 - 1;
     218      190581 :     move16();
     219      190581 :     vec[1] = NPMAXPT * 1 - 1;
     220      190581 :     move16();
     221      190581 :     vec[2] = NPMAXPT * 2 - 1;
     222      190581 :     move16();
     223      190581 :     vec[3] = NPMAXPT * 3 - 1;
     224      190581 :     move16();
     225             : 
     226     1264657 :     FOR( k = 0; k < nb_pulse; ++k )
     227             :     {
     228     1074076 :         i = codvec[k]; /* read pulse position   Q0*/
     229     1074076 :         move16();
     230     1074076 :         val = sign[i]; /* read sign             Q0*/
     231     1074076 :         move16();
     232             : 
     233     1074076 :         index = shr( i, 2 );       /* pos of pulse (0..15) */
     234     1074076 :         track = s_and( i, 4 - 1 ); /* i % 4;  */
     235             : 
     236     1074076 :         tmp = add( code[i], _1_Q9 ); /* Q9 */
     237     1074076 :         if ( val <= 0 )
     238             :         {
     239      542388 :             tmp = sub( code[i], _1_Q9 ); /* Q9 */
     240             :         }
     241     1074076 :         code[i] = tmp; /* Q9 */
     242     1074076 :         move16();
     243             : 
     244     1074076 :         if ( val <= 0 )
     245             :         {
     246      542388 :             index = add( index, 16 ); /* Q0 */
     247             :         }
     248             : 
     249             :         /* Calculate Current Store Index (we started at -1) so we increment first */
     250     1074076 :         i = add( vec[track], 1 ); /* Q0 */
     251             :         /* Save Next Store Index */
     252     1074076 :         vec[track] = i; /* Q0 */
     253     1074076 :         move16();
     254             : 
     255     1074076 :         ind[i] = index; /* Q0 */
     256     1074076 :         move16();
     257             :     }
     258      190581 : }
     259             : 
     260     2172561 : void E_ACELP_setup_pulse_search_pos(
     261             :     const PulseConfig *config, /* i: pulse configuration                  */
     262             :     Word16 k,                  /* i: interation number                  Q0*/
     263             :     UWord8 ipos[]              /* o: pulse search positions             Q0*/
     264             : )
     265             : {
     266             :     Word16 restpulses, iPulse;
     267             : 
     268             :     /* copy search order from hash-table */
     269     2172561 :     assert( config->nb_pulse + ( k * 4 ) <= 40 );
     270             : 
     271     2172561 :     copyWord8( (const Word8 *) E_ROM_tipos + ( k * 4 ), (Word8 *) ipos, config->nb_pulse );
     272             : 
     273             :     /* if all tracks do not have equal number of pulses */
     274     2172561 :     restpulses = s_and( config->nb_pulse, 3 );
     275             : 
     276     2172561 :     IF( restpulses )
     277             :     {
     278     1594613 :         SWITCH( config->codetrackpos )
     279             :         {
     280      897824 :             case TRACKPOS_FIXED_FIRST: /* fixed track positions, starting from left */
     281             :                 /* add tracks from left */
     282     2711986 :                 FOR( iPulse = 0; iPulse < restpulses; iPulse++ )
     283             :                 {
     284     1814162 :                     ipos[config->nb_pulse - restpulses + iPulse] = (UWord8) iPulse; /* Q0 */
     285     1814162 :                     move16();
     286             :                 }
     287             :                 /* Put the same track on the next position, because the 1-pulse search
     288             :                  * will access it to determine if this could be in any track. */
     289      897824 :                 ipos[config->nb_pulse] = ipos[config->nb_pulse - 1]; /* Q0 */
     290      897824 :                 move16();
     291      897824 :                 BREAK;
     292           0 :             case TRACKPOS_FIXED_EVEN: /* fixed track positions, odd tracks */
     293             :                 /* odd tracks, switch order for every iteration */
     294           0 :                 ipos[config->nb_pulse - restpulses] = (UWord8) s_and( lshl( k, 1 ), 2 );                            /* Q0 */
     295           0 :                 move16();                                                                                           /* 0 for even k, 2 for odd */
     296           0 :                 ipos[config->nb_pulse - restpulses + 1] = (UWord8) s_xor( ipos[config->nb_pulse - restpulses], 2 ); /* Q0 */
     297           0 :                 move16();                                                                                           /* 2 for even k, 0 for odd */
     298           0 :                 BREAK;
     299      294134 :             case TRACKPOS_FIXED_TWO: /* two tracks instead of four */
     300             :                 /* Put the next track on the next position, because the 1-pulse search
     301             :                  * will access it to determine if this could be in any track. */
     302      294134 :                 ipos[config->nb_pulse] = (UWord8) s_and( add( ipos[config->nb_pulse - 1], 1 ), 3 ); /* Q0 */
     303      294134 :                 move16();
     304      294134 :                 BREAK;
     305      402655 :             default: /* one or three free track positions */
     306             :                 /* copy an extra position from table - 1pulse search will access this */
     307      402655 :                 ipos[config->nb_pulse] = E_ROM_tipos[add( shl( k, 2 ), config->nb_pulse )]; /* Q0 */
     308      402655 :                 move16();
     309      402655 :                 BREAK;
     310             :         }
     311      577948 :     }
     312     2172561 : }

Generated by: LCOV version 1.14