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

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : #include <stdint.h>
       5             : #include "options.h"    /* Compilation switches                   */
       6             : #include "cnst.h"       /* Common constants                       */
       7             : #include "rom_enc.h"    /* Encoder static table prototypes        */
       8             : #include "rom_com_fx.h" /* Encoder static table prototypes        */
       9             : #include "rom_com.h"    /* Encoder static table prototypes        */
      10             : #include "rom_dec.h"
      11             : //#include "prot_fx.h"       /* Function prototypes                    */
      12             : #include "prot_fx.h"     /* Function prototypes                    */
      13             : #include "prot_fx_enc.h" /* Function prototypes                    */
      14             : 
      15             : /*-------------------------------------------------------------------*
      16             :  * Local constants
      17             :  *-------------------------------------------------------------------*/
      18             : 
      19             : #define MAX_DELTA   16 /* half-length of the delta search      */
      20             : #define COR_BUF_LEN ( L_INTERPOL1 * 2 + MAX_DELTA * 2 + 1 )
      21             : 
      22             : /*-------------------------------------------------------------------*
      23             :  * pitch_ol2()
      24             :  *
      25             :  * Open-loop pitch precision improvement with 1/4 resolution
      26             :  * The pitch is searched in the interval <pitch_ol-delta, pitch_ol+delta),
      27             :  * i.e. the value pitch_ol + delta is not a part of the interval
      28             :  *-------------------------------------------------------------------*/
      29     1185168 : void pitch_ol2_fx(
      30             :     const Word16 pit_min,  /* i  : minimum pitch value (20 or 29)                   */
      31             :     const Word16 pitch_ol, /* i  : pitch to be improved                             */
      32             :     Word16 *pitch_fr_fx,
      33             :     /* o  : adjusted 1/4 fractional pitch                    */ /*Q7*/
      34             :     Word16 *voicing_fr_fx,
      35             :     /* o  : adjusted 1/4 fractional voicing                  */ /*Q15*/
      36             :     const Word16 pos,                                           /* i  : position in frame where to calculate the improv. */
      37             :     const Word16 *wsp_fx,
      38             :     /* i  : weighted speech for current frame and look-ahead */ /*Q_new-1+shift*/
      39             :     const Word16 delta                                          /* i  : delta for pitch search (2 or 7)                  */
      40             : )
      41             : {
      42             :     Word16 i, t, step, fraction, t0_min, t0_max, t_min, t_max;
      43             :     const Word16 *pt_wsp_fx;
      44             :     Word16 wsp_fr_fx[L_SUBFR];
      45             :     Word16 temp_fx, cor_max_fx, cor_fx[COR_BUF_LEN], *pt_cor_fx;
      46             :     Word32 cor_32[COR_BUF_LEN], *pt_cor_32, t0, t1;
      47             :     Word16 t0s, t1s;
      48             :     Word16 exp3;
      49             :     Word32 R1, R2;
      50             :     Word16 R0, exp_R0, exp_R1, exp_R2, j;
      51             :     Word16 pit_max;
      52             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
      53     1185168 :     Flag Overflow = 0;
      54     1185168 :     move32();
      55             : #endif
      56             : 
      57             :     /* initialization */
      58     1185168 :     pit_max = PIT_MAX;
      59     1185168 :     move16();
      60     1185168 :     t0_min = sub( pitch_ol, delta );
      61     1185168 :     t0_max = add( pitch_ol, sub( delta, 1 ) );
      62     1185168 :     t0_min = s_max( t0_min, pit_min );
      63     1185168 :     t_min = sub( t0_min, L_INTERPOL1 );
      64             : 
      65     1185168 :     t0_max = s_min( t0_max, pit_max );
      66     1185168 :     t_max = add( t0_max, L_INTERPOL1 );
      67             : 
      68     1185168 :     pt_wsp_fx = wsp_fx + pos;
      69     1185168 :     pt_cor_32 = cor_32;
      70     1185168 :     t1 = L_deposit_l( 0 );
      71    26642726 :     FOR( t = t_min; t <= t_max; t++ )
      72             :     {
      73    25457558 :         t0 = Dot_product( pt_wsp_fx, pt_wsp_fx - t, L_SUBFR );
      74    25457558 :         *pt_cor_32++ = t0;
      75    25457558 :         move32();
      76    25457558 :         t0 = L_abs( t0 );
      77    25457558 :         t1 = L_max( t1, t0 );
      78             :     }
      79     1185168 :     exp3 = norm_l( t1 );
      80     1185168 :     pt_cor_32 = cor_32;
      81     1185168 :     pt_cor_fx = cor_fx;
      82    26642726 :     FOR( t = t_min; t <= t_max; t++ )
      83             :     {
      84    25457558 :         t0 = L_shl_o( *pt_cor_32++, exp3, &Overflow );
      85    25457558 :         *pt_cor_fx++ = round_fx_o( t0, &Overflow );
      86    25457558 :         move16();
      87             :     }
      88             : 
      89     1185168 :     pt_cor_fx = cor_fx + L_INTERPOL1;
      90     1185168 :     cor_max_fx = *pt_cor_fx++;
      91     1185168 :     move16();
      92     1185168 :     t1s = t0_min;
      93     1185168 :     move16();
      94    15976214 :     FOR( t = t0_min + 1; t <= t0_max; t++ )
      95             :     {
      96    14791046 :         if ( GT_16( *pt_cor_fx, cor_max_fx ) )
      97             :         {
      98     5883465 :             t1s = t;
      99     5883465 :             move16();
     100             :         }
     101    14791046 :         cor_max_fx = s_max( cor_max_fx, *pt_cor_fx );
     102    14791046 :         pt_cor_fx++;
     103             :     }
     104             : 
     105             :     /*----------------------------------------------------------------*
     106             :      * Search fractionnal pitch with 1/4 subsample resolution.
     107             :      * search the fractions around t0 and choose the one which maximizes
     108             :      * the interpolated normalized correlation.
     109             :      *----------------------------------------------------------------*/
     110     1185168 :     pt_cor_fx = cor_fx + sub( L_INTERPOL1, t0_min );
     111     1185168 :     t0s = t1s;
     112     1185168 :     move16();
     113             : 
     114     1185168 :     step = 1;
     115     1185168 :     move16(); /* 1/4 subsample resolution */
     116     1185168 :     fraction = 1;
     117     1185168 :     move16();
     118             : 
     119     1185168 :     IF( NE_16( t0s, t0_min ) ) /* Process negative fractions */
     120             :     {
     121     1086411 :         t0s = sub( t0s, 1 );
     122     1086411 :         cor_max_fx = Interpol_4( &pt_cor_fx[t0s], fraction );
     123     3259233 :         FOR( i = fraction + step; i <= 3; i += step )
     124             :         {
     125     2172822 :             temp_fx = Interpol_4( &pt_cor_fx[t0s], i );
     126     2172822 :             if ( GT_16( temp_fx, cor_max_fx ) )
     127             :             {
     128     2033740 :                 fraction = i;
     129     2033740 :                 move16();
     130             :             }
     131     2172822 :             cor_max_fx = s_max( temp_fx, cor_max_fx );
     132             :         }
     133             :     }
     134             :     ELSE /* Limit case */
     135             :     {
     136       98757 :         fraction = 0;
     137       98757 :         move16();
     138       98757 :         cor_max_fx = Interpol_4( &pt_cor_fx[t0s], fraction );
     139       98757 :         move16();
     140             :     }
     141     5925840 :     FOR( i = 0; i <= 3; i += step ) /* Process positive fractions */
     142             :     {
     143     4740672 :         temp_fx = Interpol_4( &pt_cor_fx[t1s], i );
     144             : 
     145     4740672 :         IF( GT_16( temp_fx, cor_max_fx ) )
     146             :         {
     147     1377348 :             cor_max_fx = temp_fx;
     148     1377348 :             move16();
     149     1377348 :             fraction = i;
     150     1377348 :             move16();
     151     1377348 :             t0s = t1s;
     152     1377348 :             move16();
     153             :         }
     154             :     }
     155             : 
     156     1185168 :     *pitch_fr_fx = shl( add( shl( t0s, 2 ), fraction ), 4 );
     157     1185168 :     move16(); /*Q7*/
     158             : 
     159     1185168 :     IF( NE_32( t1, 1L ) )
     160             :     {
     161     1169449 :         pred_lt4( pt_wsp_fx, wsp_fr_fx, t0s, fraction, L_SUBFR, pitch_inter4_1, 4, PIT_UP_SAMP );
     162             : 
     163     1169449 :         R0 = cor_max_fx;
     164     1169449 :         move16();
     165     1169449 :         R1 = L_mult( pt_wsp_fx[0], pt_wsp_fx[0] );
     166     1169449 :         R2 = L_mult( wsp_fr_fx[0], wsp_fr_fx[0] );
     167    74844736 :         FOR( j = 1; j < L_SUBFR; j++ )
     168             :         {
     169    73675287 :             R1 = L_mac_sat( R1, pt_wsp_fx[j], pt_wsp_fx[j] );
     170    73675287 :             R2 = L_mac_sat( R2, wsp_fr_fx[j], wsp_fr_fx[j] );
     171             :         }
     172             : 
     173             :         /* *voicing_fr = cor_max * inv_sqrt(enr_wsp * enr_old) */
     174             :         /* *voicing_fr = R0 * inv_sqrt(R1 * R2) */
     175     1169449 :         exp_R0 = norm_s( R0 );
     176     1169449 :         R0 = shl( R0, exp_R0 );
     177             : 
     178     1169449 :         exp_R1 = norm_l( R1 );
     179     1169449 :         R1 = L_shl( R1, exp_R1 );
     180             : 
     181     1169449 :         exp_R2 = norm_l( R2 );
     182     1169449 :         R2 = L_shl( R2, exp_R2 );
     183             : 
     184     1169449 :         R1 = L_mult_o( round_fx_o( R1, &Overflow ), round_fx_o( R2, &Overflow ), &Overflow );
     185     1169449 :         i = norm_l( R1 );
     186     1169449 :         R1 = L_shl( R1, i );
     187             : 
     188     1169449 :         exp_R1 = add( exp_R1, exp_R2 );
     189     1169449 :         exp_R1 = add( exp_R1, i );
     190     1169449 :         exp_R1 = sub( 62, exp_R1 );
     191             : 
     192     1169449 :         R1 = Isqrt_lc( R1, &exp_R1 );
     193             : 
     194     1169449 :         R1 = L_mult( R0, round_fx_o( R1, &Overflow ) );
     195     1169449 :         exp_R0 = sub( 31, exp_R0 );
     196     1169449 :         exp_R0 = sub( add( exp_R0, exp_R1 ), exp3 );
     197             : 
     198     1169449 :         *voicing_fr_fx = round_fx_o( L_shl_o( R1, exp_R0, &Overflow ), &Overflow ); /*Q15*/
     199     1169449 :         move16();
     200             :     }
     201             :     ELSE
     202             :     {
     203       15719 :         *voicing_fr_fx = 0;
     204       15719 :         move16();
     205             :     }
     206             : 
     207     1185168 :     return;
     208             : }
     209             : 
     210             : /*-------------------------------------------------------------------*
     211             :  * StableHighPitchDetect()
     212             :  *
     213             :  * stable very short pitch detection
     214             :  *-------------------------------------------------------------------*/
     215        3100 : void StableHighPitchDetect_fx(
     216             :     Word16 *flag_spitch,       /* o  : flag to indicate very short stable pitch */
     217             :     Word16 pitch[],            /* i/o: OL pitch buffer                         */
     218             :     const Word16 voicing[],    /* i  : OL pitch gains                          */
     219             :     const Word16 wsp[],        /* i  : weighted speech                         */
     220             :     const Word16 localVAD,     /* i  : local VAD flag                          */
     221             :     Word16 *voicing_sm,        /* i/o: smoothed open-loop pitch gains          */
     222             :     Word16 *voicing0_sm,       /* i/o: smoothed high pitch gains               */
     223             :     Word16 *LF_EnergyRatio_sm, /* i/o: smoothed [0, 300Hz] relative peak energy*/
     224             :     Word16 *predecision_flag,  /* i/o: predecision flag                        */
     225             :     Word32 *diff_sm,           /* i/o: smoothed pitch frequency difference     */
     226             :     Word32 *energy_sm,         /* i/o: smoothed energy around pitch frequency  */
     227             :     Word16 Q_new,
     228             :     Word16 EspecdB[] )
     229             : {
     230             :     Word16 i, pitch_freq_point;
     231             :     Word16 T, Tp, pit_min;
     232             :     Word16 energy0_16, energy1_16, ratio, voicing_m;
     233             :     Word32 energy0, energy1, cor_max, diff, sum_energy;
     234             :     const Word16 *pt_wsp;
     235             :     Word16 tmp, tmp1, exp, diff16, cor_max16, exp1, exp2, pit_min_up;
     236             :     Word32 L_tmp, L_tmp1;
     237             :     Word16 Top;
     238             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     239        3100 :     Flag Overflow = 0;
     240        3100 :     move32();
     241             : #endif
     242             : 
     243             :     /*voicing = (voicing[0] + voicing[1] + voicing[2] )/3;*/
     244        3100 :     L_tmp = L_mult( voicing[0], 10923 /*1/3 in Q15*/ );
     245        3100 :     L_tmp = L_mac( L_tmp, voicing[1], 10923 /*1/3 in Q15*/ );
     246        3100 :     L_tmp = L_mac( L_tmp, voicing[2], 10923 /*1/3 in Q15*/ );
     247        3100 :     voicing_m = round_fx_sat( L_tmp );
     248             :     /**voicing_sm = 0.75f*(*voicing_sm) + 0.25f*voicing;*/
     249        3100 :     *voicing_sm = round_fx( L_mac( L_mult( *voicing_sm, 24576 /*0.75f Q15*/ ), voicing_m, 8192 /*0.25f Q15*/ ) );
     250        3100 :     move16();
     251             :     /* pitch_freq_point = (short)(L_FFT/(mult_fact*T_op[1])+0.5f);*/
     252        3100 :     Top = pitch[1];
     253        3100 :     move16();
     254        3100 :     exp = norm_s( Top );
     255        3100 :     tmp = div_s( shl( 1, sub( 14, exp ) ), Top );                                   /*Q(29 - exp)*/
     256        3100 :     L_tmp = L_mult0( tmp, L_FFT );                                                  /*Q(29 - exp)*/
     257        3100 :     pitch_freq_point = extract_h( L_add( L_shl( L_tmp, sub( exp, 13 ) ), 32768 ) ); /* Q0*/
     258        3100 :     diff = L_deposit_l( 0 );
     259        3100 :     sum_energy = L_deposit_l( 0 );
     260       29530 :     FOR( i = 1; i < 2 * pitch_freq_point; i++ )
     261             :     {
     262       26430 :         diff = L_add( diff, sub( EspecdB[pitch_freq_point], EspecdB[i] ) );
     263       26430 :         sum_energy = L_add( sum_energy, EspecdB[i] );
     264             :     }
     265             :     /*sum_energy /= (2*pitch_freq_point-1);*/
     266        3100 :     tmp = sub( shl( pitch_freq_point, 1 ), 1 );
     267        3100 :     exp = norm_s( tmp );
     268        3100 :     tmp1 = div_s( shl( 1, sub( 14, exp ) ), tmp ); /*Q(29-exp)*/
     269        3100 :     L_tmp = Mult_32_16( sum_energy, tmp1 );
     270        3100 :     sum_energy = L_shl( L_tmp, sub( exp, 14 ) );
     271             :     /**diff_sm = 0.2f * diff  + 0.8f * *diff_sm;*/
     272        3100 :     *diff_sm = L_add( Mult_32_16( diff, 6554 ), Mult_32_16( *diff_sm, 26214 ) );
     273        3100 :     move32();
     274             :     /**energy_sm = 0.2f * sum_energy + 0.8f * *energy_sm;*/
     275        3100 :     *energy_sm = L_add( Mult_32_16( sum_energy, 6554 ), Mult_32_16( *energy_sm, 26214 ) );
     276        3100 :     move32();
     277             :     /*diff /= sum_energy;*/
     278             : 
     279        3100 :     IF( sum_energy )
     280             :     {
     281        3100 :         exp = norm_l( sum_energy );
     282        3100 :         tmp = extract_h( L_shl( sum_energy, exp ) );
     283        3100 :         exp = sub( sub( 30, exp ), 7 );
     284        3100 :         IF( tmp < 0 )
     285             :         {
     286         190 :             tmp = abs_s( tmp );
     287         190 :             tmp = div_s( 16384, tmp ); /*Q(15+exp)*/
     288             :             BASOP_SATURATE_WARNING_OFF_EVS
     289         190 :             diff = L_negate( L_shr_o( Mult_32_16( diff, tmp ), sub( exp + 7, 31 ), &Overflow ) );
     290             :             BASOP_SATURATE_WARNING_ON_EVS
     291         190 :             diff16 = round_fx_o( diff, &Overflow );
     292             :         }
     293             :         ELSE
     294             :         {
     295        2910 :             tmp = div_s( 16384, tmp ); /*Q(15+exp)*/
     296             :             BASOP_SATURATE_WARNING_OFF_EVS
     297        2910 :             diff = L_shr_o( Mult_32_16( diff, tmp ), sub( exp + 7, 31 ), &Overflow );
     298             :             BASOP_SATURATE_WARNING_ON_EVS
     299        2910 :             diff16 = round_fx_o( diff, &Overflow );
     300             :         }
     301             :     }
     302             :     ELSE
     303             :     {
     304           0 :         diff16 = round_fx_o( L_shl_o( diff, 25, &Overflow ), &Overflow );
     305             :     }
     306        3100 :     test();
     307        3100 :     test();
     308        3100 :     if ( LT_32( *diff_sm, -1280 /*-10.0f Q7*/ ) && LT_32( *energy_sm, 4928 /*38.5f Q7*/ ) && LT_16( diff16, -26214 /*-.8f Q15*/ ) )
     309             :     {
     310         154 :         *predecision_flag = 1;
     311         154 :         move16();
     312             :     }
     313        3100 :     test();
     314        3100 :     test();
     315        3100 :     if ( GT_32( *diff_sm, 1280 /*10.0f Q7*/ ) && GT_32( *energy_sm, 10624 /*83.0f Q7*/ ) && GT_16( diff16, 16384 /*.5 Q15*/ ) )
     316             :     {
     317         140 :         *predecision_flag = 0;
     318         140 :         move16();
     319             :     }
     320             : 
     321             :     /* short pitch possiblity pre-decision */
     322        3100 :     maximum_fx( EspecdB, 7, &energy0_16 );
     323        3100 :     maximum_fx( EspecdB + 8, 7, &energy1_16 );
     324        3100 :     ratio = s_max( sub( energy1_16, energy0_16 ), 0 ); /*Q7 */
     325             :     /*ratio *= max(voicing,0);*/
     326        3100 :     tmp = s_max( voicing_m, 0 );
     327        3100 :     ratio = mult_r( ratio, tmp ); /*Q7*/
     328             :     /**LF_EnergyRatio_sm = (15*(*LF_EnergyRatio_sm) + ratio)/16;*/
     329        3100 :     L_tmp = L_mult( ratio, 2048 );
     330        3100 :     L_tmp = L_mac( L_tmp, *LF_EnergyRatio_sm, 30720 );
     331        3100 :     *LF_EnergyRatio_sm = round_fx( L_tmp );
     332        3100 :     move16();
     333        3100 :     test();
     334        3100 :     if ( GT_16( *LF_EnergyRatio_sm, 4480 /*35.0f Q7*/ ) || GT_16( ratio, 6400 /*50.0f Q7*/ ) )
     335             :     {
     336           1 :         *predecision_flag = 1;
     337           1 :         move16();
     338             :     }
     339             : 
     340        3100 :     if ( LT_16( *LF_EnergyRatio_sm, 2048 /*16.0f Q7*/ ) )
     341             :     {
     342        2993 :         *predecision_flag = 0;
     343        2993 :         move16();
     344             :     }
     345             : 
     346             :     /* short pitch candidate detection */
     347        3100 :     Tp = pitch[1];
     348        3100 :     move16();
     349        3100 :     cor_max = 0;
     350        3100 :     move16();
     351        3100 :     pt_wsp = wsp + 3 * L_SUBFR;
     352        3100 :     pit_min = PIT_MIN_DOUBLEEXTEND;
     353        3100 :     move16();
     354        3100 :     pit_min_up = PIT_MIN;
     355        3100 :     move16();
     356       58900 :     FOR( T = pit_min; T <= pit_min_up; T++ )
     357             :     {
     358       55800 :         energy1 = Dot_product( pt_wsp, pt_wsp - T, L_SUBFR );
     359       55800 :         test();
     360       55800 :         IF( ( GT_32( energy1, cor_max ) ) || ( EQ_16( T, pit_min ) ) )
     361             :         {
     362       20776 :             cor_max = L_add( energy1, 0 );
     363       20776 :             Tp = T;
     364       20776 :             move16();
     365             :         }
     366             :     }
     367        3100 :     energy0 = Dot_product12( pt_wsp, pt_wsp, L_SUBFR, &exp1 );
     368        3100 :     exp1 = sub( exp1, shl( Q_new, 1 ) );
     369        3100 :     energy1 = Dot_product12( pt_wsp - Tp, pt_wsp - Tp, L_SUBFR, &exp2 );
     370        3100 :     exp2 = sub( exp2, shl( Q_new, 1 ) );
     371             :     /* cor_max *= inv_sqrt( energy0*energy1 );*/
     372        3100 :     L_tmp = Mult_32_32( energy0, energy1 );
     373        3100 :     exp = norm_l( L_tmp );
     374        3100 :     L_tmp1 = L_shl( L_tmp, exp );
     375             : 
     376        3100 :     exp = 31 - exp - ( 31 - exp1 - exp2 );
     377        3100 :     move16();
     378        3100 :     L_tmp1 = Isqrt_lc( L_tmp1, &exp ); /*Q(31-exp)*/
     379        3100 :     cor_max = Mult_32_32( cor_max, L_tmp1 );
     380        3100 :     exp = 31 - ( shl( Q_new, 1 ) + 1 ) - ( 31 - exp ) + 31;
     381        3100 :     cor_max16 = round_fx_o( L_shl_o( cor_max, exp, &Overflow ), &Overflow ); /*Q15*/
     382             :     /**voicing0_sm = add(mult_r(24576 ,(*voicing0_sm)) , mult_r(8192 , cor_max16));*/
     383        3100 :     *voicing0_sm = round_fx( L_mac( L_mult( 24576 /*.75f Q15*/, *voicing0_sm ), 8192 /*.25f Q15*/, cor_max16 ) );
     384        3100 :     move16();
     385             : 
     386             :     /* final short pitch detection */
     387        3100 :     test();
     388        3100 :     test();
     389        3100 :     test();
     390        3100 :     *flag_spitch = 0;
     391        3100 :     move16();
     392        3100 :     IF( ( EQ_16( localVAD, 1 ) ) && ( EQ_16( *predecision_flag, 1 ) ) &&
     393             :         ( GT_16( *voicing0_sm, 16384 ) ) && ( GT_16( *voicing0_sm, mult_r( *voicing_sm, 21299 ) ) ) )
     394             :     {
     395           0 :         *flag_spitch = 1;
     396           0 :         move16();
     397           0 :         pitch[0] = Tp;
     398           0 :         move16();
     399           0 :         pitch[1] = Tp;
     400           0 :         move16();
     401           0 :         pitch[2] = Tp;
     402           0 :         move16();
     403             :     }
     404             : 
     405        3100 :     return;
     406             : }
     407             : 
     408             : 
     409             : /*-------------------------------------------------------------------*
     410             :  * pitch_ol2()
     411             :  *
     412             :  * Open-loop pitch precision improvement with 1/4 resolution
     413             :  * The pitch is searched in the interval <pitch_ol-delta, pitch_ol+delta),
     414             :  * i.e. the value pitch_ol + delta is not a part of the interval
     415             :  *-------------------------------------------------------------------*/
     416             : 
     417             : /*-------------------------------------------------------------------*
     418             :  * StableHighPitchDetect()
     419             :  *
     420             :  * Very short stable pitch detection
     421             :  *-------------------------------------------------------------------*/
     422     1129000 : void StableHighPitchDetect_ivas_fx(
     423             :     Word16 *flag_spitch,       /* o  : flag to indicate very short stable pitch */
     424             :     Word16 pitch[],            /* i/o: OL pitch buffer                         */
     425             :     const Word16 voicing[],    /* i  : OL pitch gains                         Q15 */
     426             :     const Word16 wsp[],        /* i  : weighted speech                        Qx */
     427             :     const Word16 localVAD,     /* i  : local VAD flag                          */
     428             :     Word16 *voicing_sm,        /* i/o: smoothed open-loop pitch gains          */
     429             :     Word16 *voicing0_sm,       /* i/o: smoothed high pitch gains               */
     430             :     Word16 *LF_EnergyRatio_sm, /* i/o: smoothed [0, 300Hz] relative peak energy Q7*/
     431             :     Word16 *predecision_flag,  /* i/o: predecision flag                        */
     432             :     Word32 *diff_sm,           /* i/o: smoothed pitch frequency difference     Q7*/
     433             :     Word32 *energy_sm,         /* i/o: smoothed energy around pitch frequency  Q7*/
     434             :     Word16 Q_new,
     435             :     Word16 EspecdB[] /*Q8*/
     436             : )
     437             : {
     438             :     Word16 i, pitch_freq_point;
     439             :     Word16 T, Tp, pit_min;
     440             :     Word16 energy0_16, energy1_16, ratio, voicing_m;
     441             :     Word32 energy0, energy1, cor_max, diff, sum_energy;
     442             :     const Word16 *pt_wsp;
     443             :     Word16 tmp, tmp1, exp, diff16, cor_max16, exp1, exp2, pit_min_up;
     444             :     Word32 L_tmp, L_tmp1;
     445             :     Word16 Top;
     446             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     447     1129000 :     Flag Overflow = 0;
     448     1129000 :     move32();
     449             : #endif
     450             : 
     451             :     /*voicing = (voicing[0] + voicing[1] + voicing[2] )/3;*/
     452     1129000 :     L_tmp = L_mult( voicing[0], 10923 /*1/3 in Q15*/ );
     453     1129000 :     L_tmp = L_mac( L_tmp, voicing[1], 10923 /*1/3 in Q15*/ );
     454     1129000 :     L_tmp = L_mac( L_tmp, voicing[2], 10923 /*1/3 in Q15*/ );
     455     1129000 :     voicing_m = round_fx_sat( L_tmp );
     456             :     /**voicing_sm = 0.75f*(*voicing_sm) + 0.25f*voicing;*/
     457     1129000 :     *voicing_sm = round_fx( L_mac( L_mult( *voicing_sm, 24576 /*0.75f Q15*/ ), voicing_m, 8192 /*0.25f Q15*/ ) );
     458     1129000 :     move16();
     459             : 
     460             :     /* pitch_freq_point = (short)(L_FFT/(mult_fact*T_op[1])+0.5f);*/
     461     1129000 :     Top = pitch[1];
     462     1129000 :     move16();
     463     1129000 :     pitch_freq_point = idiv1616( L_FFT, Top ); /* Q0*/
     464     1129000 :     sum_energy = L_deposit_l( 0 );
     465    10075462 :     FOR( i = 1; i < 2 * pitch_freq_point; i++ )
     466             :     {
     467     8946462 :         sum_energy = L_mac0( sum_energy, EspecdB[i], 1 ); // sum_energy
     468             :     }
     469     1129000 :     tmp = sub( shl( pitch_freq_point, 1 ), 1 );
     470             : 
     471             :     /*  for ( i = 1; i < 2 * pitch_freq_point; i++ )
     472             :         {
     473             :           diff += ( EspecdB[pitch_freq_point] - EspecdB[i] );
     474             :         }
     475             :         sum energy is the accumulated value of EspecdB over the loop and EspecdB[pitch_freq_point] is constant for the loop
     476             :         diff can be computed as (2 * pitch_freq_point - 1) * EspecdB[pitch_freq_point] - sum_energy     */
     477             : 
     478     1129000 :     diff = L_mac0( L_negate( sum_energy ), EspecdB[pitch_freq_point], tmp );
     479             : 
     480             :     /*sum_energy /= (2*pitch_freq_point-1);*/
     481             : 
     482     1129000 :     exp = norm_s( tmp );
     483     1129000 :     tmp1 = div_s( shl( 1, sub( 14, exp ) ), tmp ); /*Q(29-exp)*/
     484     1129000 :     L_tmp = Mult_32_16( sum_energy, tmp1 );
     485     1129000 :     sum_energy = L_shl( L_tmp, sub( exp, 14 ) );
     486             :     /**diff_sm = 0.2f * diff  + 0.8f * *diff_sm;*/
     487     1129000 :     *diff_sm = L_add( Mult_32_16( diff, 6554 /*.2f Q15*/ ), Mult_32_16( *diff_sm, 26214 /*.8f Q15*/ ) );
     488     1129000 :     move32();
     489             :     /**energy_sm = 0.2f * sum_energy + 0.8f * *energy_sm;*/
     490     1129000 :     *energy_sm = L_add( Mult_32_16( sum_energy, 6554 /*.2f Q15*/ ), Mult_32_16( *energy_sm, 26214 /*.8f Q15*/ ) );
     491     1129000 :     move32();
     492             :     /*diff /= sum_energy;*/
     493             : 
     494     1129000 :     IF( sum_energy )
     495             :     {
     496     1128972 :         exp = norm_l( sum_energy );
     497     1128972 :         tmp = extract_h( L_shl( sum_energy, exp ) );
     498     1128972 :         exp = sub( sub( 30, exp ), 7 );
     499     1128972 :         IF( tmp < 0 )
     500             :         {
     501      180459 :             tmp = abs_s( tmp );
     502      180459 :             tmp = div_s( 16384, tmp ); /*Q(15+exp)*/
     503             :             BASOP_SATURATE_WARNING_OFF_EVS
     504      180459 :             diff = L_negate( L_shr_o( Mult_32_16( diff, tmp ), sub( exp + 7, 31 ), &Overflow ) );
     505             :             BASOP_SATURATE_WARNING_ON_EVS
     506      180459 :             diff16 = round_fx_o( diff, &Overflow );
     507             :         }
     508             :         ELSE
     509             :         {
     510      948513 :             tmp = div_s( 16384, tmp ); /*Q(15+exp)*/
     511             :             BASOP_SATURATE_WARNING_OFF_EVS
     512      948513 :             diff = L_shr_o( Mult_32_16( diff, tmp ), sub( exp + 7, 31 ), &Overflow );
     513             :             BASOP_SATURATE_WARNING_ON_EVS
     514      948513 :             diff16 = round_fx_o( diff, &Overflow );
     515             :         }
     516             :     }
     517             :     ELSE
     518             :     {
     519          28 :         diff16 = round_fx_o( L_shl_o( diff, 25, &Overflow ), &Overflow );
     520             :     }
     521     1129000 :     test();
     522     1129000 :     test();
     523     1129000 :     IF( LT_32( *diff_sm, -1280 /*-10.0f Q7*/ ) && LT_32( *energy_sm, 4928 /*38.5f Q7*/ ) && LT_16( diff16, -26214 /*-.8f Q15*/ ) )
     524             :     {
     525       20829 :         *predecision_flag = 1;
     526       20829 :         move16();
     527             :     }
     528     1129000 :     test();
     529     1129000 :     test();
     530     1129000 :     if ( GT_32( *diff_sm, 1280 /*10.0f Q7*/ ) && GT_32( *energy_sm, 10624 /*83.0f Q7*/ ) && GT_16( diff16, 16384 /*.5 Q15*/ ) )
     531             :     {
     532       86486 :         *predecision_flag = 0;
     533       86486 :         move16();
     534             :     }
     535             : 
     536             :     /* short pitch possiblity pre-decision */
     537     1129000 :     maximum_fx( EspecdB, 7, &energy0_16 );
     538     1129000 :     maximum_fx( EspecdB + 8, 7, &energy1_16 );
     539     1129000 :     test();
     540     1129000 :     IF( energy1_16 < 0 && energy0_16 > 0 )
     541             :     {
     542       30526 :         ratio = 0;
     543       30526 :         move16();
     544             :     }
     545             :     ELSE
     546             :     {
     547     1098474 :         ratio = s_max( sub( energy1_16, energy0_16 ), 0 ); /*Q7 */
     548             :     }
     549             :     /*ratio *= max(voicing,0);*/
     550     1129000 :     tmp = s_max( voicing_m, 0 );
     551     1129000 :     ratio = mult_r( ratio, tmp ); /*Q7*/
     552             :     /**LF_EnergyRatio_sm = (15*(*LF_EnergyRatio_sm) + ratio)/16;*/
     553     1129000 :     L_tmp = L_mult( ratio, 2048 );
     554     1129000 :     L_tmp = L_mac( L_tmp, *LF_EnergyRatio_sm, 30720 );
     555     1129000 :     *LF_EnergyRatio_sm = round_fx( L_tmp );
     556     1129000 :     move16();
     557     1129000 :     test();
     558     1129000 :     if ( GT_16( *LF_EnergyRatio_sm, 4480 /*35.0f Q7*/ ) || GT_16( ratio, 6400 /*50.0f Q7*/ ) )
     559             :     {
     560       26807 :         *predecision_flag = 1;
     561       26807 :         move16();
     562             :     }
     563             : 
     564     1129000 :     if ( LT_16( *LF_EnergyRatio_sm, 2048 /*16.0f Q7*/ ) )
     565             :     {
     566     1081692 :         *predecision_flag = 0;
     567     1081692 :         move16();
     568             :     }
     569             : 
     570             :     /* short pitch candidate detection */
     571     1129000 :     Tp = pitch[1];
     572     1129000 :     move16();
     573     1129000 :     cor_max = 0;
     574     1129000 :     move16();
     575     1129000 :     pt_wsp = wsp + 3 * L_SUBFR;
     576     1129000 :     pit_min = PIT_MIN_DOUBLEEXTEND;
     577     1129000 :     move16();
     578     1129000 :     pit_min_up = PIT_MIN;
     579     1129000 :     move16();
     580    21451000 :     FOR( T = pit_min; T <= pit_min_up; T++ )
     581             :     {
     582    20322000 :         energy1 = Dot_product( pt_wsp, pt_wsp - T, L_SUBFR );
     583    20322000 :         test();
     584    20322000 :         IF( ( GT_32( energy1, cor_max ) ) || ( EQ_16( T, pit_min ) ) )
     585             :         {
     586     5935961 :             cor_max = L_add( energy1, 0 );
     587     5935961 :             Tp = T;
     588     5935961 :             move16();
     589             :         }
     590             :     }
     591     1129000 :     energy0 = Dot_product12( pt_wsp, pt_wsp, L_SUBFR, &exp1 );
     592     1129000 :     exp1 = sub( exp1, shl( Q_new, 1 ) );
     593     1129000 :     energy1 = Dot_product12( pt_wsp - Tp, pt_wsp - Tp, L_SUBFR, &exp2 );
     594     1129000 :     exp2 = sub( exp2, shl( Q_new, 1 ) );
     595             :     /* cor_max *= inv_sqrt( energy0*energy1 );*/
     596     1129000 :     L_tmp = Mult_32_32( energy0, energy1 );
     597     1129000 :     exp = norm_l( L_tmp );
     598     1129000 :     L_tmp1 = L_shl( L_tmp, exp );
     599             : 
     600     1129000 :     exp = sub( sub( 31, exp ), ( sub( sub( 31, exp1 ), exp2 ) ) );
     601     1129000 :     move16();
     602     1129000 :     L_tmp1 = Isqrt_lc( L_tmp1, &exp ); /*Q(31-exp)*/
     603     1129000 :     cor_max = Mult_32_32( cor_max, L_tmp1 );
     604     1129000 :     exp = add( sub( sub( 31, add( shl( Q_new, 1 ), 1 ) ), sub( 31, exp ) ), 31 );
     605     1129000 :     cor_max16 = round_fx_o( L_shl_o( cor_max, exp, &Overflow ), &Overflow ); /*Q15*/
     606             :     /**voicing0_sm = add(mult_r(24576 ,(*voicing0_sm)) , mult_r(8192 , cor_max16));*/
     607     1129000 :     *voicing0_sm = round_fx( L_mac( L_mult( 24576 /*.75f Q15*/, *voicing0_sm ), 8192 /*.25f Q15*/, cor_max16 ) );
     608     1129000 :     move16();
     609             : 
     610             :     /* final short pitch detection */
     611     1129000 :     test();
     612     1129000 :     test();
     613     1129000 :     test();
     614     1129000 :     *flag_spitch = 0;
     615     1129000 :     move16();
     616     1129000 :     IF( ( EQ_16( localVAD, 1 ) ) && ( EQ_16( *predecision_flag, 1 ) ) &&
     617             :         ( GT_16( *voicing0_sm, 21299 /*.65f in Q15*/ ) ) && ( GT_16( *voicing0_sm, mult_r( *voicing_sm, 22938 /*.7f in Q15*/ ) ) ) )
     618             :     {
     619       35447 :         *flag_spitch = 1;
     620       35447 :         move16();
     621       35447 :         pitch[0] = Tp;
     622       35447 :         move16();
     623       35447 :         pitch[1] = Tp;
     624       35447 :         move16();
     625       35447 :         pitch[2] = Tp;
     626       35447 :         move16();
     627             :     }
     628             : 
     629     1129000 :     return;
     630             : }

Generated by: LCOV version 1.14