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

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include <stdint.h>
       6             : #include "options.h"
       7             : //#include "prot_fx.h"
       8             : #include "basop_util.h"
       9             : #include "options.h"
      10             : #include "rom_enc.h"
      11             : #include "prot_fx.h"     /* Function prototypes                    */
      12             : #include "prot_fx_enc.h" /* Function prototypes                    */
      13             : 
      14             : /*--------------------------------------------------------------------------------------*
      15             :  * Local constant
      16             :  *--------------------------------------------------------------------------------------*/
      17             : 
      18             : #define _1_Q11 ( 2048 /*1.0f Q11*/ ) /* 1.0f in 4Q11 */
      19             : /*--------------------------------------------------------------------------------------*
      20             :  * E_ACELP_update_cor
      21             :  *--------------------------------------------------------------------------------------*/
      22     8808176 : static void E_ACELP_update_cor_fx(
      23             :     const Word16 pos[],    /* i Q0*/
      24             :     Word16 nb_pulse,       /* i Q0*/
      25             :     const Word16 sign[],   /* i Q13*/
      26             :     const Word16 R[],      /* i Q9+scale*/
      27             :     const Word16 cor_in[], /* i Q9*/
      28             :     Word16 cor_out[]       /* o Q9*/
      29             : )
      30             : {
      31             :     Word16 sign_x, sign_y;
      32             :     const Word16 *pRx, *pRy;
      33             :     Word16 i, tmp;
      34             : 
      35     8808176 :     IF( EQ_16( nb_pulse, 2 ) )
      36             :     {
      37             :         /* Update product of autocorrelation and already fixed pulses. with the
      38             :          * two newly found ones */
      39     8152476 :         sign_x = sign[pos[0]]; /*Q13*/
      40     8152476 :         move16();
      41     8152476 :         sign_y = sign[pos[1]]; /*Q13*/
      42     8152476 :         move16();
      43             : 
      44     8152476 :         IF( s_xor( sign_x, sign_y ) < 0 )
      45             :         {
      46     4781875 :             i = 1;
      47     4781875 :             move16();
      48     4781875 :             if ( sign_x > 0 )
      49             :             {
      50     2393914 :                 i = 0;
      51     2393914 :                 move16();
      52             :             }
      53     4781875 :             pRx = R - pos[i];     /*Q9+scale*/
      54     4781875 :             pRy = R - pos[1 - i]; /*Q9+scale*/
      55             :             /* different sign x and y */
      56   310821875 :             FOR( i = 0; i < L_SUBFR; i++ )
      57             :             {
      58   306040000 :                 tmp = sub( pRx[i], pRy[i] );
      59   306040000 :                 if ( cor_in != NULL )
      60             :                 {
      61   279042368 :                     tmp = add( tmp, cor_in[i] ); /* Q9 */
      62             :                 }
      63   306040000 :                 cor_out[i] = tmp; /* Q9 */
      64   306040000 :                 move16();
      65             :             }
      66             :         }
      67             :         ELSE
      68             :         {
      69     3370601 :             pRx = R - pos[0]; /*Q9+scale*/
      70     3370601 :             pRy = R - pos[1]; /*Q9+scale*/
      71     3370601 :             IF( sign_x > 0 )
      72             :             {
      73             :                 /* sign x and y is positive */
      74   108755140 :                 FOR( i = 0; i < L_SUBFR; i++ )
      75             :                 {
      76   107081984 :                     tmp = add( pRx[i], pRy[i] );
      77   107081984 :                     if ( cor_in != NULL )
      78             :                     {
      79    78882176 :                         tmp = add( tmp, cor_in[i] ); /* Q9 */
      80             :                     }
      81   107081984 :                     cor_out[i] = tmp; /* Q9 */
      82   107081984 :                     move16();
      83             :                 }
      84             :             }
      85             :             ELSE
      86             :             {
      87             :                 /* sign x and y is negative */
      88   110333925 :                 FOR( i = 0; i < L_SUBFR; i++ )
      89             :                 {
      90   108636480 :                     tmp = add( pRx[i], pRy[i] );
      91   108636480 :                     if ( cor_in != NULL )
      92             :                     {
      93    81052160 :                         tmp = sub( cor_in[i], tmp ); /* Q9 */
      94             :                     }
      95   108636480 :                     if ( cor_in == NULL )
      96             :                     {
      97    27584320 :                         tmp = negate( tmp );
      98             :                     }
      99   108636480 :                     cor_out[i] = tmp; /* Q9 */
     100   108636480 :                     move16();
     101             :                 }
     102             :             }
     103             :         }
     104             :     }
     105      655700 :     ELSE IF( EQ_16( nb_pulse, 4 ) )
     106             :     {
     107      655700 :         E_ACELP_update_cor_fx( pos, 2, sign, R, cor_in, cor_out );
     108      655700 :         E_ACELP_update_cor_fx( pos + 2, 2, sign, R, cor_out, cor_out );
     109             :     }
     110             :     else
     111             :     {
     112           0 :         assert( !"Number of pulses not supported" );
     113             :     }
     114     8808176 : }
     115             : /*--------------------------------------------------------------------------------------*
     116             :  * E_ACELP_2pulse_searchx
     117             :  * Iterations: nb_pos_ix*16
     118             :  *--------------------------------------------------------------------------------------*/
     119     6203311 : static void E_ACELP_2pulse_searchx_fx(
     120             :     const Word16 nb_pos_ix, /*Q0*/
     121             :     const Word16 track_x,   /*Q0*/
     122             :     const Word16 track_y,   /*Q0*/
     123             :     Word16 *R,              /*Q9+scale*/
     124             :     Word16 *ps,             /*Qdn*/
     125             :     Word16 *alp,            /*Q6*/
     126             :     Word16 *ix,             /*Q0*/
     127             :     Word16 *iy,             /*Q0*/
     128             :     Word16 dn[],            /*Qdn*/
     129             :     Word16 *dn2,            /*Q0*/
     130             :     Word16 cor[],           /*Q9*/
     131             :     Word16 sign[],          /*Q13*/
     132             :     Word16 sign_val_2 /*Q15*/ )
     133             : {
     134             :     Word16 i, x;
     135             :     Word32 y;
     136             :     Word16 *pos_x, pos[2];
     137             :     Word32 xy_save;
     138             :     Word16 ps0, ps1, alp2_16, ps2, sq;
     139             :     Word32 alp0, alp1, alp2, s;
     140             :     Word16 *pR, sgnx;
     141             :     Word16 sqk[2], alpk[2], ik;
     142             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     143     6203311 :     Flag Overflow = 0;
     144     6203311 :     move32();
     145             : #endif
     146             : 
     147             :     /* eight dn2 max positions per track */
     148     6203311 :     pos_x = &dn2[( track_x * 8 )]; /*Qdn*/
     149     6203311 :     move16();
     150             :     /* save these to limit memory searches */
     151     6203311 :     ps0 = *ps; /*Qdn*/
     152     6203311 :     move16();
     153             :     /*alp0 = *alp + 2.0f*R[0];                         move16();*/
     154     6203311 :     alp0 = L_deposit_h( *alp );                 /* Qalp = Q_R*Q_signval */
     155     6203311 :     alp0 = L_mac_sat( alp0, R[0], sign_val_2 ); /*Q9+scale+Q15*/
     156             : 
     157             :     /* Ensure that in the loop below s > 0 in the first iteration, the actual values do not matter. */
     158     6203311 :     sqk[0] = -1;
     159     6203311 :     move16();
     160     6203311 :     alpk[0] = 1;
     161     6203311 :     move16();
     162     6203311 :     x = pos_x[0];
     163     6203311 :     move16();
     164     6203311 :     sgnx = sign[track_y]; /*Q13*/
     165     6203311 :     move16();
     166     6203311 :     if ( sign[x] < 0 )
     167             :     {
     168     3069733 :         sgnx = negate( sgnx );
     169             :     }
     170     6203311 :     if ( mac_ro( L_mac_o( L_mac_o( alp0, cor[x], sign[x], &Overflow ), cor[track_y], sign[track_y], &Overflow ), R[track_y - x], sgnx, &Overflow ) < 0 )
     171             : 
     172             :     {
     173           0 :         sqk[0] = 1;
     174           0 :         move16();
     175             :     }
     176     6203311 :     ik = 0;
     177     6203311 :     move16();
     178             : 
     179     6203311 :     xy_save = L_mac0( L_deposit_l( track_y ), track_x, L_SUBFR ); /*Q0*/
     180             : 
     181             :     /* loop track 1 */
     182    45273236 :     FOR( i = 0; i < nb_pos_ix; i++ )
     183             :     {
     184    39069925 :         x = pos_x[i]; /*Q0*/
     185    39069925 :         move16();
     186    39069925 :         sgnx = sign[x]; /*Q13*/
     187    39069925 :         move16();
     188             :         /* dn[x] has only nb_pos_ix positions saved */
     189             :         /*ps1 = ps0 + dn[x];                            INDIRECT(1);ADD(1);*/
     190    39069925 :         ps1 = add_sat( ps0, dn[x] ); /*Qdn*/
     191             :         /*alp1 = alp0 + 2*sgnx*cor[x];                  INDIRECT(1);MULT(1); MAC(1);*/
     192    39069925 :         alp1 = L_mac_o( alp0, cor[x], sgnx, &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
     193    39069925 :         pR = R - x;                                      /*Q9+scale*/
     194             : 
     195   664188725 :         FOR( y = track_y; y < L_SUBFR; y += 4 )
     196             :         {
     197             :             /*ps2 = ps1 + dn[y];                         ADD(1);*/
     198   625118800 :             ps2 = add_sat( ps1, dn[y] ); /*Qdn*/
     199             :             /*alp2 = alp1 + 2.0f*sign[y]*(cor[y] + sgnx*pR[y]);   MULT(1); MAC(2);*/
     200             :             /*alp2 = alp1 + 2.0f*sign[y]*cor[y] + 2.0f*sign[y]*sgnx*pR[y];   MULT(1); MAC(2);*/
     201   625118800 :             assert( sign[y] == sign_val_2 || sign[y] == -sign_val_2 );
     202             : 
     203             :             /* Compiler warning workaround (not instrumented) */
     204   625118800 :             assert( sgnx != 0 );
     205   625118800 :             alp2_16 = 0;
     206             : 
     207   625118800 :             alp2 = L_mac_o( alp1, cor[y], sign[y], &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
     208   625118800 :             if ( sgnx > 0 )
     209             :             {
     210   310299472 :                 alp2_16 = mac_ro( alp2, pR[y], sign[y], &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
     211             :             }
     212   625118800 :             if ( sgnx < 0 )
     213             :             {
     214   314819328 :                 alp2_16 = msu_ro( alp2, pR[y], sign[y], &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
     215             :             }
     216   625118800 :             alpk[1 - ik] = alp2_16; /* Qalp */
     217   625118800 :             move16();
     218             : 
     219             :             /*sq = ps2 * ps2;                            MULT(1);*/
     220   625118800 :             sq = mult_r( ps2, ps2 ); /* (3+3)Q -> 6Q9 */
     221   625118800 :             sqk[1 - ik] = sq;        /* Q9 */
     222   625118800 :             move16();
     223             : 
     224             : 
     225             :             /*s = (alpk * sq) - (sqk * alp2);            MULT(1);MAC(1);*/
     226   625118800 :             s = L_msu_o( L_mult( alpk[ik], sq ), sqk[ik], alp2_16, &Overflow ); /* Q_sq = Q_sqk, Q_alpk = Q_alp */
     227   625118800 :             if ( s > 0 )
     228             :             {
     229    35744593 :                 ik = sub( 1, ik );
     230             :             }
     231   625118800 :             if ( s > 0 )
     232             :             {
     233    35744593 :                 xy_save = L_mac0( y, x, L_SUBFR ); /* Q0 */
     234             :             }
     235   625118800 :             assert( ( ( s >= 0 && i == 0 && y == track_y ) ) || ( y > track_y ) || ( i > 0 ) );
     236             :         }
     237             :     }
     238     6203311 :     ps1 = extract_l( xy_save );
     239     6203311 :     pos[1] = s_and( ps1, L_SUBFR - 1 );
     240     6203311 :     move16();
     241     6203311 :     pos[0] = lshr( ps1, 6 ); /* Q0 */
     242     6203311 :     move16();
     243             :     /* Update numerator */
     244     6203311 :     *ps = add( add( ps0, dn[pos[0]] ), dn[pos[1]] ); /* Qdn */
     245     6203311 :     move16();
     246             : 
     247             :     /* Update denominator */
     248     6203311 :     *alp = alpk[ik]; /* Q_alp */
     249     6203311 :     move16();
     250             : 
     251     6203311 :     E_ACELP_update_cor_fx( pos, 2, sign, R, cor, cor );
     252             : 
     253     6203311 :     *ix = pos[0]; /* Q0 */
     254     6203311 :     move16();
     255     6203311 :     *iy = pos[1]; /* Q0 */
     256     6203311 :     move16();
     257             : 
     258     6203311 :     assert( ( ( pos[0] & 3 ) == track_x ) && ( ( pos[1] & 3 ) == track_y ) ); /* sanity check */
     259     6203311 : }
     260             : 
     261             : /*--------------------------------------------------------------------------------------*
     262             :  * E_ACELP_1pulse_searchx
     263             :  *--------------------------------------------------------------------------------------*/
     264      604108 : static void E_ACELP_1pulse_searchx_fx(
     265             :     UWord8 tracks[2], /*Q0*/
     266             :     Word16 *R,        /*Q9+scale*/
     267             :     Word16 *ps,       /* Qdn */
     268             :     Word16 *alp,      /*Q6*/
     269             :     Word16 *ix,       /*Q0*/
     270             :     Word16 dn[],      /* Qdn */
     271             :     Word16 cor[],     /* Q9 */
     272             :     Word16 sign[],    /* Q13 */
     273             :     Word16 sign_val_1 /* Q15 */ )
     274             : {
     275      604108 :     Word16 x, x_save = 0;
     276             :     Word16 ps0;
     277             :     Word32 alp0;
     278             :     Word16 ps1, sq;
     279             :     Word16 alp1;
     280             :     Word32 s;
     281             :     Word16 ntracks, t;
     282             :     Word16 sqk[2], alpk[2], ik;
     283      604108 :     move16();
     284             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     285      604108 :     Flag Overflow = 0;
     286      604108 :     move32();
     287             : #endif
     288             :     /* save these to limit memory searches */
     289             :     /*alp0 = *alp + R[0];                              INDIRECT(1);*/
     290      604108 :     ps0 = *ps; /* Qdn */
     291      604108 :     move16();
     292      604108 :     alp0 = L_deposit_h( *alp );             /* Q22 */
     293      604108 :     alp0 = L_mac( alp0, R[0], sign_val_1 ); /* Qalp = (Q_R=Q_cor)*Q_signval */
     294             : 
     295             :     /* Ensure that in the loop below s > 0 in the first iteration, the actual values do not matter. */
     296      604108 :     move16();
     297      604108 :     move16();
     298      604108 :     alpk[0] = 1;
     299      604108 :     sqk[0] = -1;
     300      604108 :     ik = 0;
     301      604108 :     move16();
     302      604108 :     if ( mac_ro( alp0, cor[tracks[0]], sign[tracks[0]], &Overflow ) < 0 )
     303             :     {
     304           0 :         sqk[0] = 1;
     305           0 :         move16();
     306             :     }
     307             : 
     308      604108 :     x_save = tracks[0]; /* Q0 */
     309      604108 :     move16();
     310             : 
     311      604108 :     ntracks = 1;
     312      604108 :     move16();
     313      604108 :     if ( NE_16( tracks[1], tracks[0] ) )
     314             :     {
     315      158060 :         ntracks = 2;
     316      158060 :         move16();
     317             :     }
     318     1366276 :     FOR( t = 0; t < ntracks; ++t )
     319             :     {
     320    12956856 :         FOR( x = tracks[t]; x < L_SUBFR; x += 4 )
     321             :         {
     322             :             /* ps1 = ps0 + dn[x];                             ADD(1);*/
     323    12194688 :             ps1 = add( ps0, dn[x] );
     324             :             /* alp1 = alp0 + 2*sign[x]*cor[x];                MAC(1); MULT(1);*/
     325    12194688 :             assert( sign[x] == sign_val_1 << 1 || sign[x] == -( sign_val_1 << 1 ) );
     326    12194688 :             alp1 = mac_ro( alp0, cor[x], sign[x], &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
     327    12194688 :             alpk[1 - ik] = alp1;                               /* Qalp */
     328    12194688 :             move16();
     329             : 
     330             : 
     331             :             /*sq = ps1 * ps1;                                MULT(1);*/
     332    12194688 :             sq = mult_r( ps1, ps1 ); /* 6Q9 */
     333    12194688 :             sqk[1 - ik] = sq;        /* Q9 */
     334    12194688 :             move16();
     335             : 
     336             :             /*s = (alpk[ik] * sq) - (sqk[ik] * alp1);                MULT(1);MAC(1);*/
     337    12194688 :             s = L_msu_o( L_mult_o( alpk[ik], sq, &Overflow ), sqk[ik], alp1, &Overflow ); /* Q9+Qalp+1 */
     338    12194688 :             if ( s > 0 )
     339             :             {
     340     2201028 :                 ik = sub( 1, ik );
     341             :             }
     342    12194688 :             if ( s > 0 )
     343             :             {
     344     2201028 :                 x_save = x;
     345     2201028 :                 move16();
     346             :             }
     347    12194688 :             assert( t > 0 || ( ( s >= 0 ) && ( x == tracks[t] ) ) || x > tracks[t] );
     348             :         }
     349             :     }
     350             : 
     351      604108 :     *ps = add( ps0, dn[x_save] ); /* Qdn */
     352      604108 :     move16();
     353      604108 :     *alp = alpk[ik]; /* Qalp */
     354      604108 :     move16();
     355      604108 :     *ix = x_save; /* Q0 */
     356      604108 :     move16();
     357      604108 : }
     358             : 
     359             : /*--------------------------------------------------------------------------------------*
     360             :  * E_ACELP_4tsearchx_fx
     361             :  * Autocorrelation method for searching pulse positions effectively
     362             :  * Algorithm is identical to traditional covariance method
     363             :  *--------------------------------------------------------------------------------------*/
     364        6409 : void E_ACELP_4tsearchx_fx(
     365             :     Word16 dn[],       /*Qdn*/
     366             :     const Word16 cn[], /*Q_new*/
     367             :     Word16 Rw[],       /*Q9*/
     368             :     Word16 code[],     /*Q9*/
     369             :     const PulseConfig *config,
     370             :     Word16 ind[] /*Q0*/ )
     371             : {
     372             :     Word16 sign[L_SUBFR], vec[L_SUBFR];
     373             :     Word16 cor[L_SUBFR];
     374             :     Word16 R_buf[2 * L_SUBFR - 1], *R;
     375             :     Word16 dn2[L_SUBFR];
     376        6409 :     Word16 ps2k, ps /* same format as dn[] */, ps2, alpk, alp = 0 /* Q13 and later Q_Rw*Q_signval=Q_cor*Q_signval */;
     377             :     Word32 s;
     378             :     Word16 codvec[NB_PULSE_MAX];
     379             :     Word16 pos_max[4];
     380             :     Word16 dn2_pos[8 * 4];
     381             :     UWord8 ipos[NB_PULSE_MAX];
     382        6409 :     Word16 i, j, k, st, pos = 0;
     383             :     Word16 scale;
     384             :     Word16 sign_val_1, sign_val_2;
     385             :     Word16 nb_pulse, nb_pulse_m2;
     386        6409 :     move16();
     387        6409 :     move16();
     388             : 
     389        6409 :     ps = 0; /* to avoid compilation warnings */
     390        6409 :     move16();
     391             : 
     392             : 
     393        6409 :     alp = config->alp; /* Q13 */
     394        6409 :     move16();
     395        6409 :     nb_pulse = config->nb_pulse;
     396        6409 :     move16();
     397        6409 :     move16();
     398        6409 :     nb_pulse_m2 = sub( nb_pulse, 2 );
     399             : 
     400             :     /* Init to avoid crash when the search does not find a solution */
     401       81753 :     FOR( k = 0; k < nb_pulse; k++ )
     402             :     {
     403       75344 :         codvec[k] = k;
     404       75344 :         move16();
     405             :     }
     406             : 
     407        6409 :     scale = 0;
     408        6409 :     move16();
     409        6409 :     s = L_mult0( Rw[0], Rw[0] ); /*Q18*/
     410      410176 :     FOR( i = 1; i < L_SUBFR; i++ )
     411             :     {
     412      403767 :         s = L_mac0( s, Rw[i], Rw[i] ); /*Q18*/
     413             :     }
     414        6409 :     if ( s_and( (Word16) GE_16( nb_pulse, 9 ), (Word16) GT_32( s, 0x800000 ) ) )
     415             :     {
     416        2998 :         scale = -1;
     417        2998 :         move16();
     418             :     }
     419        6409 :     if ( s_and( (Word16) GE_16( nb_pulse, 13 ), (Word16) GT_32( s, 0x4000000 ) ) )
     420             :     {
     421         373 :         scale = -2;
     422         373 :         move16();
     423             :     }
     424        6409 :     IF( GE_16( nb_pulse, 18 ) )
     425             :     {
     426           0 :         if ( GT_32( s, 0x200000 ) )
     427             :         {
     428           0 :             scale = -1;
     429           0 :             move16();
     430             :         }
     431           0 :         if ( GT_32( s, 0x400000 ) )
     432             :         {
     433           0 :             scale = -2;
     434           0 :             move16();
     435             :         }
     436           0 :         if ( GT_32( s, 0x4000000 ) )
     437             :         {
     438           0 :             scale = -3;
     439           0 :             move16();
     440             :         }
     441             :     }
     442        6409 :     if ( s_and( (Word16) GE_16( nb_pulse, 28 ), (Word16) GT_32( s, 0x800000 ) ) )
     443             :     {
     444           0 :         scale = -3;
     445           0 :         move16();
     446             :     }
     447        6409 :     if ( s_and( (Word16) GE_16( nb_pulse, 36 ), (Word16) GT_32( s, 0x4000000 ) ) )
     448             :     {
     449           0 :         scale = -4;
     450           0 :         move16();
     451             :     }
     452             : 
     453             :     /* Set up autocorrelation vector */
     454        6409 :     R = R_buf + L_SUBFR - 1;
     455        6409 :     Copy_Scale_sig( Rw, R, L_SUBFR, scale ); /*Q9+scale*/
     456      410176 :     FOR( k = 1; k < L_SUBFR; k++ )
     457             :     {
     458      403767 :         R[-k] = R[k];
     459      403767 :         move16();
     460             :     }
     461             : 
     462             :     /* Sign value */
     463        6409 :     sign_val_2 = 0x2000; /* Q15 */
     464        6409 :     move16();
     465        6409 :     if ( GE_16( nb_pulse, 24 ) )
     466             :     {
     467           0 :         sign_val_2 = shr( sign_val_2, 1 ); /* Q15 */
     468             :     }
     469        6409 :     sign_val_1 = shr( sign_val_2, 1 ); /* Q15 */
     470             : 
     471             :     /*
     472             :      * Find sign for each pulse position.
     473             :      */
     474        6409 :     E_ACELP_pulsesign( cn, dn, dn2, sign, vec, alp, sign_val_2, L_SUBFR );
     475             : 
     476             :     /*
     477             :      * Select the most important 8 position per track according to dn2[].
     478             :      */
     479        6409 :     E_ACELP_findcandidates( dn2, dn2_pos, pos_max );
     480             : 
     481             :     /*
     482             :      * Deep first search:
     483             :      */
     484             : 
     485             :     /* Ensure that in the loop below s > 0 in the first iteration, the actual values do not matter. */
     486        6409 :     ps2k = -1;
     487        6409 :     move16();
     488        6409 :     alpk = 1;
     489        6409 :     move16();
     490             : 
     491             :     /* Number of iterations */
     492       25639 :     FOR( k = 0; k < config->nbiter; k++ )
     493             :     {
     494       19230 :         E_ACELP_setup_pulse_search_pos( config, k, ipos );
     495             : 
     496             :         /* index to first non-fixed position */
     497       19230 :         pos = config->fixedpulses; /* Q0 */
     498       19230 :         move16();
     499             : 
     500       19230 :         IF( config->fixedpulses == 0 ) /* 1100, 11, 1110, 1111, 2211 */
     501             :         {
     502           0 :             ps = 0;
     503           0 :             move16();
     504           0 :             alp = 0;
     505           0 :             move16();
     506           0 :             set16_fx( cor, 0, L_SUBFR );
     507             :         }
     508             :         ELSE
     509             :         {
     510       19230 :             assert( config->fixedpulses == 2 || config->fixedpulses == 4 );
     511             : 
     512             :             /* set fixed positions */
     513       76730 :             FOR( i = 0; i < pos; ++i )
     514             :             {
     515       57500 :                 ind[i] = pos_max[ipos[i]]; /* Q0 */
     516       57500 :                 move16();
     517             :             }
     518             : 
     519             :             /* multiplication of autocorrelation with signed fixed pulses */
     520       19230 :             E_ACELP_update_cor_fx( ind, config->fixedpulses, sign, R, NULL, cor );
     521             : 
     522             :             /* normalisation contribution of fixed part */
     523       19230 :             s = L_mult0( cor[ind[0]], sign[ind[0]] ); /* Q22 */
     524       19230 :             ps = dn[ind[0]];                          /* Qdn */
     525       19230 :             move16();
     526       57500 :             FOR( i = 1; i < pos; ++i )
     527             :             {
     528       38270 :                 s = L_mac0( s, cor[ind[i]], sign[ind[i]] ); /*Q12+Q9+1=Q22 */
     529       38270 :                 ps = add( ps, dn[ind[i]] );                 /* Qdn */
     530             :             }
     531       19230 :             alp = round_fx( s ); /*mac0 >>1 sign = 2 Q6*/
     532             :         }
     533             : 
     534             :         /* other stages of 2 pulses */
     535       19230 :         st = 0;
     536       19230 :         move16();
     537      105912 :         FOR( j = pos; j < nb_pulse; j += 2 )
     538             :         {
     539       86682 :             IF( GE_16( nb_pulse_m2, j ) ) /* pair-wise search */
     540             :             {
     541             :                 /*
     542             :                  * Calculate correlation of all possible positions
     543             :                  * of the next 2 pulses with previous fixed pulses.
     544             :                  * Each pulse can have 16 possible positions.
     545             :                  */
     546             : 
     547       84714 :                 E_ACELP_2pulse_searchx_fx( config->nbpos[st], ipos[j], ipos[j + 1], R, &ps, &alp,
     548       84714 :                                            &ind[j], &ind[j + 1], dn, dn2_pos, cor, sign, sign_val_2 );
     549             :             }
     550             :             ELSE /* single pulse search */
     551             :             {
     552        1968 :                 E_ACELP_1pulse_searchx_fx( &ipos[j], R, &ps, &alp,
     553        1968 :                                            &ind[j], dn, cor, sign, sign_val_1 );
     554             :             }
     555             : 
     556             : 
     557       86682 :             st = add( st, 1 );
     558             :         }
     559             : 
     560             :         /* memorise the best codevector */
     561             :         /*ps2 = ps * ps;                                            MULT(1);*/
     562       19230 :         ps2 = mult( ps, ps ); /* 2*Qdn+1 */
     563             : 
     564             :         /*s = (alpk * ps2) - (ps2k * alp);                          MULT(2);ADD(1);*/
     565       19230 :         s = L_msu( L_mult( alpk, ps2 ), ps2k, alp ); /* 2*Qdn+8 */
     566             : 
     567       19230 :         IF( s > 0 )
     568             :         {
     569       11682 :             ps2k = ps2;
     570       11682 :             move16();
     571       11682 :             alpk = alp;
     572       11682 :             move16();
     573       11682 :             Copy( ind, codvec, nb_pulse ); /* Q0 */
     574             :         }
     575             :     }
     576             : 
     577             : 
     578             :     /*
     579             :      * Store weighted energy of code, build the codeword and index of codevector.
     580             :      */
     581        6409 :     E_ACELP_build_code( nb_pulse, codvec, sign, code, ind );
     582        6409 : }
     583             : 
     584      387401 : void E_ACELP_4tsearchx_ivas_fx(
     585             :     Word16 dn[],       /*Qdn*/
     586             :     const Word16 cn[], /*Q_new*/
     587             :     Word16 Rw[],       /*Q9*/
     588             :     Word16 code[],     /*Q9*/
     589             :     const PulseConfig *config,
     590             :     Word16 ind[], /*Q0*/
     591             :     Word16 element_mode )
     592             : {
     593             :     Word16 sign[L_SUBFR], vec[L_SUBFR];
     594             :     Word16 cor[L_SUBFR];
     595             :     Word16 R_buf[2 * L_SUBFR - 1], *R;
     596             :     Word16 dn2[L_SUBFR];
     597      387401 :     Word16 ps2k, ps /* same format as dn[] */, ps2, alpk, alp = 0 /* Q13 and later Q_Rw*Q_signval=Q_cor*Q_signval */;
     598             :     Word32 s;
     599             :     Word16 codvec[NB_PULSE_MAX];
     600             :     Word16 pos_max[4];
     601             :     Word16 dn2_pos[8 * 4];
     602             :     UWord8 ipos[NB_PULSE_MAX];
     603      387401 :     Word16 i, j, k, st, pos = 0;
     604             :     Word16 scale;
     605             :     Word16 sign_val_1, sign_val_2;
     606             :     Word16 nb_pulse, nb_pulse_m2;
     607             :     Word16 psk;
     608             :     Word16 val, index, track;
     609      387401 :     move16();
     610      387401 :     move16();
     611             : 
     612      387401 :     psk = ps = 0; /* to avoid compilation warnings */
     613      387401 :     move16();
     614      387401 :     move16();
     615             : 
     616             : 
     617      387401 :     alp = config->alp; /* Q13 */
     618      387401 :     move16();
     619      387401 :     nb_pulse = config->nb_pulse;
     620      387401 :     move16();
     621      387401 :     nb_pulse_m2 = sub( nb_pulse, 2 );
     622             : 
     623             :     /* Init to avoid crash when the search does not find a solution */
     624     5263443 :     FOR( k = 0; k < nb_pulse; k++ )
     625             :     {
     626     4876042 :         codvec[k] = k;
     627     4876042 :         move16();
     628             :     }
     629             : 
     630      387401 :     scale = 0;
     631      387401 :     move16();
     632      387401 :     s = L_mult0( Rw[0], Rw[0] ); /* Q18 */
     633    24793664 :     FOR( i = 1; i < L_SUBFR; i++ )
     634             :     {
     635    24406263 :         s = L_mac0( s, Rw[i], Rw[i] ); /* Q18 */
     636             :     }
     637      387401 :     if ( s_and( (Word16) GE_16( nb_pulse, 9 ), (Word16) GT_32( s, 0x800000 ) ) )
     638             :     {
     639      135911 :         scale = -1;
     640      135911 :         move16();
     641             :     }
     642      387401 :     if ( s_and( (Word16) GE_16( nb_pulse, 13 ), (Word16) GT_32( s, 0x4000000 ) ) )
     643             :     {
     644           0 :         scale = -2;
     645           0 :         move16();
     646             :     }
     647      387401 :     IF( GE_16( nb_pulse, 18 ) )
     648             :     {
     649       53517 :         if ( GT_32( s, 0x200000 ) )
     650             :         {
     651       53517 :             scale = -1;
     652       53517 :             move16();
     653             :         }
     654       53517 :         if ( GT_32( s, 0x400000 ) )
     655             :         {
     656       47720 :             scale = -2;
     657       47720 :             move16();
     658             :         }
     659       53517 :         if ( GT_32( s, 0x4000000 ) )
     660             :         {
     661           0 :             scale = -3;
     662           0 :             move16();
     663             :         }
     664             :     }
     665      387401 :     if ( s_and( (Word16) GE_16( nb_pulse, 28 ), (Word16) GT_32( s, 0x800000 ) ) )
     666             :     {
     667         238 :         scale = -3;
     668         238 :         move16();
     669             :     }
     670      387401 :     if ( s_and( (Word16) GE_16( nb_pulse, 36 ), (Word16) GT_32( s, 0x4000000 ) ) )
     671             :     {
     672           0 :         scale = -4;
     673           0 :         move16();
     674             :     }
     675             : 
     676             :     /* Set up autocorrelation vector */
     677      387401 :     R = R_buf + L_SUBFR - 1;
     678      387401 :     Copy_Scale_sig( Rw, R, L_SUBFR, scale ); /* Q9 + scale */
     679    24793664 :     FOR( k = 1; k < L_SUBFR; k++ )
     680             :     {
     681    24406263 :         R[-k] = R[k];
     682    24406263 :         move16();
     683             :     }
     684             : 
     685             :     /* Sign value */
     686      387401 :     sign_val_2 = 0x2000; /* Q15 */
     687      387401 :     move16();
     688      387401 :     if ( GE_16( nb_pulse, 24 ) )
     689             :     {
     690       25186 :         sign_val_2 = shr( sign_val_2, 1 ); /* Q15 */
     691             :     }
     692      387401 :     sign_val_1 = shr( sign_val_2, 1 ); /* Q15 */
     693             : 
     694             :     /*
     695             :      * Find sign for each pulse position.
     696             :      */
     697      387401 :     E_ACELP_pulsesign( cn, dn, dn2, sign, vec, alp, sign_val_2, L_SUBFR );
     698             : 
     699             :     /*
     700             :      * Select the most important 8 position per track according to dn2[].
     701             :      */
     702      387401 :     E_ACELP_findcandidates( dn2, dn2_pos, pos_max );
     703             : 
     704             :     /*
     705             :      * Deep first search:
     706             :      */
     707             : 
     708             :     /* Ensure that in the loop below s > 0 in the first iteration, the actual values do not matter. */
     709      387401 :     ps2k = -1;
     710      387401 :     move16();
     711      387401 :     alpk = 1;
     712      387401 :     move16();
     713             : 
     714             :     /* Number of iterations */
     715     1766560 :     FOR( k = 0; k < config->nbiter; k++ )
     716             :     {
     717     1379159 :         E_ACELP_setup_pulse_search_pos( config, k, ipos );
     718             : 
     719             :         /* index to first non-fixed position */
     720     1379159 :         pos = config->fixedpulses; /* Q0 */
     721     1379159 :         move16();
     722             : 
     723     1379159 :         IF( config->fixedpulses == 0 ) /* 1100, 11, 1110, 1111, 2211 */
     724             :         {
     725      104924 :             ps = 0;
     726      104924 :             move16();
     727      104924 :             alp = 0;
     728      104924 :             move16();
     729      104924 :             set16_fx( cor, 0, L_SUBFR );
     730             :         }
     731             :         ELSE
     732             :         {
     733     1274235 :             assert( config->fixedpulses == 2 || config->fixedpulses == 4 );
     734             : 
     735             :             /* set fixed positions */
     736     5115065 :             FOR( i = 0; i < pos; ++i )
     737             :             {
     738     3840830 :                 ind[i] = pos_max[ipos[i]]; /* Q0 */
     739     3840830 :                 move16();
     740             :             }
     741             : 
     742             :             /* multiplication of autocorrelation with signed fixed pulses */
     743     1274235 :             E_ACELP_update_cor_fx( ind, config->fixedpulses, sign, R, NULL, cor );
     744             : 
     745             :             /* normalisation contribution of fixed part */
     746     1274235 :             s = L_mult0( cor[ind[0]], sign[ind[0]] ); /* Q22 */
     747     1274235 :             ps = dn[ind[0]];                          /* Qdn */
     748     1274235 :             move16();
     749     3840830 :             FOR( i = 1; i < pos; ++i )
     750             :             {
     751     2566595 :                 s = L_mac0( s, cor[ind[i]], sign[ind[i]] ); /*Q12+Q9+1=Q22 */
     752     2566595 :                 ps = add( ps, dn[ind[i]] );
     753             :             }
     754     1274235 :             alp = round_fx( s ); /*mac0 >>1 sign = 2 Q6*/
     755             :         }
     756             : 
     757             :         /* other stages of 2 pulses */
     758     1379159 :         st = 0;
     759     1379159 :         move16();
     760     8099896 :         FOR( j = pos; j < nb_pulse; j += 2 )
     761             :         {
     762     6720737 :             IF( GE_16( nb_pulse_m2, j ) ) /* pair-wise search */
     763             :             {
     764             :                 /*
     765             :                  * Calculate correlation of all possible positions
     766             :                  * of the next 2 pulses with previous fixed pulses.
     767             :                  * Each pulse can have 16 possible positions.
     768             :                  */
     769             : 
     770     6118597 :                 E_ACELP_2pulse_searchx_fx( config->nbpos[st], ipos[j], ipos[j + 1], R, &ps, &alp,
     771     6118597 :                                            &ind[j], &ind[j + 1], dn, dn2_pos, cor, sign, sign_val_2 );
     772             :             }
     773             :             ELSE /* single pulse search */
     774             :             {
     775      602140 :                 E_ACELP_1pulse_searchx_fx( &ipos[j], R, &ps, &alp,
     776      602140 :                                            &ind[j], dn, cor, sign, sign_val_1 );
     777             :             }
     778             : 
     779     6720737 :             IF( GT_16( alp, ONE_IN_Q14 ) )
     780             :             {
     781         780 :                 alp = shr( alp, 1 );
     782         780 :                 Scale_sig( cor, L_SUBFR, -1 );           /*Q8*/
     783         780 :                 Scale_sig( R_buf, 2 * L_SUBFR - 1, -1 ); /*Q8+scale*/
     784         780 :                 Scale_sig( dn, L_SUBFR, -1 );            /*Qdn-1*/
     785             :             }
     786             : 
     787             : 
     788     6720737 :             st = add( st, 1 );
     789             :         }
     790             : 
     791             :         /* memorise the best codevector */
     792             :         /*ps2 = ps * ps;                                            MULT(1);*/
     793     1379159 :         ps2 = mult( ps, ps ); /* 2*Qdn+1 */
     794             : 
     795             :         /*s = (alpk * ps2) - (ps2k * alp);                          MULT(2);ADD(1);*/
     796     1379159 :         s = L_msu( L_mult( alpk, ps2 ), ps2k, alp ); /* 2*Qdn+8 */
     797             : 
     798     1379159 :         IF( s > 0 )
     799             :         {
     800      753880 :             ps2k = ps2;
     801      753880 :             move16();
     802      753880 :             psk = ps;
     803      753880 :             move16();
     804      753880 :             alpk = alp;
     805      753880 :             move16();
     806      753880 :             Copy( ind, codvec, nb_pulse ); /*Q0*/
     807             :         }
     808             :     }
     809             : 
     810             : 
     811             :     /*
     812             :      * Store weighted energy of code, build the codeword and index of codevector.
     813             :      */
     814      387401 :     IF( EQ_16( element_mode, EVS_MONO ) )
     815             :     {
     816           0 :         E_ACELP_build_code( nb_pulse, codvec, sign, code, ind );
     817             :     }
     818             :     ELSE
     819             :     {
     820             :         /* Store weighted energy of code, build the codeword and index of codevector. */
     821      387401 :         set16_fx( code, 0, L_SUBFR );
     822      387401 :         set16_fx( ind, -1, NPMAXPT * 4 );
     823             : 
     824     5263443 :         FOR( k = 0; k < config->nb_pulse; k++ )
     825             :         {
     826     4876042 :             i = codvec[k]; /* read pulse position  Q0*/
     827     4876042 :             move16();
     828     4876042 :             val = sign[i]; /* read sign            Q13*/
     829     4876042 :             move16();
     830             : 
     831     4876042 :             index = shr( i, 2 ); /* pos of pulse (0..15) */
     832             :             // track = i % 4;
     833     4876042 :             track = s_and( i, 3 );
     834     4876042 :             IF( L_mult0( val, psk ) > 0 )
     835             :             {
     836     2406864 :                 code[i] = add( code[i], ONE_IN_Q9 /*1.0f*/ ); /* Q9 */
     837     2406864 :                 move16();
     838     2406864 :                 codvec[k] = add( codvec[k], 2 * L_SUBFR ); /* Q0 */
     839     2406864 :                 move16();
     840             :             }
     841             :             ELSE
     842             :             {
     843     2469178 :                 code[i] = sub( code[i], ONE_IN_Q9 /*1.0f*/ ); /* Q9 */
     844     2469178 :                 move16();
     845     2469178 :                 index = add( index, 16 ); /* Q0 */
     846             :             }
     847             : 
     848     4876042 :             i = imult1616( track, NPMAXPT );
     849    11389266 :             WHILE( ind[i] >= 0 )
     850             :             {
     851     6513224 :                 i++;
     852             :             }
     853             : 
     854     4876042 :             ind[i] = index;
     855     4876042 :             move16();
     856             :         }
     857             :     }
     858      387401 : }

Generated by: LCOV version 1.14