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

          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      406825 : 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      406825 :     assert( L_subfr <= L_SUBFR16k );
      51             : 
      52             : 
      53             :     /* first keep the result on 32 bits and find absolute maximum */
      54      406825 :     L_tot = L_deposit_l( 1 );
      55             : 
      56     2034125 :     FOR( k = 0; k < step; k++ )
      57             :     {
      58     1627300 :         L_maxloc = L_deposit_l( 0 );
      59    27664100 :         FOR( i = k; i < L_subfr; i += step )
      60             :         {
      61    26036800 :             s = L_mult( R[i], c[0] ); /* Q10 + Qx */
      62   820566025 :             FOR( j = 1; j < i; j++ )
      63             :             {
      64   794529225 :                 s = L_mac( s, R[i - j], c[j] ); /* Q10 + Qx */
      65             :             }
      66   871825975 :             FOR( ; j < L_subfr; j++ )
      67             :             {
      68   845789175 :                 s = L_mac( s, R[j - i], c[j] ); /* Q10 + Qx */
      69             :             }
      70             : 
      71    26036800 :             y32[i] = s;
      72    26036800 :             move32();
      73    26036800 :             s = L_abs( s );
      74    26036800 :             L_maxloc = L_max( s, L_maxloc ); /* Q10 + Qx */
      75             :         }
      76             :         /* tot += 3*max / 8 */
      77     1627300 :         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     1627300 :         L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/4 */
      81     1627300 :         L_maxloc = L_shr( L_maxloc, 1 );
      82     1627300 :         L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/8 */
      83     1627300 :         if ( highrate )
      84             :         {
      85     1615220 :             L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/8 */
      86             :         }
      87     1627300 :         L_maxloc = L_shr( L_maxloc, 1 );
      88     1627300 :         if ( highrate )
      89             :         {
      90     1615220 :             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      406825 :     j = s_min( sub( norm_l( L_tot ), 4 + 16 ), 15 - 16 ); /* 4 -> 16 x tot */
     101             : 
     102      406825 :     Copy_Scale_sig_32_16( y32, d, L_subfr, j ); /* exp(j) */
     103             : 
     104      406825 :     return j;
     105             : }
     106             : 
     107       64164 : 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       64164 :     n = 0;
     119       64164 :     move16();
     120     4170660 :     FOR( i = 0; i < L_SUBFR; ++i )
     121             :     {
     122     4106496 :         if ( code[i] != 0 )
     123             :         {
     124      526920 :             nz[n++] = i;
     125      526920 :             move16();
     126             :         }
     127             :     }
     128       64164 :     assert( n > 0 );
     129             : 
     130       64164 :     one = shl( 1, Q );
     131       64164 :     Q = sub( 15, Q );
     132             : 
     133             :     /* Generate weighted code */
     134       64164 :     j = nz[0];
     135       64164 :     move16();
     136       64164 :     set16_fx( y, 0, j );
     137     3780685 :     FOR( k = 0; k < L_SUBFR - j; k++ )
     138             :     {
     139     3716521 :         L_tmp = L_mult( code[j], H[k] );           /* Q10 + Q */
     140     3716521 :         y[j + k] = extract_h( L_shl( L_tmp, Q ) ); /* Q9 */
     141             :     }
     142             : 
     143      526920 :     FOR( i = 1; i < n; ++i )
     144             :     {
     145      462756 :         j = nz[i];
     146      462756 :         move16();
     147    13307946 :         FOR( k = 0; k < L_SUBFR - j; k++ )
     148             :         {
     149    12845190 :             L_tmp = L_mult( y[j + k], one );
     150    12845190 :             L_tmp = L_mac( L_tmp, code[j], H[k] );     /* Q10 + Q */
     151    12845190 :             y[j + k] = extract_h( L_shl( L_tmp, Q ) ); /* Q9*/
     152             :         }
     153             :     }
     154       64164 : }
     155             : 
     156        6409 : 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             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     165        6409 :     Flag Overflow = 0;
     166             : #endif
     167      416585 :     FOR( k = 0; k < L_SUBFR; k++ )
     168             :     {
     169             :         /*cn2[k] = xn2[k];     */
     170             :         Word64 L_tmp_64;
     171      410176 :         L_tmp_64 = W_deposit32_l( L_mult( xn2[k], 0x800 ) ); /* 4Q11 */
     172    13330720 :         FOR( i = 0; i < k; i++ )
     173             :         {
     174             :             /*cn2[k]-=cn2[i]*h2[k-i];*/
     175    12920544 :             L_tmp_64 = W_msu0_16_16( L_tmp_64, cn2[i], h2[k - i] ); /*h2 4Q11*/
     176             :         }
     177      410176 :         L_tmp = W_sat_l( L_tmp_64 );                                      /* 4Q11 */
     178      410176 :         cn2[k] = round_fx_o( L_shl_o( L_tmp, 5, &Overflow ), &Overflow ); /* Q0 */
     179             :     }
     180        6409 : }
     181             : 
     182      400416 : void E_ACELP_conv_ivas_fx(
     183             :     const Word16 xn2[], /* i    Qnew - 1*/
     184             :     const Word16 h2[],  /* i    Q12*/
     185             :     Word16 cn2[]        /* o    Qnew*/
     186             : )
     187             : {
     188             :     Word16 i, k;
     189             :     Word32 L_tmp;
     190             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     191      400416 :     Flag Overflow = 0;
     192             : #endif
     193    26027040 :     FOR( k = 0; k < L_SUBFR; k++ )
     194             :     {
     195             :         /*cn2[k] = xn2[k];     */
     196             :         Word64 L_tmp_64;
     197    25626624 :         L_tmp_64 = W_deposit32_l( L_mult0( xn2[k], 0x800 ) ); /* Qnew -1 + 12  */
     198   832865280 :         FOR( i = 0; i < k; i++ )
     199             :         {
     200             :             /*cn2[k]-=cn2[i]*h2[k-i];*/
     201   807238656 :             L_tmp_64 = W_msu0_16_16( L_tmp_64, cn2[i], h2[k - i] ); /*Qnew + 11*/
     202             :         }
     203    25626624 :         L_tmp = W_sat_l( L_tmp_64 );                                      /* Qnew + 11 */
     204    25626624 :         cn2[k] = round_fx_o( L_shl_o( L_tmp, 5, &Overflow ), &Overflow ); /* Qnew*/
     205    25626624 :         move16();
     206             :     }
     207      400416 : }
     208      188246 : void E_ACELP_build_code(
     209             :     Word16 nb_pulse,       /* i         Q0*/
     210             :     const Word16 codvec[], /* i         Q0*/
     211             :     const Word16 sign[],   /* i         Q0*/
     212             :     Word16 code[],         /* o         Q9*/
     213             :     Word16 ind[]           /* o         Q0*/
     214             : )
     215             : {
     216             :     Word16 i, k, val, index, track, tmp, vec[4];
     217             : 
     218      188246 :     set16_fx( code, 0, L_SUBFR );
     219      188246 :     set16_fx( ind, -1, NPMAXPT * 4 );
     220             : 
     221             :     /* use vec to store point counter */
     222      188246 :     vec[0] = NPMAXPT * 0 - 1;
     223      188246 :     move16();
     224      188246 :     vec[1] = NPMAXPT * 1 - 1;
     225      188246 :     move16();
     226      188246 :     vec[2] = NPMAXPT * 2 - 1;
     227      188246 :     move16();
     228      188246 :     vec[3] = NPMAXPT * 3 - 1;
     229      188246 :     move16();
     230             : 
     231     1250263 :     FOR( k = 0; k < nb_pulse; ++k )
     232             :     {
     233     1062017 :         i = codvec[k]; /* read pulse position   Q0*/
     234     1062017 :         move16();
     235     1062017 :         val = sign[i]; /* read sign             Q0*/
     236     1062017 :         move16();
     237             : 
     238     1062017 :         index = shr( i, 2 );       /* pos of pulse (0..15) */
     239     1062017 :         track = s_and( i, 4 - 1 ); /* i % 4;  */
     240             : 
     241     1062017 :         tmp = add( code[i], _1_Q9 ); /* Q9 */
     242     1062017 :         if ( val <= 0 )
     243             :         {
     244      535922 :             tmp = sub( code[i], _1_Q9 ); /* Q9 */
     245             :         }
     246     1062017 :         code[i] = tmp; /* Q9 */
     247     1062017 :         move16();
     248             : 
     249     1062017 :         if ( val <= 0 )
     250             :         {
     251      535922 :             index = add( index, 16 ); /* Q0 */
     252             :         }
     253             : 
     254             :         /* Calculate Current Store Index (we started at -1) so we increment first */
     255     1062017 :         i = add( vec[track], 1 ); /* Q0 */
     256             :         /* Save Next Store Index */
     257     1062017 :         vec[track] = i; /* Q0 */
     258     1062017 :         move16();
     259             : 
     260     1062017 :         ind[i] = index; /* Q0 */
     261     1062017 :         move16();
     262             :     }
     263      188246 : }
     264             : 
     265     2159474 : void E_ACELP_setup_pulse_search_pos(
     266             :     const PulseConfig *config, /* i: pulse configuration                  */
     267             :     Word16 k,                  /* i: interation number                  Q0*/
     268             :     UWord8 ipos[]              /* o: pulse search positions             Q0*/
     269             : )
     270             : {
     271             :     Word16 restpulses, iPulse;
     272             : 
     273             :     /* copy search order from hash-table */
     274     2159474 :     assert( config->nb_pulse + ( k * 4 ) <= 40 );
     275             : 
     276     2159474 :     copyWord8( (const Word8 *) E_ROM_tipos + ( k * 4 ), (Word8 *) ipos, config->nb_pulse );
     277             : 
     278             :     /* if all tracks do not have equal number of pulses */
     279     2159474 :     restpulses = s_and( config->nb_pulse, 3 );
     280             : 
     281     2159474 :     IF( restpulses )
     282             :     {
     283     1581554 :         SWITCH( config->codetrackpos )
     284             :         {
     285      890193 :             case TRACKPOS_FIXED_FIRST: /* fixed track positions, starting from left */
     286             :                 /* add tracks from left */
     287     2689062 :                 FOR( iPulse = 0; iPulse < restpulses; iPulse++ )
     288             :                 {
     289     1798869 :                     ipos[config->nb_pulse - restpulses + iPulse] = (UWord8) iPulse; /* Q0 */
     290     1798869 :                     move16();
     291             :                 }
     292             :                 /* Put the same track on the next position, because the 1-pulse search
     293             :                  * will access it to determine if this could be in any track. */
     294      890193 :                 ipos[config->nb_pulse] = ipos[config->nb_pulse - 1]; /* Q0 */
     295      890193 :                 move16();
     296      890193 :                 BREAK;
     297           0 :             case TRACKPOS_FIXED_EVEN: /* fixed track positions, odd tracks */
     298             :                 /* odd tracks, switch order for every iteration */
     299           0 :                 ipos[config->nb_pulse - restpulses] = (UWord8) s_and( lshl( k, 1 ), 2 );                            /* Q0 */
     300           0 :                 move16();                                                                                           /* 0 for even k, 2 for odd */
     301           0 :                 ipos[config->nb_pulse - restpulses + 1] = (UWord8) s_xor( ipos[config->nb_pulse - restpulses], 2 ); /* Q0 */
     302           0 :                 move16();                                                                                           /* 2 for even k, 0 for odd */
     303           0 :                 BREAK;
     304      292276 :             case TRACKPOS_FIXED_TWO: /* two tracks instead of four */
     305             :                 /* Put the next track on the next position, because the 1-pulse search
     306             :                  * will access it to determine if this could be in any track. */
     307      292276 :                 ipos[config->nb_pulse] = (UWord8) s_and( add( ipos[config->nb_pulse - 1], 1 ), 3 ); /* Q0 */
     308      292276 :                 move16();
     309      292276 :                 BREAK;
     310      399085 :             default: /* one or three free track positions */
     311             :                 /* copy an extra position from table - 1pulse search will access this */
     312      399085 :                 ipos[config->nb_pulse] = E_ROM_tipos[add( shl( k, 2 ), config->nb_pulse )]; /* Q0 */
     313      399085 :                 move16();
     314      399085 :                 BREAK;
     315             :         }
     316      577920 :     }
     317     2159474 : }

Generated by: LCOV version 1.14