LCOV - code coverage report
Current view: top level - lib_enc - enc_gain_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ 22b74eaeaa63d28e0fcc8ed21c8f7c451f461847 Lines: 129 158 81.6 %
Date: 2025-10-18 02:19:22 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include <assert.h>
       6             : #include <stdint.h>
       7             : #include "options.h"
       8             : #include "cnst.h"
       9             : #include "rom_com.h"
      10             : #include "rom_enc.h"
      11             : #include "basop_util.h"
      12             : #include "prot_fx.h"     /* Function prototypes                    */
      13             : #include "prot_fx_enc.h" /* Function prototypes                    */
      14             : 
      15             : 
      16             : /*
      17             :  * E_GAIN_norm_corr
      18             :  *
      19             :  * Parameters:
      20             :  *    exc            I: excitation buffer (Q_new)
      21             :  *    xn             I: target signal (Q_new+shift-1)
      22             :  *    h              I: weighted synthesis filter impulse response (Q14+shift)
      23             :  *    t0_min         I: minimum value in the searched range
      24             :  *    t0_max         I: maximum value in the searched range
      25             :  *    corr_norm      O: normalized correlation (Q15+(Q_new+shift-1)+scale)
      26             :  *
      27             :  * Function:
      28             :  *    Find the normalized correlation between the target vector and the
      29             :  *    filtered past excitation (correlation between target and filtered
      30             :  *    excitation divided by the square root of energy of filtered excitation)
      31             :  *    Size of subframe = L_SUBFR.
      32             :  *
      33             :  * Returns:
      34             :  *    void
      35             :  */
      36             : 
      37        3060 : static void E_GAIN_norm_corr_fx(
      38             :     Word16 exc[] /*Q_new*/,
      39             :     Word16 xn[] /*(Q_new+shift-1)*/,
      40             :     Word16 h[] /*(Q14+shift)*/,
      41             :     Word16 t_min,
      42             :     Word16 t_max,
      43             :     Word16 corr_norm[] /*(Q15+(Q_new+shift-1)+scale)*/,
      44             :     Word16 L_subfr )
      45             : {
      46             :     Word16 excf[L_SUBFR]; /* filtered past excitation (Q_new+shift-1) */
      47             :     Word16 ps, norm, exp_alp, exp_ps, scale, L_subfr2;
      48             :     Word16 t, j, k;
      49             :     Word32 L_tmp, L_tmp2;
      50             : 
      51        3060 :     k = negate( t_min );
      52        3060 :     L_subfr2 = shr( L_subfr, 1 );
      53             : 
      54             :     /* compute the filtered excitation for the first delay t_min */
      55        3060 :     E_UTIL_f_convolve( &exc[k], h, excf, L_subfr );
      56             : 
      57             :     /* Compute rounded down 1/sqrt(energy of xn[]) */
      58        3060 :     Dot_product12_offs( xn, xn, L_subfr, &scale, 1 );
      59             : 
      60        3060 :     scale = add( scale, 2 + 1 ); /* energy of xn[] x 2 + rounded up     */
      61        3060 :     move16();
      62        3060 :     scale = negate( shr( scale, 1 ) ); /* (1<<scale) < 1/sqrt(energy rounded) */
      63             : 
      64             :     /* loop for every possible period */
      65       82957 :     FOR( t = t_min; t < t_max; t++ )
      66             :     {
      67             :         /* Compute correlation between xn[] and excf[] */
      68             : 
      69             :         /*for (j = 0; j < L_subfr; j++)
      70             :         {
      71             :            ps  += xn[j] * excf[j];                                          MAC(1);
      72             :            alp += excf[j] * excf[j];                                        MAC(1);
      73             :         }*/
      74       79897 :         L_tmp = Dot_product12_offs( xn, excf, L_subfr, &exp_ps, 1 ); /*Q31 + 2x(Q_new+shift-1) - exp_ps*/
      75       79897 :         ps = extract_h( L_tmp );                                     /* Scaling of ps = 15 + 2x(Q_new+shift-1) - exp_ps */
      76             : 
      77             : 
      78             :         /* Compute 1/sqrt(energy of excf[]) */
      79       79897 :         L_tmp = Dot_product12_offs( excf, excf, L_subfr2, NULL, 1 );
      80       79897 :         L_tmp2 = Dot_product12_offs( excf + L_subfr2, excf + L_subfr2, L_subfr2, NULL, 1 );
      81       79897 :         exp_alp = sub( s_min( norm_l( L_tmp ), norm_l( L_tmp2 ) ), 1 );
      82       79897 :         L_tmp = L_add( L_shl( L_tmp, exp_alp ), L_shl( L_tmp2, exp_alp ) );
      83       79897 :         exp_alp = sub( 31 + 1, exp_alp );
      84             : 
      85             :         /*norm = (Float32)(1.0F / sqrt(alp));                                 SQRT(1);*/
      86       79897 :         L_tmp = ISqrt32( L_tmp, &exp_alp ); /*Q31 - (Q_new+shift-1) - exp_alp*/
      87       79897 :         norm = extract_h( L_tmp );          /* Scaling of norm = 15 - (Q_new+shift-1) - exp_alp */
      88             : 
      89             :         /* Normalize correlation = correlation * (1/sqrt(energy)) */
      90             :         /*corr_norm[t-t_min] = ps * norm;                                     MULT(1); STORE(1);*/
      91       79897 :         L_tmp = L_mult( ps, norm ); /*Q31 + (Q_new+shift-1) - (exp_ps + exp_alp)*/
      92       79897 :         L_tmp = L_shl( L_tmp, add( add( exp_ps, exp_alp ), scale ) );
      93             : 
      94       79897 :         corr_norm[t - t_min] = round_fx( L_tmp ); /* Scaling of corr_norm = 15 + (Q_new+shift-1) + scale */
      95             : 
      96             :         /* update the filtered excitation excf[] for the next iteration */
      97       79897 :         k = sub( k, 1 );
      98             : 
      99     5113408 :         FOR( j = L_subfr - 1; j > 0; j-- )
     100             :         {
     101             :             /*excf[j] = excf[j - 1] + exc[k] * h[j];                           MAC(1); STORE(1);*/
     102             :             /* saturation can occur in add() */
     103     5033511 :             excf[j] = add( mult_r( exc[k], h[j] ), excf[j - 1] ); /*Q_new + (Q14+shift) - 15*/
     104     5033511 :             move16();
     105             :         }
     106       79897 :         excf[0] = mult_r( exc[k], h[0] ); /*Q_new + (Q14+shift) - 15*/
     107       79897 :         move16();
     108             :     }
     109             :     /* Last reduced iteration for t=t_max */
     110        3060 :     L_tmp = Dot_product12_offs( xn, excf, L_subfr, &exp_ps, 1 ); /*Q31 + 2x(Q_new+shift-1) - exp_ps*/
     111        3060 :     ps = extract_h( L_tmp );                                     /*Q15 + 2x(Q_new+shift-1) - exp_ps*/
     112             : 
     113             : 
     114             :     /* Compute 1/sqrt(energy of excf[]) */
     115        3060 :     L_tmp = Dot_product12_offs( excf, excf, L_subfr2, NULL, 1 );
     116        3060 :     L_tmp2 = Dot_product12_offs( excf + L_subfr2, excf + L_subfr2, L_subfr2, NULL, 1 );
     117        3060 :     exp_alp = sub( s_min( norm_l( L_tmp ), norm_l( L_tmp2 ) ), 1 );
     118        3060 :     L_tmp = L_add( L_shl( L_tmp, exp_alp ), L_shl( L_tmp2, exp_alp ) );
     119        3060 :     exp_alp = sub( 31 + 1, exp_alp );
     120             : 
     121             : 
     122             :     /*norm = (Float32)(1.0F / sqrt(alp));                                 SQRT(1);*/
     123        3060 :     L_tmp = ISqrt32( L_tmp, &exp_alp ); /*Q31 - (Q_new+shift-1) - exp_alp*/
     124        3060 :     norm = extract_h( L_tmp );          /*15 - (Q_new+shift-1) - exp_alp */
     125             : 
     126             :     /* Normalize correlation = correlation * (1/sqrt(energy)) */
     127             :     /*corr_norm[t-t_min] = ps * norm;                                     MULT(1); STORE(1);*/
     128        3060 :     L_tmp = L_mult( ps, norm ); /*Q31 + (Q_new+shift-1) - (exp_ps + exp_alp)*/
     129        3060 :     L_tmp = L_shl( L_tmp, add( add( exp_ps, exp_alp ), scale ) );
     130        3060 :     corr_norm[t - t_min] = round_fx( L_tmp ); /* 15 + (Q_new+shift-1) + scale */
     131             : 
     132        3060 :     return;
     133             : }
     134             : 
     135             : 
     136             : /*
     137             :  * E_GAIN_norm_corr_interpolate
     138             :  *
     139             :  * Parameters:
     140             :  *    x           I: input vector
     141             :  *    frac        I: fraction (-4..+3)
     142             :  *
     143             :  * Function:
     144             :  *    Interpolating the normalized correlation
     145             :  *
     146             :  * Returns:
     147             :  *    interpolated value
     148             :  */
     149           0 : static Word16 E_GAIN_norm_corr_interpolate_fx( Word16 *x /*Qx*/, Word16 frac /*Q0*/ )
     150             : {
     151             :     Word16 *x1, *x2, i;
     152             :     const Word16 *c1, *c2;
     153             :     Word32 s;
     154             : 
     155           0 :     IF( frac < 0 )
     156             :     {
     157           0 :         frac = add( frac, 4 ); /*Q0*/
     158           0 :         x--;
     159             :     }
     160             : 
     161           0 :     x1 = &x[0];                        /*Qx*/
     162           0 :     x2 = &x[1];                        /*Qx*/
     163           0 :     c1 = &E_ROM_inter4_1_fx[frac];     /*Q14*/
     164           0 :     c2 = &E_ROM_inter4_1_fx[4 - frac]; /*Q14*/
     165             : 
     166             :     /*s = x1[0] * c1[0] + x2[0] * c2[0];
     167             :     s += x1[-1] * c1[4] + x2[1] * c2[4];
     168             :     s += x1[-2] * c1[8] + x2[2] * c2[8];
     169             :     s += x1[-3] * c1[12] + x2[3] * c2[12];*/
     170             : 
     171           0 :     s = L_deposit_l( 0 );
     172           0 :     FOR( i = 0; i < 4; i++ )
     173             :     {
     174           0 :         s = L_mac( s, *x1--, *c1 ); /* Qx + 15 */
     175           0 :         s = L_mac( s, *x2++, *c2 ); /* Qx + 15 */
     176           0 :         c1 += 4;
     177           0 :         c2 += 4;
     178             :     }
     179             : 
     180           0 :     return round_fx( L_shl( s, 1 ) ); /*Qx*/
     181             : }
     182             : 
     183       14609 : static Word16 E_GAIN_norm_corr_interpolate6_fx( Word16 *x /*Qx*/, Word16 frac /*Q0*/ )
     184             : {
     185             :     Word16 *x1, *x2, i;
     186             :     const Word16 *c1, *c2;
     187             :     Word32 s;
     188             : 
     189       14609 :     IF( frac < 0 )
     190             :     {
     191        5851 :         frac = add( frac, 6 ); /*Q0*/
     192        5851 :         x--;
     193             :     }
     194             : 
     195       14609 :     x1 = &x[0];                        /*Qx*/
     196       14609 :     x2 = &x[1];                        /*Qx*/
     197       14609 :     c1 = &E_ROM_inter6_1_fx[frac];     /*Q14*/
     198       14609 :     c2 = &E_ROM_inter6_1_fx[6 - frac]; /*Q14*/
     199             : 
     200             :     /*s = x1[0] * c1[0] + x2[0] * c2[0];
     201             :     s += x1[-1] * c1[6] + x2[1] * c2[6];
     202             :     s += x1[-2] * c1[12] + x2[2] * c2[12];
     203             :     s += x1[-3] * c1[18] + x2[3] * c2[18];*/
     204       14609 :     s = L_deposit_l( 0 );
     205       73045 :     FOR( i = 0; i < 4; i++ )
     206             :     {
     207       58436 :         s = L_mac( s, *x1--, *c1 ); /* Qx + 15 */
     208       58436 :         s = L_mac( s, *x2++, *c2 ); /* Qx + 15 */
     209       58436 :         c1 += 6;
     210       58436 :         c2 += 6;
     211             :     }
     212             : 
     213       14609 :     return round_fx( L_shl( s, 1 ) ); /*Qx*/
     214             : }
     215             : 
     216             : /*
     217             :  * E_GAIN_closed_loop_search_fx
     218             :  *
     219             :  * Parameters:
     220             :  *    exc            I: excitation buffer
     221             :  *    xn             I: target signal
     222             :  *    h              I: weighted synthesis filter impulse response
     223             :  *    dn             I: residual domain target signal
     224             :  *    t0_min         I: minimum value in the searched range
     225             :  *    t0_max         I: maximum value in the searched range
     226             :  *    pit_frac       O: chosen fraction
     227             :  *    i_subfr        I: flag to first subframe
     228             :  *    t0_fr2         I: minimum value for resolution 1/2
     229             :  *    t0_fr1         I: minimum value for resolution 1
     230             :  *
     231             :  * Function:
     232             :  *    Find the closed loop pitch period with 1/4 subsample resolution.
     233             :  *
     234             :  * Returns:
     235             :  *    chosen integer pitch lag
     236             :  */
     237        3060 : Word16 E_GAIN_closed_loop_search_fx( Word16 exc[],          /*Q_new*/
     238             :                                      Word16 xn[],           /*Q_xn*/
     239             :                                      Word16 h[],            /* Q14+shift */
     240             :                                      Word16 t0_min,         /*Q0*/
     241             :                                      Word16 t0_min_frac,    /*Q0*/
     242             :                                      Word16 t0_max,         /*Q0*/
     243             :                                      Word16 t0_max_frac,    /*Q0*/
     244             :                                      Word16 t0_min_max_res, /*Q0*/
     245             :                                      Word16 *pit_frac,      /*Q0*/
     246             :                                      Word16 *pit_res,       /*Q0*/
     247             :                                      Word16 pit_res_max,    /*Q0*/
     248             :                                      Word16 i_subfr,        /*Q0*/
     249             :                                      Word16 pit_min,        /*Q0*/
     250             :                                      Word16 pit_fr2,        /*Q0*/
     251             :                                      Word16 pit_fr1,        /*Q0*/
     252             :                                      Word16 L_subfr /*Q0*/ )
     253             : {
     254             :     Word16 corr_v[32 + 2 * L_INTERPOL1 + 1];
     255             :     Word16 cor_max, max, temp;
     256             :     Word16 *corr;
     257             :     Word16 i, fraction, frac1, frac2, step;
     258             :     Word16 t0, t_min, t_max;
     259             : 
     260        3060 :     set16_fx( corr_v, 0, 32 + 2 * L_INTERPOL1 + 1 );
     261             :     /* Find interval to compute normalized correlation */
     262        3060 :     if ( t0_min_frac > 0 )
     263             :     {
     264        2761 :         t0_min = add( t0_min, 1 );
     265        2761 :         move16();
     266             :     }
     267        3060 :     t_min = sub( t0_min, L_INTERPOL1 );
     268        3060 :     t_max = add( t0_max, L_INTERPOL1 );
     269        3060 :     move16();
     270        3060 :     move16();
     271             : 
     272             :     /* allocate memory to normalized correlation vector */
     273        3060 :     corr = &corr_v[negate( t_min )]; /* corr[t_min..t_max] */
     274             : 
     275             :     /* Compute normalized correlation between target and filtered excitation */
     276        3060 :     E_GAIN_norm_corr_fx( exc, xn, h, t_min, t_max, corr_v, L_subfr );
     277             : 
     278             :     /*  find integer pitch */
     279        3060 :     max = corr[t0_min]; /*(Q15+(Q_new+shift-1)+scale)*/
     280        3060 :     move16();
     281        3060 :     t0 = t0_min; /*Q0*/
     282        3060 :     move16();
     283             : 
     284       58477 :     FOR( i = t0_min + 1; i <= t0_max; i++ )
     285             :     {
     286             :         BASOP_SATURATE_WARNING_OFF_EVS;
     287       55417 :         if ( GE_16( corr[i], max ) )
     288             :         {
     289       20300 :             t0 = i;
     290       20300 :             move16();
     291             :         }
     292       55417 :         max = s_max( max, corr[i] );
     293             :         BASOP_SATURATE_WARNING_ON_EVS;
     294             :     }
     295             : 
     296             : 
     297             :     /* If first subframe and t0 >= pit_fr1, do not search fractionnal pitch */
     298        3060 :     test();
     299        3060 :     IF( ( i_subfr == 0 ) && GE_16( t0, pit_fr1 ) )
     300             :     {
     301         112 :         *pit_frac = 0;
     302         112 :         move16();
     303         112 :         *pit_res = 1;
     304         112 :         move16();
     305         112 :         return ( t0 );
     306             :     }
     307             : 
     308             : 
     309             :     /*
     310             :      * Search fractionnal pitch
     311             :      * Test the fractions around t0 and choose the one which maximizes
     312             :      * the interpolated normalized correlation.
     313             :      */
     314             : 
     315        2948 :     IF( EQ_16( t0_min_max_res, shr( pit_res_max, 1 ) ) )
     316             :     {
     317        2948 :         t0_min_frac = shl( t0_min_frac, 1 ); /*Q0*/
     318        2948 :         t0_max_frac = shl( t0_max_frac, 1 ); /*Q0*/
     319             :     }
     320             : 
     321        2948 :     step = 1;
     322        2948 :     move16();
     323        2948 :     frac1 = sub( 1, pit_res_max ); /*Q0*/
     324        2948 :     frac2 = sub( pit_res_max, 1 ); /*Q0*/
     325             : 
     326        2948 :     test();
     327        2948 :     test();
     328        2948 :     IF( ( ( i_subfr == 0 ) && GE_16( t0, pit_fr2 ) ) || LE_16( pit_fr2, pit_min ) )
     329             :     {
     330        2948 :         step = 2;
     331        2948 :         move16();
     332        2948 :         frac1 = sub( 2, pit_res_max ); /*Q0*/
     333        2948 :         frac2 = sub( pit_res_max, 2 ); /*Q0*/
     334             :     }
     335        2948 :     test();
     336        2948 :     IF( ( EQ_16( t0, t0_min ) ) && ( t0_min_frac == 0 ) )
     337             :     {
     338          10 :         frac1 = t0_min_frac; /*Q0*/
     339          10 :         move16();
     340             :     }
     341             :     ELSE
     342             :     {
     343        2938 :         test();
     344        2938 :         IF( ( EQ_16( t0, t0_min ) ) && ( LT_16( add( frac1, pit_res_max ), t0_min_frac ) ) )
     345             :         {
     346          25 :             frac1 = sub( t0_min_frac, pit_res_max ); /*Q0*/
     347             :         }
     348             :     }
     349             : 
     350        2948 :     if ( EQ_16( t0, t0_max ) )
     351             :     {
     352          67 :         frac2 = t0_max_frac; /*Q0*/
     353          67 :         move16();
     354             :     }
     355        2948 :     assert( frac1 <= 0 && frac2 >= 0 && frac2 > frac1 );
     356             : 
     357        2948 :     IF( EQ_16( pit_res_max, 6 ) )
     358             :     {
     359        2948 :         cor_max = E_GAIN_norm_corr_interpolate6_fx( &corr[t0], frac1 ); /*(Q15+(Q_new+shift-1)+scale)*/
     360        2948 :         fraction = frac1;                                               /*Q0*/
     361        2948 :         move16();
     362             : 
     363       14609 :         FOR( i = ( frac1 + step ); i <= frac2; i += step )
     364             :         {
     365       11661 :             temp = E_GAIN_norm_corr_interpolate6_fx( &corr[t0], i ); /*(Q15+(Q_new+shift-1)+scale)*/
     366       11661 :             IF( GT_16( temp, cor_max ) )
     367             :             {
     368        5850 :                 cor_max = temp; /*(Q15+(Q_new+shift-1)+scale)*/
     369        5850 :                 move16();
     370        5850 :                 fraction = i;
     371        5850 :                 move16();
     372             :             }
     373             :         }
     374             :     }
     375             :     ELSE
     376             :     {
     377           0 :         cor_max = E_GAIN_norm_corr_interpolate_fx( &corr[t0], frac1 ); /*(Q15+(Q_new+shift-1)+scale)*/
     378           0 :         fraction = frac1;                                              /*Q0*/
     379           0 :         move16();
     380             : 
     381           0 :         FOR( i = ( frac1 + step ); i <= frac2; i += step )
     382             :         {
     383           0 :             temp = E_GAIN_norm_corr_interpolate_fx( &corr[t0], i ); /*(Q15+(Q_new+shift-1)+scale)*/
     384           0 :             IF( GT_16( temp, cor_max ) )
     385             :             {
     386           0 :                 cor_max = temp; /*(Q15+(Q_new+shift-1)+scale)*/
     387           0 :                 move16();
     388           0 :                 fraction = i;
     389           0 :                 move16();
     390             :             }
     391             :         }
     392             :     }
     393             : 
     394             :     /* limit the fraction value */
     395        2948 :     IF( fraction < 0 )
     396             :     {
     397         769 :         fraction = add( fraction, pit_res_max ); /*Q0*/
     398         769 :         t0 = sub( t0, 1 );
     399             :     }
     400        2948 :     test();
     401        2948 :     test();
     402        2948 :     IF( ( ( i_subfr == 0 ) && GE_16( t0, pit_fr2 ) ) || LE_16( pit_fr2, pit_min ) )
     403             :     {
     404        2948 :         *pit_res = shr( pit_res_max, 1 ); /*Q0*/
     405        2948 :         move16();
     406        2948 :         *pit_frac = shr( fraction, 1 ); /*Q0*/
     407        2948 :         move16();
     408             :     }
     409             :     ELSE
     410             :     {
     411           0 :         *pit_res = pit_res_max; /*Q0*/
     412           0 :         move16();
     413           0 :         *pit_frac = fraction; /*Q0*/
     414           0 :         move16();
     415             :     }
     416        2948 :     return ( t0 );
     417             : }

Generated by: LCOV version 1.14