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 @ 574a190e3c6896c6c4ed10d7f23649709a0c4347 Lines: 364 391 93.1 %
Date: 2025-06-27 02:59:36 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     8817291 : 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     8817291 :     IF( EQ_16( nb_pulse, 2 ) )
      36             :     {
      37             :         /* Update product of autocorrelation and already fixed pulses. with the
      38             :          * two newly found ones */
      39     8161548 :         sign_x = sign[pos[0]]; /*Q13*/
      40     8161548 :         move16();
      41     8161548 :         sign_y = sign[pos[1]]; /*Q13*/
      42     8161548 :         move16();
      43             : 
      44     8161548 :         IF( s_xor( sign_x, sign_y ) < 0 )
      45             :         {
      46     4789611 :             i = 1;
      47     4789611 :             move16();
      48     4789611 :             if ( sign_x > 0 )
      49             :             {
      50     2400933 :                 i = 0;
      51     2400933 :                 move16();
      52             :             }
      53     4789611 :             pRx = R - pos[i];     /*Q9+scale*/
      54     4789611 :             pRy = R - pos[1 - i]; /*Q9+scale*/
      55             :             /* different sign x and y */
      56   311324715 :             FOR( i = 0; i < L_SUBFR; i++ )
      57             :             {
      58   306535104 :                 tmp = sub( pRx[i], pRy[i] );
      59   306535104 :                 if ( cor_in != NULL )
      60             :                 {
      61   279702912 :                     tmp = add( tmp, cor_in[i] ); /* Q9 */
      62             :                 }
      63   306535104 :                 cor_out[i] = tmp; /* Q9 */
      64   306535104 :                 move16();
      65             :             }
      66             :         }
      67             :         ELSE
      68             :         {
      69     3371937 :             pRx = R - pos[0]; /*Q9+scale*/
      70     3371937 :             pRy = R - pos[1]; /*Q9+scale*/
      71     3371937 :             IF( sign_x > 0 )
      72             :             {
      73             :                 /* sign x and y is positive */
      74   108855435 :                 FOR( i = 0; i < L_SUBFR; i++ )
      75             :                 {
      76   107180736 :                     tmp = add( pRx[i], pRy[i] );
      77   107180736 :                     if ( cor_in != NULL )
      78             :                     {
      79    78844800 :                         tmp = add( tmp, cor_in[i] ); /* Q9 */
      80             :                     }
      81   107180736 :                     cor_out[i] = tmp; /* Q9 */
      82   107180736 :                     move16();
      83             :                 }
      84             :             }
      85             :             ELSE
      86             :             {
      87             :                 /* sign x and y is negative */
      88   110320470 :                 FOR( i = 0; i < L_SUBFR; i++ )
      89             :                 {
      90   108623232 :                     tmp = add( pRx[i], pRy[i] );
      91   108623232 :                     if ( cor_in != NULL )
      92             :                     {
      93    80967040 :                         tmp = sub( cor_in[i], tmp ); /* Q9 */
      94             :                     }
      95   108623232 :                     if ( cor_in == NULL )
      96             :                     {
      97    27656192 :                         tmp = negate( tmp );
      98             :                     }
      99   108623232 :                     cor_out[i] = tmp; /* Q9 */
     100   108623232 :                     move16();
     101             :                 }
     102             :             }
     103             :         }
     104             :     }
     105      655743 :     ELSE IF( EQ_16( nb_pulse, 4 ) )
     106             :     {
     107      655743 :         E_ACELP_update_cor_fx( pos, 2, sign, R, cor_in, cor_out );
     108      655743 :         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     8817291 : }
     115             : /*--------------------------------------------------------------------------------------*
     116             :  * E_ACELP_2pulse_searchx
     117             :  * Iterations: nb_pos_ix*16
     118             :  *--------------------------------------------------------------------------------------*/
     119     6211675 : 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     6211675 :     Flag Overflow = 0;
     144     6211675 :     move32();
     145             : #endif
     146             : 
     147             :     /* eight dn2 max positions per track */
     148     6211675 :     pos_x = &dn2[( track_x * 8 )]; /*Qdn*/
     149     6211675 :     move16();
     150             :     /* save these to limit memory searches */
     151     6211675 :     ps0 = *ps; /*Qdn*/
     152     6211675 :     move16();
     153             :     /*alp0 = *alp + 2.0f*R[0];                         move16();*/
     154     6211675 :     alp0 = L_deposit_h( *alp );                 /* Qalp = Q_R*Q_signval */
     155     6211675 :     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     6211675 :     sqk[0] = -1;
     159     6211675 :     move16();
     160     6211675 :     alpk[0] = 1;
     161     6211675 :     move16();
     162     6211675 :     x = pos_x[0];
     163     6211675 :     move16();
     164     6211675 :     sgnx = sign[track_y]; /*Q13*/
     165     6211675 :     move16();
     166     6211675 :     if ( sign[x] < 0 )
     167             :     {
     168     3071334 :         sgnx = negate( sgnx );
     169             :     }
     170     6211675 :     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     6211675 :     ik = 0;
     177     6211675 :     move16();
     178             : 
     179     6211675 :     xy_save = L_mac0( L_deposit_l( track_y ), track_x, L_SUBFR ); /*Q0*/
     180             : 
     181             :     /* loop track 1 */
     182    45328371 :     FOR( i = 0; i < nb_pos_ix; i++ )
     183             :     {
     184    39116696 :         x = pos_x[i]; /*Q0*/
     185    39116696 :         move16();
     186    39116696 :         sgnx = sign[x]; /*Q13*/
     187    39116696 :         move16();
     188             :         /* dn[x] has only nb_pos_ix positions saved */
     189             :         /*ps1 = ps0 + dn[x];                            INDIRECT(1);ADD(1);*/
     190    39116696 :         ps1 = add_sat( ps0, dn[x] ); /*Qdn*/
     191             :         /*alp1 = alp0 + 2*sgnx*cor[x];                  INDIRECT(1);MULT(1); MAC(1);*/
     192    39116696 :         alp1 = L_mac_o( alp0, cor[x], sgnx, &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
     193    39116696 :         pR = R - x;                                      /*Q9+scale*/
     194             : 
     195   664983832 :         FOR( y = track_y; y < L_SUBFR; y += 4 )
     196             :         {
     197             :             /*ps2 = ps1 + dn[y];                         ADD(1);*/
     198   625867136 :             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   625867136 :             assert( sign[y] == sign_val_2 || sign[y] == -sign_val_2 );
     202             : 
     203             :             /* Compiler warning workaround (not instrumented) */
     204   625867136 :             assert( sgnx != 0 );
     205   625867136 :             alp2_16 = 0;
     206             : 
     207   625867136 :             alp2 = L_mac_o( alp1, cor[y], sign[y], &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
     208   625867136 :             if ( sgnx > 0 )
     209             :             {
     210   310840448 :                 alp2_16 = mac_ro( alp2, pR[y], sign[y], &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
     211             :             }
     212   625867136 :             if ( sgnx < 0 )
     213             :             {
     214   315026688 :                 alp2_16 = msu_ro( alp2, pR[y], sign[y], &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
     215             :             }
     216   625867136 :             alpk[1 - ik] = alp2_16; /* Qalp */
     217   625867136 :             move16();
     218             : 
     219             :             /*sq = ps2 * ps2;                            MULT(1);*/
     220   625867136 :             sq = mult_r( ps2, ps2 ); /* (3+3)Q -> 6Q9 */
     221   625867136 :             sqk[1 - ik] = sq;        /* Q9 */
     222   625867136 :             move16();
     223             : 
     224             : 
     225             :             /*s = (alpk * sq) - (sqk * alp2);            MULT(1);MAC(1);*/
     226   625867136 :             s = L_msu_o( L_mult( alpk[ik], sq ), sqk[ik], alp2_16, &Overflow ); /* Q_sq = Q_sqk, Q_alpk = Q_alp */
     227   625867136 :             if ( s > 0 )
     228             :             {
     229    35823633 :                 ik = sub( 1, ik );
     230             :             }
     231   625867136 :             if ( s > 0 )
     232             :             {
     233    35823633 :                 xy_save = L_mac0( y, x, L_SUBFR ); /* Q0 */
     234             :             }
     235   625867136 :             assert( ( ( s >= 0 && i == 0 && y == track_y ) ) || ( y > track_y ) || ( i > 0 ) );
     236             :         }
     237             :     }
     238     6211675 :     ps1 = extract_l( xy_save );
     239     6211675 :     pos[1] = s_and( ps1, L_SUBFR - 1 );
     240     6211675 :     move16();
     241     6211675 :     pos[0] = lshr( ps1, 6 ); /* Q0 */
     242     6211675 :     move16();
     243             :     /* Update numerator */
     244     6211675 :     *ps = add( add( ps0, dn[pos[0]] ), dn[pos[1]] ); /* Qdn */
     245     6211675 :     move16();
     246             : 
     247             :     /* Update denominator */
     248     6211675 :     *alp = alpk[ik]; /* Q_alp */
     249     6211675 :     move16();
     250             : 
     251     6211675 :     E_ACELP_update_cor_fx( pos, 2, sign, R, cor, cor );
     252             : 
     253     6211675 :     *ix = pos[0]; /* Q0 */
     254     6211675 :     move16();
     255     6211675 :     *iy = pos[1]; /* Q0 */
     256     6211675 :     move16();
     257             : 
     258     6211675 :     assert( ( ( pos[0] & 3 ) == track_x ) && ( ( pos[1] & 3 ) == track_y ) ); /* sanity check */
     259     6211675 : }
     260             : 
     261             : /*--------------------------------------------------------------------------------------*
     262             :  * E_ACELP_1pulse_searchx
     263             :  *--------------------------------------------------------------------------------------*/
     264      606701 : 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      606701 :     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      606701 :     move16();
     284             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     285      606701 :     Flag Overflow = 0;
     286      606701 :     move32();
     287             : #endif
     288             :     /* save these to limit memory searches */
     289             :     /*alp0 = *alp + R[0];                              INDIRECT(1);*/
     290      606701 :     ps0 = *ps; /* Qdn */
     291      606701 :     move16();
     292      606701 :     alp0 = L_deposit_h( *alp );             /* Q22 */
     293      606701 :     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      606701 :     move16();
     297      606701 :     move16();
     298      606701 :     alpk[0] = 1;
     299      606701 :     sqk[0] = -1;
     300      606701 :     ik = 0;
     301      606701 :     move16();
     302      606701 :     if ( mac_ro( alp0, cor[tracks[0]], sign[tracks[0]], &Overflow ) < 0 )
     303             :     {
     304           0 :         sqk[0] = 1;
     305           0 :         move16();
     306             :     }
     307             : 
     308      606701 :     x_save = tracks[0]; /* Q0 */
     309      606701 :     move16();
     310             : 
     311      606701 :     ntracks = 1;
     312      606701 :     move16();
     313      606701 :     if ( NE_16( tracks[1], tracks[0] ) )
     314             :     {
     315      158934 :         ntracks = 2;
     316      158934 :         move16();
     317             :     }
     318     1372336 :     FOR( t = 0; t < ntracks; ++t )
     319             :     {
     320    13015795 :         FOR( x = tracks[t]; x < L_SUBFR; x += 4 )
     321             :         {
     322             :             /* ps1 = ps0 + dn[x];                             ADD(1);*/
     323    12250160 :             ps1 = add( ps0, dn[x] );
     324             :             /* alp1 = alp0 + 2*sign[x]*cor[x];                MAC(1); MULT(1);*/
     325    12250160 :             assert( sign[x] == sign_val_1 << 1 || sign[x] == -( sign_val_1 << 1 ) );
     326    12250160 :             alp1 = mac_ro( alp0, cor[x], sign[x], &Overflow ); /* Qalp = (Q_R=Q_cor)*Q_signval */
     327    12250160 :             alpk[1 - ik] = alp1;                               /* Qalp */
     328    12250160 :             move16();
     329             : 
     330             : 
     331             :             /*sq = ps1 * ps1;                                MULT(1);*/
     332    12250160 :             sq = mult_r( ps1, ps1 ); /* 6Q9 */
     333    12250160 :             sqk[1 - ik] = sq;        /* Q9 */
     334    12250160 :             move16();
     335             : 
     336             :             /*s = (alpk[ik] * sq) - (sqk[ik] * alp1);                MULT(1);MAC(1);*/
     337    12250160 :             s = L_msu_o( L_mult_o( alpk[ik], sq, &Overflow ), sqk[ik], alp1, &Overflow ); /* Q9+Qalp+1 */
     338    12250160 :             if ( s > 0 )
     339             :             {
     340     2210159 :                 ik = sub( 1, ik );
     341             :             }
     342    12250160 :             if ( s > 0 )
     343             :             {
     344     2210159 :                 x_save = x;
     345     2210159 :                 move16();
     346             :             }
     347    12250160 :             assert( t > 0 || ( ( s >= 0 ) && ( x == tracks[t] ) ) || x > tracks[t] );
     348             :         }
     349             :     }
     350             : 
     351      606701 :     *ps = add( ps0, dn[x_save] ); /* Qdn */
     352      606701 :     move16();
     353      606701 :     *alp = alpk[ik]; /* Qalp */
     354      606701 :     move16();
     355      606701 :     *ix = x_save; /* Q0 */
     356      606701 :     move16();
     357      606701 : }
     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        6452 : 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        6452 :     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        6452 :     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        6452 :     move16();
     387        6452 :     move16();
     388             : 
     389        6452 :     ps = 0; /* to avoid compilation warnings */
     390        6452 :     move16();
     391             : 
     392             : 
     393        6452 :     alp = config->alp; /* Q13 */
     394        6452 :     move16();
     395        6452 :     nb_pulse = config->nb_pulse;
     396        6452 :     move16();
     397        6452 :     move16();
     398        6452 :     nb_pulse_m2 = sub( nb_pulse, 2 );
     399             : 
     400             :     /* Init to avoid crash when the search does not find a solution */
     401       82476 :     FOR( k = 0; k < nb_pulse; k++ )
     402             :     {
     403       76024 :         codvec[k] = k;
     404       76024 :         move16();
     405             :     }
     406             : 
     407        6452 :     scale = 0;
     408        6452 :     move16();
     409        6452 :     s = L_mult0( Rw[0], Rw[0] ); /*Q18*/
     410      412928 :     FOR( i = 1; i < L_SUBFR; i++ )
     411             :     {
     412      406476 :         s = L_mac0( s, Rw[i], Rw[i] ); /*Q18*/
     413             :     }
     414        6452 :     if ( s_and( (Word16) GE_16( nb_pulse, 9 ), (Word16) GT_32( s, 0x800000 ) ) )
     415             :     {
     416        3041 :         scale = -1;
     417        3041 :         move16();
     418             :     }
     419        6452 :     if ( s_and( (Word16) GE_16( nb_pulse, 13 ), (Word16) GT_32( s, 0x4000000 ) ) )
     420             :     {
     421         361 :         scale = -2;
     422         361 :         move16();
     423             :     }
     424        6452 :     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        6452 :     if ( s_and( (Word16) GE_16( nb_pulse, 28 ), (Word16) GT_32( s, 0x800000 ) ) )
     443             :     {
     444           0 :         scale = -3;
     445           0 :         move16();
     446             :     }
     447        6452 :     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        6452 :     R = R_buf + L_SUBFR - 1;
     455        6452 :     Copy_Scale_sig( Rw, R, L_SUBFR, scale ); /*Q9+scale*/
     456      412928 :     FOR( k = 1; k < L_SUBFR; k++ )
     457             :     {
     458      406476 :         R[-k] = R[k];
     459      406476 :         move16();
     460             :     }
     461             : 
     462             :     /* Sign value */
     463        6452 :     sign_val_2 = 0x2000; /* Q15 */
     464        6452 :     move16();
     465        6452 :     if ( GE_16( nb_pulse, 24 ) )
     466             :     {
     467           0 :         sign_val_2 = shr( sign_val_2, 1 ); /* Q15 */
     468             :     }
     469        6452 :     sign_val_1 = shr( sign_val_2, 1 ); /* Q15 */
     470             : 
     471             :     /*
     472             :      * Find sign for each pulse position.
     473             :      */
     474        6452 :     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        6452 :     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        6452 :     ps2k = -1;
     487        6452 :     move16();
     488        6452 :     alpk = 1;
     489        6452 :     move16();
     490             : 
     491             :     /* Number of iterations */
     492       25814 :     FOR( k = 0; k < config->nbiter; k++ )
     493             :     {
     494       19362 :         E_ACELP_setup_pulse_search_pos( config, k, ipos );
     495             : 
     496             :         /* index to first non-fixed position */
     497       19362 :         pos = config->fixedpulses; /* Q0 */
     498       19362 :         move16();
     499             : 
     500       19362 :         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       19362 :             assert( config->fixedpulses == 2 || config->fixedpulses == 4 );
     511             : 
     512             :             /* set fixed positions */
     513       77390 :             FOR( i = 0; i < pos; ++i )
     514             :             {
     515       58028 :                 ind[i] = pos_max[ipos[i]]; /* Q0 */
     516       58028 :                 move16();
     517             :             }
     518             : 
     519             :             /* multiplication of autocorrelation with signed fixed pulses */
     520       19362 :             E_ACELP_update_cor_fx( ind, config->fixedpulses, sign, R, NULL, cor );
     521             : 
     522             :             /* normalisation contribution of fixed part */
     523       19362 :             s = L_mult0( cor[ind[0]], sign[ind[0]] ); /* Q22 */
     524       19362 :             ps = dn[ind[0]];                          /* Qdn */
     525       19362 :             move16();
     526       58028 :             FOR( i = 1; i < pos; ++i )
     527             :             {
     528       38666 :                 s = L_mac0( s, cor[ind[i]], sign[ind[i]] ); /*Q12+Q9+1=Q22 */
     529       38666 :                 ps = add( ps, dn[ind[i]] );                 /* Qdn */
     530             :             }
     531       19362 :             alp = round_fx( s ); /*mac0 >>1 sign = 2 Q6*/
     532             :         }
     533             : 
     534             :         /* other stages of 2 pulses */
     535       19362 :         st = 0;
     536       19362 :         move16();
     537      106812 :         FOR( j = pos; j < nb_pulse; j += 2 )
     538             :         {
     539       87450 :             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       85506 :                 E_ACELP_2pulse_searchx_fx( config->nbpos[st], ipos[j], ipos[j + 1], R, &ps, &alp,
     548       85506 :                                            &ind[j], &ind[j + 1], dn, dn2_pos, cor, sign, sign_val_2 );
     549             :             }
     550             :             ELSE /* single pulse search */
     551             :             {
     552        1944 :                 E_ACELP_1pulse_searchx_fx( &ipos[j], R, &ps, &alp,
     553        1944 :                                            &ind[j], dn, cor, sign, sign_val_1 );
     554             :             }
     555             : 
     556             : 
     557       87450 :             st = add( st, 1 );
     558             :         }
     559             : 
     560             :         /* memorise the best codevector */
     561             :         /*ps2 = ps * ps;                                            MULT(1);*/
     562       19362 :         ps2 = mult( ps, ps ); /* 2*Qdn+1 */
     563             : 
     564             :         /*s = (alpk * ps2) - (ps2k * alp);                          MULT(2);ADD(1);*/
     565       19362 :         s = L_msu( L_mult( alpk, ps2 ), ps2k, alp ); /* 2*Qdn+8 */
     566             : 
     567       19362 :         IF( s > 0 )
     568             :         {
     569       11635 :             ps2k = ps2;
     570       11635 :             move16();
     571       11635 :             alpk = alp;
     572       11635 :             move16();
     573       11635 :             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        6452 :     E_ACELP_build_code( nb_pulse, codvec, sign, code, ind );
     582        6452 : }
     583             : 
     584      387612 : 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      387612 :     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      387612 :     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      387612 :     move16();
     610      387612 :     move16();
     611             : 
     612      387612 :     psk = ps = 0; /* to avoid compilation warnings */
     613      387612 :     move16();
     614      387612 :     move16();
     615             : 
     616             : 
     617      387612 :     alp = config->alp; /* Q13 */
     618      387612 :     move16();
     619      387612 :     nb_pulse = config->nb_pulse;
     620      387612 :     move16();
     621      387612 :     nb_pulse_m2 = sub( nb_pulse, 2 );
     622             : 
     623             :     /* Init to avoid crash when the search does not find a solution */
     624     5267450 :     FOR( k = 0; k < nb_pulse; k++ )
     625             :     {
     626     4879838 :         codvec[k] = s_and( k, 3 );
     627     4879838 :         move16();
     628             :     }
     629             : 
     630      387612 :     scale = 0;
     631      387612 :     move16();
     632      387612 :     s = L_mult0( Rw[0], Rw[0] ); /* Q18 */
     633    24807168 :     FOR( i = 1; i < L_SUBFR; i++ )
     634             :     {
     635    24419556 :         s = L_mac0( s, Rw[i], Rw[i] ); /* Q18 */
     636             :     }
     637      387612 :     if ( s_and( (Word16) GE_16( nb_pulse, 9 ), (Word16) GT_32( s, 0x800000 ) ) )
     638             :     {
     639      288637 :         scale = -1;
     640      288637 :         move16();
     641             :     }
     642      387612 :     if ( s_and( (Word16) GE_16( nb_pulse, 13 ), (Word16) GT_32( s, 0x4000000 ) ) )
     643             :     {
     644       48056 :         scale = -2;
     645       48056 :         move16();
     646             :     }
     647      387612 :     IF( GE_16( nb_pulse, 18 ) )
     648             :     {
     649       53848 :         if ( GT_32( s, 0x200000 ) )
     650             :         {
     651       53848 :             scale = -1;
     652       53848 :             move16();
     653             :         }
     654       53848 :         if ( GT_32( s, 0x400000 ) )
     655             :         {
     656       53848 :             scale = -2;
     657       53848 :             move16();
     658             :         }
     659       53848 :         if ( GT_32( s, 0x4000000 ) )
     660             :         {
     661       13942 :             scale = -3;
     662       13942 :             move16();
     663             :         }
     664             :     }
     665      387612 :     if ( s_and( (Word16) GE_16( nb_pulse, 28 ), (Word16) GT_32( s, 0x800000 ) ) )
     666             :     {
     667         463 :         scale = -3;
     668         463 :         move16();
     669             :     }
     670      387612 :     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      387612 :     R = R_buf + L_SUBFR - 1;
     678      387612 :     Copy_Scale_sig( Rw, R, L_SUBFR, scale ); /* Q9 + scale */
     679    24807168 :     FOR( k = 1; k < L_SUBFR; k++ )
     680             :     {
     681    24419556 :         R[-k] = R[k];
     682    24419556 :         move16();
     683             :     }
     684             : 
     685             :     /* Sign value */
     686      387612 :     sign_val_2 = 0x2000; /* Q15 */
     687      387612 :     move16();
     688      387612 :     if ( GE_16( nb_pulse, 24 ) )
     689             :     {
     690       25228 :         sign_val_2 = shr( sign_val_2, 1 ); /* Q15 */
     691             :     }
     692      387612 :     sign_val_1 = shr( sign_val_2, 1 ); /* Q15 */
     693             : 
     694             :     /*
     695             :      * Find sign for each pulse position.
     696             :      */
     697      387612 :     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      387612 :     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      387612 :     ps2k = -1;
     710      387612 :     move16();
     711      387612 :     alpk = 1;
     712      387612 :     move16();
     713             : 
     714             :     /* Number of iterations */
     715     1767878 :     FOR( k = 0; k < config->nbiter; k++ )
     716             :     {
     717     1380266 :         E_ACELP_setup_pulse_search_pos( config, k, ipos );
     718             : 
     719             :         /* index to first non-fixed position */
     720     1380266 :         pos = config->fixedpulses; /* Q0 */
     721     1380266 :         move16();
     722             : 
     723     1380266 :         IF( config->fixedpulses == 0 ) /* 1100, 11, 1110, 1111, 2211 */
     724             :         {
     725      105498 :             ps = 0;
     726      105498 :             move16();
     727      105498 :             alp = 0;
     728      105498 :             move16();
     729      105498 :             set16_fx( cor, 0, L_SUBFR );
     730             :         }
     731             :         ELSE
     732             :         {
     733     1274768 :             assert( config->fixedpulses == 2 || config->fixedpulses == 4 );
     734             : 
     735             :             /* set fixed positions */
     736     5116486 :             FOR( i = 0; i < pos; ++i )
     737             :             {
     738     3841718 :                 ind[i] = pos_max[ipos[i]]; /* Q0 */
     739     3841718 :                 move16();
     740             :             }
     741             : 
     742             :             /* multiplication of autocorrelation with signed fixed pulses */
     743     1274768 :             E_ACELP_update_cor_fx( ind, config->fixedpulses, sign, R, NULL, cor );
     744             : 
     745             :             /* normalisation contribution of fixed part */
     746     1274768 :             s = L_mult0( cor[ind[0]], sign[ind[0]] ); /* Q22 */
     747     1274768 :             ps = dn[ind[0]];                          /* Qdn */
     748     1274768 :             move16();
     749     3841718 :             FOR( i = 1; i < pos; ++i )
     750             :             {
     751     2566950 :                 s = L_mac0( s, cor[ind[i]], sign[ind[i]] ); /*Q12+Q9+1=Q22 */
     752     2566950 :                 ps = add( ps, dn[ind[i]] );
     753             :             }
     754     1274768 :             alp = round_fx( s ); /*mac0 >>1 sign = 2 Q6*/
     755             :         }
     756             : 
     757             :         /* other stages of 2 pulses */
     758     1380266 :         st = 0;
     759     1380266 :         move16();
     760     8111192 :         FOR( j = pos; j < nb_pulse; j += 2 )
     761             :         {
     762     6730926 :             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     6126169 :                 E_ACELP_2pulse_searchx_fx( config->nbpos[st], ipos[j], ipos[j + 1], R, &ps, &alp,
     771     6126169 :                                            &ind[j], &ind[j + 1], dn, dn2_pos, cor, sign, sign_val_2 );
     772             :             }
     773             :             ELSE /* single pulse search */
     774             :             {
     775      604757 :                 E_ACELP_1pulse_searchx_fx( &ipos[j], R, &ps, &alp,
     776      604757 :                                            &ind[j], dn, cor, sign, sign_val_1 );
     777             :             }
     778             : 
     779     6730926 :             IF( GT_16( alp, ONE_IN_Q14 ) )
     780             :             {
     781        1802 :                 alp = shr( alp, 1 );
     782        1802 :                 Scale_sig( cor, L_SUBFR, -1 );           /*Q8*/
     783        1802 :                 Scale_sig( R_buf, 2 * L_SUBFR - 1, -1 ); /*Q8+scale*/
     784        1802 :                 Scale_sig( dn, L_SUBFR, -1 );            /*Qdn-1*/
     785             :             }
     786             : 
     787             : 
     788     6730926 :             st = add( st, 1 );
     789             :         }
     790             : 
     791             :         /* memorise the best codevector */
     792             :         /*ps2 = ps * ps;                                            MULT(1);*/
     793     1380266 :         ps2 = mult( ps, ps ); /* 2*Qdn+1 */
     794             : 
     795             :         /*s = (alpk * ps2) - (ps2k * alp);                          MULT(2);ADD(1);*/
     796     1380266 :         s = L_msu( L_mult( alpk, ps2 ), ps2k, alp ); /* 2*Qdn+8 */
     797             : 
     798     1380266 :         IF( s > 0 )
     799             :         {
     800      755874 :             ps2k = ps2;
     801      755874 :             move16();
     802      755874 :             psk = ps;
     803      755874 :             move16();
     804      755874 :             alpk = alp;
     805      755874 :             move16();
     806      755874 :             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      387612 :     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      387612 :         set16_fx( code, 0, L_SUBFR );
     822      387612 :         set16_fx( ind, -1, NPMAXPT * 4 );
     823             : 
     824     5267450 :         FOR( k = 0; k < config->nb_pulse; k++ )
     825             :         {
     826     4879838 :             i = codvec[k]; /* read pulse position  Q0*/
     827     4879838 :             move16();
     828     4879838 :             val = sign[i]; /* read sign            Q13*/
     829     4879838 :             move16();
     830             : 
     831     4879838 :             index = shr( i, 2 ); /* pos of pulse (0..15) */
     832             :             // track = i % 4;
     833     4879838 :             track = s_and( i, 3 );
     834     4879838 :             IF( L_mult0( val, psk ) > 0 )
     835             :             {
     836     2409740 :                 code[i] = add( code[i], ONE_IN_Q9 /*1.0f*/ ); /* Q9 */
     837     2409740 :                 move16();
     838     2409740 :                 codvec[k] = add( codvec[k], 2 * L_SUBFR ); /* Q0 */
     839     2409740 :                 move16();
     840             :             }
     841             :             ELSE
     842             :             {
     843     2470098 :                 code[i] = sub( code[i], ONE_IN_Q9 /*1.0f*/ ); /* Q9 */
     844     2470098 :                 move16();
     845     2470098 :                 index = add( index, 16 ); /* Q0 */
     846             :             }
     847             : 
     848     4879838 :             i = imult1616( track, NPMAXPT );
     849    11401639 :             WHILE( ind[i] >= 0 )
     850             :             {
     851     6521801 :                 i++;
     852             :             }
     853             : 
     854     4879838 :             ind[i] = index;
     855     4879838 :             move16();
     856             :         }
     857             :     }
     858      387612 : }

Generated by: LCOV version 1.14