LCOV - code coverage report
Current view: top level - lib_dec - er_sync_exc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 241 252 95.6 %
Date: 2025-08-23 01:22:27 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             : /*This BASOP port is up to date with trunk rev. 36554*/
       6             : 
       7             : #include <assert.h>
       8             : #include <stdint.h>
       9             : #include "options.h"
      10             : #include "cnst.h"
      11             : #include "prot_fx.h"
      12             : #include "basop32.h"
      13             : #include "basop_util.h"
      14             : /*-------------------------------------------------------------------------
      15             :  *
      16             :  * Perform resynchronisation of the last glottal pulse in voiced lost frame
      17             :  *
      18             :  *------------------------------------------------------------------------*/
      19             : 
      20             : 
      21             : /** Get the location of the minimum energy in the given signal.
      22             :  * @returns Index of the position of the minimum energy, that is the position i where filter(x[i-filterLength/2],...,x[i+(filterLength-filterLength/2)-1]) is at maximum.
      23             :  */
      24        2444 : static Word16 GetMinimumPosition_fx(
      25             :     Word16 const *x,    /* Input signal.                                                            Qx*/
      26             :     Word16 length,      /* The length of the input signal.                                          Q0*/
      27             :     Word16 filterLength /* the length of the filter length used for the energy calculation.         Q0*/
      28             : )
      29             : {
      30             :     Word16 iMinEnergyPos, center, i;
      31             :     Word16 cnt, tmp_e, tmp16;
      32             :     Word32 energy, energy_old, tmptest;
      33             : #ifndef ISSUE_1866_replace_overflow_libdec
      34             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
      35             :     Flag Overflow = 0;
      36             :     move16();
      37             : #endif
      38             : #endif
      39             : 
      40        2444 :     filterLength = s_min( filterLength, length ); /*Q0*/
      41        2444 :     center = shr( filterLength, 1 );              /*Q0*/
      42        2444 :     iMinEnergyPos = center;                       /*Q0*/
      43        2444 :     move16();
      44             : 
      45        2444 :     IF( filterLength > 0 )
      46             :     {
      47        1774 :         center = add( center, 1 );
      48        1774 :         energy = L_deposit_l( 0 );
      49        1774 :         energy_old = L_deposit_l( 0 );
      50             : 
      51        1774 :         cnt = sub( length, filterLength ); /*Q0*/
      52             : 
      53        1774 :         tmp_e = 0;
      54        1774 :         move16();
      55      322381 :         FOR( i = 0; i < cnt; i++ )
      56             :         {
      57      320607 :             tmp16 = shr( x[i], tmp_e );                     /*Qx*/
      58      320607 :             energy = L_msu_sat( energy_old, tmp16, tmp16 ); /*2Qx+1*/
      59      320607 :             tmp16 = shr( x[( i + filterLength )], tmp_e );  /*Qx*/
      60             :             BASOP_SATURATE_WARNING_OFF_EVS                  /*Saturation will be handled*/
      61      320607 :                 energy = L_mac_sat( energy, tmp16, tmp16 ); /*2Qx+1*/
      62             :             BASOP_SATURATE_WARNING_ON_EVS
      63             : 
      64             :             /*if (energy == MAXVAL_WORD32)*/
      65             :             BASOP_SATURATE_WARNING_OFF_EVS /*saturates if energy < 0*/
      66             : #ifdef ISSUE_1866_replace_overflow_libdec
      67      320607 :                 tmptest = L_sub_sat( energy, MAXVAL_WORD32 );
      68             :             /*Q31*/
      69             : #else
      70             :                 tmptest = L_sub_o( energy, MAXVAL_WORD32, &Overflow );                     /*Q31*/
      71             : #endif
      72             :             BASOP_SATURATE_WARNING_ON_EVS
      73      320607 :             IF( tmptest == 0 )
      74             :             {
      75           0 :                 tmp_e = add( tmp_e, 1 );
      76           0 :                 energy = L_shr( energy_old, 2 );
      77           0 :                 tmp16 = shr( x[i], tmp_e );             /*Qx-1*/
      78           0 :                 energy = L_msu( energy, tmp16, tmp16 ); /*2Qx-1*/
      79           0 :                 tmp16 = shr( x[( i - filterLength )], tmp_e );
      80           0 :                 energy = L_mac( energy, tmp16, tmp16 ); /*2Qx-1*/
      81             :             }
      82             : 
      83      320607 :             IF( energy < 0 )
      84             :             {
      85       11552 :                 iMinEnergyPos = add( i, center ); /*Q0*/
      86       11552 :                 tmp_e = 0;
      87       11552 :                 move16();
      88       11552 :                 energy = 0;
      89       11552 :                 move16();
      90             :             }
      91      320607 :             energy_old = L_add( energy, 0 );
      92             :         }
      93             :     }
      94             : 
      95        2444 :     return iMinEnergyPos; /*Q0*/
      96             : }
      97             : 
      98             : /*!
      99             :  * \brief FindMaxPeak - Get the location of the maximum peak in the given signal.
     100             :  *
     101             :  * \returns Index of the position of the maximum peak, that is the position i where abs(x[i]) has it's maximum.
     102             :  */
     103             : 
     104        1233 : static Word16 FindMaxPeak_fx(
     105             :     Word16 /*float*/ const *x, /*<!i   : Input signal. Q15*/
     106             :     Word16 /*int*/ length      /*<!i   : The length of the input signal.*/
     107             : )
     108             : {
     109             :     Word16 iMax, i;
     110             : 
     111        1233 :     iMax = 0;
     112        1233 :     move16();
     113      287151 :     FOR( i = 1; i < length; i++ )
     114             :     {
     115      285918 :         if ( GT_16( abs_s( x[i] ), abs_s( x[iMax] ) ) )
     116             :         {
     117        6796 :             iMax = i; /*Q0*/
     118        6796 :             move16();
     119             :         }
     120             :     }
     121             : 
     122        1233 :     return iMax; /*Q0*/
     123             : }
     124             : 
     125         764 : static void AddSamples_fx(
     126             :     Word16 const *const old_exc,   /*Qx*/
     127             :     Word16 *const new_exc,         /*Qx*/
     128             :     Word16 const L_frame,          /*Q0*/
     129             :     Word16 const n_samples_to_add, /*Q0*/
     130             :     Word16 const min_pos[],        /*Q0*/
     131             :     Word16 const points_by_pos[],  /*Q0*/
     132             :     Word16 const nb_min            /*Q0*/
     133             : )
     134             : {
     135             :     Word16 *pt_dest;
     136             :     Word16 const *pt_src;
     137             :     Word16 last_min_pos, i, j;
     138             :     Word16 ftmp;
     139             : 
     140         764 :     pt_dest = new_exc; /*Qx*/
     141         764 :     pt_src = old_exc;  /*Qx*/
     142         764 :     last_min_pos = 0;
     143         764 :     move16();
     144             : 
     145        4165 :     FOR( i = 0; i < nb_min; i++ )
     146             :     {
     147             :         /* Copy section */
     148      507705 :         FOR( j = min_pos[i] - last_min_pos; j > 0; j-- )
     149             :         {
     150      504304 :             *pt_dest++ = *pt_src++; /*Qx*/
     151      504304 :             move16();
     152             :         }
     153             :         /* Add some samples */
     154        3401 :         ftmp = negate( mult( *pt_src, 1638 /*.05f Q15*/ ) ); /*Qx*/
     155             : 
     156        8082 :         FOR( j = 0; j < points_by_pos[i]; j++ )
     157             :         {
     158        4681 :             *pt_dest++ = ftmp; /*Qx*/
     159        4681 :             move16();
     160        4681 :             ftmp = negate( ftmp ); /*Qx*/
     161             :         }
     162             :         /* Prepare for the next loop iteration */
     163        3401 :         last_min_pos = min_pos[i]; /*Q0*/
     164        3401 :         move16();
     165             :     }
     166             :     /* Copy remaining length */
     167       46595 :     FOR( j = sub( L_frame, add( n_samples_to_add, last_min_pos ) ); j > 0; j-- )
     168             :     {
     169       45831 :         *pt_dest++ = *pt_src++; /*Qx*/
     170       45831 :         move16();
     171             :     }
     172         764 : }
     173             : 
     174         469 : static void RemoveSamples_fx(
     175             :     Word16 /*float*/ const *const old_exc, /*i   : Qx */
     176             :     Word16 /*float*/ *const new_exc,       /*o   : Qx */
     177             :     Word16 /*int*/ const L_frame,          /*i   : Q0 */
     178             :     Word16 /*int*/ const n_samples_to_add, /*i   : Q0 */
     179             :     Word16 /*int*/ const min_pos[],        /*i   : Q0 */
     180             :     Word16 /*int*/ const points_by_pos[],  /*i   : Q0 */
     181             :     Word16 /*int*/ const nb_min            /*i   : Q0*/
     182             : )
     183             : {
     184             :     Word16 /*float*/ *pt_dest;
     185             :     Word16 /*float*/ const *pt_src;
     186             :     Word16 /*int*/ last_min_pos, i, j;
     187             : 
     188             : 
     189         469 :     pt_dest = new_exc + L_frame;                     /*Qx*/
     190         469 :     last_min_pos = sub( L_frame, n_samples_to_add ); /*Q0*/
     191             : 
     192        2835 :     FOR( i = sub( nb_min, 1 ); i >= 0; i-- )
     193             :     {
     194             :         /* Compute len to copy */
     195             :         /* Copy section, removing some samples */
     196        2366 :         pt_src = old_exc + last_min_pos; /*Qx*/
     197             : 
     198      323794 :         FOR( j = sub( last_min_pos, add( min_pos[i], points_by_pos[i] ) ); j > 0; j-- )
     199             :         {
     200      321428 :             *--pt_dest = *--pt_src; /*Qx*/
     201      321428 :             move16();
     202             :         }
     203             :         /* Prepare for the next loop iteration */
     204        2366 :         last_min_pos = min_pos[i]; /*Q0*/
     205        2366 :         move16();
     206             :     }
     207             :     /* Copy remaining length */
     208         469 :     pt_src = old_exc + last_min_pos; /*Qx*/
     209             : 
     210       18625 :     FOR( j = last_min_pos; j > 0; j-- )
     211             :     {
     212       18156 :         *--pt_dest = *--pt_src; /*Qx*/
     213       18156 :         move16();
     214             :     }
     215         469 : }
     216             : 
     217             : /** Resynchronize glotal pulse positions of the signal in src_exc and store it in dst_exc.
     218             :  * src_exc holds on call the harmonic part of the signal with the constant pitch, constructed by repeating the last pitch cycle of length pitchStart.
     219             :  * dst_exc holds on return the harmonic part of the signal with the pitch changing from pitchStart to pitchEnd.
     220             :  * src_exc and dst_exc can overlap, but src_exc < dst_exc must be fullfiled.
     221             :  */
     222             : /*This BASOP port is up to date with trunk rev 8779(svnext2)*/
     223        1233 : void PulseResynchronization_fx(
     224             :     Word16 /*float*/ const *const src_exc, /*<!i  : Input excitation buffer                                                                        Q15*/
     225             :     Word16 /*float*/ *const dst_exc,       /*<!o  : Output excitation buffer                                                                       Q15*/
     226             :     Word16 /*int*/ const nFrameLength,     /*<!i  : Length of the frame, that is the length of the valid data in the excitation buffer on return.  Q0 */
     227             :     Word16 /*int*/ const nSubframes,       /*<!i  : Number of subframes in the excitation buffer. nFrameLength must be divisible by nSubframes     Q0 */
     228             :     Word32 /*float*/ const pitchStart,     /*<!i  : Pitch at the end of the last frame                                                             Q16*/
     229             :     Word32 /*float*/ const pitchEnd        /*<!i  : Pitch at the end of the current frame                                                          Q16*/
     230             : )
     231             : {
     232             :     Word16 /*int*/ T0, i, k;
     233             :     Word16 /*float*/ perCycleDeltaDelta, cycleDelta, freqStart, fractionalLeft;
     234             :     Word16 /*int*/ roundedPitchStart, nSamplesDelta, nSamplesDeltaRemain, iMinPos1, iMinPos[NB_PULSES_MAX + 1], iDeltaSamples[NB_PULSES_MAX + 1], maxDeltaSamples, roundedCycleDelta;
     235             :     Word16 tmp16, tmp16_a, freqStart_e /*exponent of freqStart*/, tmp_e, samplesDelta_e, perCycleDeltaDelta_e, cycleDelta_e, tmp2_e, tmp3_e;
     236             :     Word32 /* pitchDelta, */ tmp32, tmp32_a, tmp32_b, samplesDelta, absPitchDiff, cycleDelta32;
     237             : #ifndef ISSUE_1866_replace_overflow_libdec
     238             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     239             :     Flag Overflow = 0;
     240             :     move32();
     241             : #endif
     242             : #endif
     243             : 
     244             : 
     245        1233 :     test();
     246        1233 :     test();
     247        1233 :     test();
     248        1233 :     test();
     249        1233 :     test();
     250        1233 :     test();
     251        1233 :     IF( ( LT_32( L_deposit_h( nFrameLength ), pitchStart ) ) || ( pitchStart <= 0 ) || ( pitchEnd <= 0 ) || ( LT_16( nSubframes, 1 ) ) || ( GT_16( nSubframes, 5 ) ) || ( LE_32( Mpy_32_16_1( pitchEnd, add( nSubframes, 1 ) ), Mpy_32_16_1( pitchStart, sub( nSubframes, 1 ) ) ) ) || ( src_exc - dst_exc >= 0 ) )
     252             :     {
     253             :         /* This is error handling and recovery that should never occur. */
     254           0 :         test();
     255           0 :         IF( src_exc != dst_exc && LE_16( nFrameLength, 1200 ) )
     256             :         {
     257           0 :             Copy( src_exc, dst_exc, nFrameLength ); /*Q15*/
     258             :         }
     259           0 :         return;
     260             :     }
     261             : 
     262        1233 :     roundedPitchStart = round_fx( pitchStart ); /*Q0*/
     263             : 
     264             :     /* freqStart = 1.0f/roundedPitchStart; */
     265        1233 :     freqStart_e = 15;
     266        1233 :     move16();
     267        1233 :     freqStart = Inv16( roundedPitchStart, &freqStart_e ); /*Q15,freqStart_e*/
     268             : 
     269             :     /* Calculate number of samples to be removed (if negative) or added (if positive) */
     270             :     /*samplesDelta = 0.5f*pitchDelta*nFrameLength*(nSubframes+1)*freqStart;*/
     271             :     /* pitchDelta*freqStart = ((pitchEnd - pitchStart)/roundedPitchStart)/nSubframes  */
     272        1233 :     tmp16 = shl( roundedPitchStart, 2 ); /*Q0*/
     273        1233 :     if ( EQ_16( nSubframes, 5 ) )
     274             :     {
     275         630 :         tmp16 = add( tmp16, roundedPitchStart ); /*Q0*/ /*tmp16=roundedPitchStart*nSubframes*/
     276             :     }
     277        1233 :     tmp_e = norm_s( tmp16 );
     278        1233 :     tmp16 = shl( tmp16, tmp_e ); /*Q0,-tmp_e*/ /*tmp16=roundedPitchStart*nSubframes*/
     279        1233 :     tmp_e = sub( 15, tmp_e );
     280        1233 :     tmp16 = Inv16( tmp16, &tmp_e ); /*Q15,tmp_e*/ /*tmp16=1.0/(roundedPitchStart*nSubframes)*/
     281        1233 :     tmp32 = L_sub( pitchEnd, pitchStart );        /*Q16*/
     282        1233 :     tmp2_e = norm_l( tmp32 );
     283        1233 :     tmp32 = L_shl( tmp32, tmp2_e );                           /*Q16,-tmp2_e*/
     284        1233 :     tmp32 = Mpy_32_16_1( tmp32, tmp16 ); /*Q16,tmp_e-tmp2_e*/ /*tmp32=pitchDelta*freqStart*/
     285        1233 :     tmp_e = sub( tmp_e, tmp2_e );                             /* sum up all the scalings for tmp32 */
     286             : 
     287        1233 :     tmp16 = imult1616( nFrameLength, add( nSubframes, 1 ) ); /*Q0*/ /*tmp16=nFrameLength*(nSubframes+1)*/
     288        1233 :     tmp2_e = norm_s( tmp16 );
     289        1233 :     tmp16 = shl( tmp16, tmp2_e ); /*Q0+tmp2_e*/
     290             : 
     291        1233 :     tmp32 = Mpy_32_16_1( tmp32, tmp16 ); /*Q1 scaling (tmp_e-tmp2_e-1), -1 because of 0.5f*/ /*tmp32=0.5f*pitchDelta*nFrameLength*(nSubframes+1)*freqStart*/
     292        1233 :     tmp_e = sub( sub( tmp_e, tmp2_e ), 1 );                                                  /* sum up all the scalings for tmp32 */
     293        1233 :     tmp_e = add( tmp_e, 31 - 1 );                                                            /* tmp32 is now regarded as Q31 with scaling tmp_e */
     294             : 
     295             :     /*samplesDelta -= nFrameLength*(1.0f-pitchStart*freqStart);*/
     296        1233 :     tmp2_e = norm_l( pitchStart );
     297        1233 :     tmp32_a = L_shl( pitchStart, tmp2_e );                                                                                 /*Q16+tmp2_e*/
     298        1233 :     tmp32_a = Mpy_32_16_1( tmp32_a /*Q16,-tmp2_e*/, freqStart /*Q15,freqStart_e*/ ); /*Q16, scaling (freqStart_e-tmp2_e)*/ /*tmp32_a=pitchStart*freqStart*/
     299        1233 :     tmp16 = norm_l( tmp32_a );
     300        1233 :     tmp32_a = L_shl( tmp32_a, tmp16 );
     301        1233 :     tmp2_e = sub( sub( freqStart_e, tmp16 ), tmp2_e ); /* sum up all scalings for tmp32_a */
     302        1233 :     tmp2_e = add( tmp2_e, 31 - 16 );                   /* tmp32_a is now regarded as Q31 with scaling tmp2_e */
     303             : 
     304        1233 :     tmp3_e = tmp2_e;
     305        1233 :     move16();
     306        1233 :     tmp32_a = L_negate( tmp32_a );
     307             : #ifdef ISSUE_1866_replace_overflow_libdec
     308        1233 :     tmp32_a = L_add( L_shl_sat( 1, sub( 31, tmp3_e ) ), tmp32_a ); /*Q31,tmp3_e*/ /*tmp32_a= 1.0f-pitchStart*freqStart*/
     309             : #else
     310             :     tmp32_a = L_add( L_shl_o( 1, sub( 31, tmp3_e ), &Overflow ), tmp32_a ); /*Q31,tmp3_e*/ /*tmp32_a= 1.0f-pitchStart*freqStart*/
     311             : #endif
     312        1233 :     tmp2_e = norm_s( nFrameLength );
     313        1233 :     tmp16_a = shl( nFrameLength, tmp2_e );                                                         /*Q0+tmp2_e*/
     314        1233 :     tmp32_a = Mpy_32_16_1( tmp32_a /*Q31,tmp3_e*/, tmp16_a /*Q0,-tmp2_e*/ ); /*Q16,tmp3_e-tmp2_e*/ /*tmp32_a= nFrameLength*(1.0f-pitchStart*freqStart)*/
     315        1233 :     tmp2_e = add( sub( tmp3_e, tmp2_e ), 15 );
     316        1233 :     samplesDelta = BASOP_Util_Add_Mant32Exp( tmp32, tmp_e, L_negate( tmp32_a ), tmp2_e, &samplesDelta_e ); /*Q31,samplesDelta_e*/
     317             : 
     318             :     /* To have enough samples in the buffer of length nFrameLength*(nSubframes+1)/nSubframes, pitchEnd/pitchEnd must be bigger than (nSubframes-1)/(nSubframes+1)=1-2/(nSubframes+1) */
     319             :     /* Thus nSubframes must be bigger than 1 */
     320        1233 :     nSamplesDelta = round_fx( L_shl( samplesDelta, sub( samplesDelta_e, 31 - 16 ) ) ); /*Q0*/
     321        1233 :     nSamplesDeltaRemain = abs_s( nSamplesDelta );
     322             :     /* Find the location of the glottal pulse */
     323        1233 :     T0 = FindMaxPeak_fx( src_exc, roundedPitchStart ); /*Q0*/
     324             :     /* Get the index of the last pulse in the resynchronized frame */
     325             :     /*k = (int)ceil((nFrameLength-nSamplesDelta-T0)*freqStart - 1);*/
     326        1233 :     tmp32 = BASOP_Util_Add_Mant32Exp( L_mult( sub( nFrameLength, add( nSamplesDelta, T0 ) ), freqStart ) /*Q16*/, add( freqStart_e, 31 - 16 ), (Word32) 0x80000000 /*-1.f Q31*/, 0, &tmp_e );
     327        1233 :     tmp32 = L_shl( tmp32, sub( tmp_e, 31 - 16 ) ) /*Q16*/;
     328        1233 :     tmp32 = L_add( tmp32, 65536l /*1.f Q16*/ );
     329        1233 :     k = extract_h( tmp32 );
     330        1233 :     test();
     331        1233 :     IF( ( k >= 0 ) && LE_16( add( k, 1 ), NB_PULSES_MAX ) )
     332             :     {
     333        1233 :         absPitchDiff = L_abs( L_sub( L_deposit_h( roundedPitchStart ), pitchEnd ) ); /*Q16*/
     334             : 
     335             :         /* Calculate the delta of the samples to be added/removed between consecutive cycles */
     336             :         /*perCycleDeltaDelta = (absPitchDiff*(nFrameLength-samplesDelta) - (float)fabs(samplesDelta)*roundedPitchStart)
     337             :                              / ((k+1)*(T0+0.5f*k*roundedPitchStart));*/
     338        1233 :         tmp32 = L_sub( L_deposit_h( nFrameLength ), L_shl( samplesDelta, sub( samplesDelta_e, 31 - 16 ) ) ); /*Q16*/
     339        1233 :         tmp_e = 15;                                                                                          /*tmp32 = Q31,tmp_e*/
     340        1233 :         move16();
     341        1233 :         tmp2_e = norm_l( tmp32 );
     342        1233 :         tmp32 = L_shl( tmp32, tmp2_e );
     343        1233 :         tmp_e = sub( tmp_e, tmp2_e ); /*tmp32 = Q31,tmp_e*/
     344        1233 :         tmp2_e = norm_l( absPitchDiff );
     345        1233 :         tmp32_b = L_shl( absPitchDiff, tmp2_e ); /*Q16+tmp2_e*/
     346        1233 :         tmp_e = sub( tmp_e, tmp2_e );
     347        1233 :         tmp32 = Mpy_32_16_1( tmp32_b, round_fx( tmp32 ) ); /*Q16,tmp_e*/                                                                             /*tmp32 = absPitchDiff*(nFrameLength-samplesDelta)*/
     348        1233 :         tmp32_a = Mpy_32_16_1( L_abs( samplesDelta ) /*Q31,samplesDelta_e*/, roundedPitchStart /*Q0*/ ); /*Q16,samplesDelta_e*/                      /*tmp32_a=fabs(samplesDelta)*roundedPitchStart*/
     349        1233 :         tmp32 = BASOP_Util_Add_Mant32Exp( tmp32, add( tmp_e, 31 - 16 ), L_negate( tmp32_a ), add( samplesDelta_e, 31 - 16 ), &tmp_e ); /*Q31,tmp_e*/ /*tmp32=absPitchDiff*(nFrameLength-samplesDelta)-fabs(samplesDelta)*roundedPitchStart*/
     350        1233 :         tmp16 = imult1616( add( k, 1 ), add( shl( T0, 1 ), imult1616( k, roundedPitchStart ) ) ); /*Q0,-1*/                                          /*tmp16=(k+1)*(T0+0.5f*k*roundedPitchStart)*/
     351        1233 :         perCycleDeltaDelta = BASOP_Util_Divide3216_Scale( tmp32 /*Q31,tmp_e*/, tmp16 /*Q0,-1*/, &perCycleDeltaDelta_e );                             /*Q15,perCycleDeltaDelta_e*/
     352        1233 :         perCycleDeltaDelta_e = add( perCycleDeltaDelta_e, sub( tmp_e, -1 + 15 ) );
     353        1233 :         tmp_e = norm_s( perCycleDeltaDelta );
     354        1233 :         perCycleDeltaDelta_e = sub( perCycleDeltaDelta_e, tmp_e );
     355        1233 :         perCycleDeltaDelta = shl( perCycleDeltaDelta, tmp_e ); /*Q15,perCycleDeltaDelta_e*/
     356             : 
     357             : 
     358             :         /* Calculate the integer number of samples to be added/removed in each pitch cycle */
     359             :         /*cycleDelta = max(0, (absPitchDiff-(k+1)*perCycleDeltaDelta)*T0*freqStart); */
     360        1233 :         tmp_e = norm_s( add( k, 1 ) );
     361        1233 :         tmp32 = L_mult( perCycleDeltaDelta /*Q15,perCycleDeltaDelta_e*/, shl( add( k, 1 ), tmp_e ) /*Q0, tmp_e*/ ) /*Q0+16, perCycleDeltaDelta_e-tmp_e*/;
     362        1233 :         tmp32 = BASOP_Util_Add_Mant32Exp( absPitchDiff /*Q16*/, 31 - 16, L_negate( tmp32 ), add( sub( perCycleDeltaDelta_e, tmp_e ), 31 - 16 ), &tmp_e ); /*Q31,tmp_e*/
     363        1233 :         tmp32 = Mpy_32_16_1( tmp32, T0 /*Q0*/ );                                                                                                          /*Q16,tmp_e*/
     364        1233 :         tmp32 = Mpy_32_16_1( tmp32 /*Q16,tmp_e*/, freqStart /*Q15,freqStart_e*/ ) /*Q16, tmp_e+(freqStart_e)*/;
     365        1233 :         tmp32 = L_max( 0, tmp32 );
     366        1233 :         cycleDelta_e = add( tmp_e, freqStart_e );
     367        1233 :         tmp32_a = L_shl( tmp32, cycleDelta_e );
     368        1233 :         roundedCycleDelta = extract_h( L_abs( tmp32_a ) );
     369        1233 :         if ( tmp32 < 0 )
     370             :         {
     371           0 :             roundedCycleDelta = negate( roundedCycleDelta );
     372             :         }
     373        1233 :         fractionalLeft = lshr( extract_l( tmp32_a ), 1 ); /*Q15*/
     374        1233 :         tmp_e = sub( 15, norm_l( tmp32 ) );
     375        1233 :         cycleDelta_e = add( cycleDelta_e, tmp_e );
     376        1233 :         tmp32 = L_shr( tmp32, sub( tmp_e, 15 ) ); /*Q31 frac, cycleDelta_e*/
     377             : #ifdef ISSUE_1866_replace_overflow_libdec
     378        1233 :         cycleDelta = round_fx_sat( tmp32 ); /*Q15, cycleDelta_e*/
     379             : #else
     380             :         cycleDelta = round_fx_o( tmp32, &Overflow );                                       /*Q15, cycleDelta_e*/
     381             : #endif
     382        1233 :         if ( cycleDelta == 0 )
     383             :         {
     384          93 :             cycleDelta_e = 0;
     385          93 :             move16();
     386             :         }
     387             : 
     388             :         /*roundedCycleDelta = (int)(cycleDelta); */ /*done above*/
     389        1233 :         iDeltaSamples[0] = roundedCycleDelta;       /*Q0*/
     390        1233 :         move16();
     391             :         /*fractionalLeft = cycleDelta-roundedCycleDelta;*/                   /*done above*/
     392        1233 :         nSamplesDeltaRemain = sub( nSamplesDeltaRemain, roundedCycleDelta ); /*Q0*/
     393             : 
     394        1233 :         tmp_e = s_max( 2, k );
     395        1233 :         tmp_e = norm_s( tmp_e ); /*maximum norming factor for following loop*/
     396             : 
     397             : 
     398        4534 :         FOR( i = 1; i <= k; i++ )
     399             :         {
     400             :             /*cycleDelta = (absPitchDiff-(k+1-i)*perCycleDeltaDelta) + fractionalLeft; */
     401        3301 :             tmp32 = L_mult( perCycleDeltaDelta /*Q15,perCycleDeltaDelta_e*/, shl( sub( add( k, 1 ), i ), tmp_e ) /*Q0, tmp_e*/ ) /*Q0+16, perCycleDeltaDelta_e-tmp_e*/; /*calcultion of base for first iteration*/
     402        3301 :             tmp32 = L_shl( tmp32, sub( perCycleDeltaDelta_e, tmp_e ) );                                                                                                 /*Q16*/
     403        3301 :             tmp32_a = L_sub( absPitchDiff, tmp32 );
     404        3301 :             tmp32_b = L_lshl( L_deposit_l( fractionalLeft /*Q15*/ ), 1 ) /*Q16*/;
     405        3301 :             cycleDelta32 = L_add( tmp32_a, tmp32_b ); /*Q16*/
     406        3301 :             cycleDelta32 = L_max( 0, cycleDelta32 );
     407             : 
     408             :             /* Make sure that the number of samples increases */
     409        3301 :             IF( GT_32( L_deposit_h( roundedCycleDelta ), cycleDelta32 ) )
     410             :             {
     411         211 :                 iDeltaSamples[i] = roundedCycleDelta; /*Q0*/
     412         211 :                 move16();
     413         211 :                 roundedCycleDelta = extract_h( cycleDelta32 ); /* cycleDelta32 should never be < 0 here Q0*/
     414         211 :                 iDeltaSamples[i - 1] = roundedCycleDelta;      /*Q0*/
     415         211 :                 move16();
     416             :             }
     417             :             ELSE
     418             :             {
     419        3090 :                 roundedCycleDelta = extract_h( cycleDelta32 ); /* cycleDelta32 should never be < 0 here Q0*/
     420        3090 :                 iDeltaSamples[i] = roundedCycleDelta;          /*Q0*/
     421        3090 :                 move16();
     422             :             }
     423             :             /*fractionalLeft = cycleDelta-roundedCycleDelta = cycleDelta-(int)cycleDelta;*/
     424        3301 :             fractionalLeft = lshr( extract_l( cycleDelta32 ), 1 ); /*Q15*/ /* cycleDelta32 should never be < 0 here */
     425        3301 :             nSamplesDeltaRemain = sub( nSamplesDeltaRemain, roundedCycleDelta );
     426             :         }
     427        1233 :         iDeltaSamples[( k + 1 )] = s_max( 0, nSamplesDeltaRemain );
     428        1233 :         move16();
     429        1233 :         maxDeltaSamples = s_max( iDeltaSamples[k], iDeltaSamples[( k + 1 )] ); /*Q0*/
     430             : 
     431             :         /* Find the location of the minimum energy between the first two pulses */
     432             : 
     433             :         /*iMinPos1 = T0+GetMinimumPosition_fx(src_exc+T0, min(roundedPitchStart, (nSubframes+1)*nFrameLength/nSubframes-T0), maxDeltaSamples);*/
     434        1233 :         BASOP_Util_Divide_MantExp( add( nSubframes, 1 ), 15, nSubframes, 15, &tmp16, &tmp_e );
     435        1233 :         tmp32 = L_mult( nFrameLength /*Q0*/, tmp16 /*Q15,tmp_e*/ ); /*Q16,tmp_e*/
     436        1233 :         tmp16 = round_fx( L_shl( tmp32, tmp_e ) );                  /*Q0*/
     437        1233 :         tmp16 = sub( tmp16, T0 );                                   /*Q0*/
     438        1233 :         tmp16 = s_min( roundedPitchStart, tmp16 );
     439             : 
     440        1233 :         iMinPos1 = GetMinimumPosition_fx(
     441        1233 :             src_exc + T0,   /*Qx*/
     442             :             tmp16,          /*Q0*/
     443             :             maxDeltaSamples /*Q0*/
     444             :         );
     445        1233 :         iMinPos1 = add( iMinPos1, T0 );
     446             : 
     447             : 
     448        1233 :         IF( nSamplesDelta < 0 )
     449             :         {
     450             :             /* Find the location of the minimum energy before the first pulse */
     451             : 
     452         469 :             IF( GT_16( iMinPos1, add( roundedPitchStart, shr( iDeltaSamples[0], 1 ) ) ) )
     453             :             {
     454         247 :                 iMinPos[0] = sub( iMinPos1, sub( roundedPitchStart, shr( iDeltaSamples[0], 1 ) ) ); /*Q0*/
     455         247 :                 move16();
     456             :             }
     457             :             ELSE
     458             :             {
     459         222 :                 iMinPos[0] = sub( GetMinimumPosition_fx( src_exc, T0, iDeltaSamples[0] ), shr( iDeltaSamples[0], 1 ) ); /*Q0*/
     460         222 :                 move16();
     461             :             }
     462             : 
     463             :             /* Find the location of the minimum energy between the pulses */
     464        1897 :             FOR( i = 1; i <= k; i++ )
     465             :             {
     466        1428 :                 iMinPos[i] = add( iMinPos1, sub( imult1616( sub( i, 1 ), roundedPitchStart ), shr( iDeltaSamples[i], 1 ) ) ); /*Q0*/
     467        1428 :                 move16();
     468             :             }
     469             :             /* Find the location of the minimum energy after the last pulse */
     470             : 
     471         469 :             IF( LT_16( add( iMinPos1, add( imult1616( k, roundedPitchStart ), sub( iDeltaSamples[( k + 1 )], shr( iDeltaSamples[( k + 1 )], 1 ) ) ) ), sub( nFrameLength, nSamplesDelta ) ) )
     472             :             {
     473         215 :                 iMinPos[( k + 1 )] = add( iMinPos1, sub( imult1616( k, roundedPitchStart ), shr( iDeltaSamples[( k + 1 )], 1 ) ) ); /*Q0*/
     474         215 :                 move16();
     475             :             }
     476             :             ELSE
     477             :             {
     478             :                 /*iMinPos[k+1] = T0+k*roundedPitchStart
     479             :                                + GetMinimumPosition_fx(src_exc+T0+k*roundedPitchStart, nFrameLength-nSamplesDelta-(T0+k*roundedPitchStart), iDeltaSamples[k+1])
     480             :                                - iDeltaSamples[k+1]/2;                                                 */
     481         254 :                 tmp16 = GetMinimumPosition_fx( src_exc + add( T0, imult1616( k, roundedPitchStart ) ), sub( nFrameLength, add( nSamplesDelta, add( T0, imult1616( k, roundedPitchStart ) ) ) ), iDeltaSamples[( k + 1 )] ); /*Q0*/
     482         254 :                 tmp16 = add( add( T0, imult1616( k, roundedPitchStart ) ), tmp16 );
     483         254 :                 tmp16 = sub( tmp16, shr( iDeltaSamples[( k + 1 )], 1 ) );
     484         254 :                 iMinPos[( k + 1 )] = tmp16;
     485         254 :                 move16();
     486             :             }
     487             : 
     488         469 :             IF( GT_16( add( iMinPos[( k + 1 )], iDeltaSamples[( k + 1 )] ), sub( nFrameLength, nSamplesDelta ) ) )
     489             :             {
     490           1 :                 iDeltaSamples[k] = add( iDeltaSamples[k], add( iMinPos[( k + 1 )], sub( iDeltaSamples[( k + 1 )], sub( nFrameLength, nSamplesDelta ) ) ) ); /*Q0*/
     491           1 :                 move16();
     492           1 :                 iDeltaSamples[( k + 1 )] = sub( nFrameLength, add( nSamplesDelta, iMinPos[( k + 1 )] ) ); /*Q0*/
     493           1 :                 move16();
     494             :             }
     495             : 
     496             :             /* Remove samples at the given positions */
     497         469 :             RemoveSamples_fx( src_exc, dst_exc, nFrameLength, nSamplesDelta, iMinPos, iDeltaSamples, add( k, 2 ) );
     498             :         }
     499             :         ELSE
     500             :         {
     501             :             /* Find the location of the minimum energy before the first pulse */
     502         764 :             IF( GT_16( iMinPos1, roundedPitchStart ) )
     503             :             {
     504         400 :                 iMinPos[0] = sub( iMinPos1, roundedPitchStart ); /*Q0*/
     505         400 :                 move16();
     506             :             }
     507             :             ELSE
     508             :             {
     509         364 :                 iMinPos[0] = GetMinimumPosition_fx( src_exc, T0, iDeltaSamples[0] ); /*Q0*/
     510         364 :                 move16();
     511             :             }
     512             :             /* Find the location of the minimum energy between the pulses */
     513             : 
     514        2637 :             FOR( i = 1; i <= k; i++ )
     515             :             {
     516        1873 :                 iMinPos[i] = iMinPos1; /*Q0*/
     517        1873 :                 move16();
     518        1873 :                 iMinPos1 = add( iMinPos1, roundedPitchStart ); /*Q0*/
     519             :             }
     520             : 
     521             :             /* Find the location of the minimum energy after the last pulse */
     522         764 :             IF( LT_16( iMinPos1, sub( nFrameLength, nSamplesDelta ) ) )
     523             :             {
     524         393 :                 iMinPos[( k + 1 )] = iMinPos1;
     525         393 :                 move16();
     526             :             }
     527             :             ELSE
     528             :             {
     529             : 
     530         371 :                 tmp16 = GetMinimumPosition_fx( src_exc + add( T0, imult1616( k, roundedPitchStart ) ), sub( nFrameLength, add( nSamplesDelta, add( T0, imult1616( k, roundedPitchStart ) ) ) ), iDeltaSamples[( k + 1 )] ); /*Q0*/
     531         371 :                 tmp16 = add( add( tmp16, T0 ), imult1616( k, roundedPitchStart ) );
     532         371 :                 iMinPos[( k + 1 )] = tmp16; /*Q0*/
     533         371 :                 move16();
     534             :             }
     535             : 
     536         764 :             IF( GT_16( add( iMinPos[( k + 1 )], iDeltaSamples[( k + 1 )] ), sub( nFrameLength, nSamplesDelta ) ) )
     537             :             {
     538           8 :                 iDeltaSamples[k] = add( iDeltaSamples[k], add( iMinPos[( k + 1 )], sub( iDeltaSamples[( k + 1 )], sub( nFrameLength, nSamplesDelta ) ) ) ); /*Q0*/
     539           8 :                 move16();
     540           8 :                 iDeltaSamples[( k + 1 )] = sub( sub( nFrameLength, nSamplesDelta ), iMinPos[( k + 1 )] ); /*Q0*/
     541           8 :                 move16();
     542             :             }
     543             :             /* Add samples at the given positions */
     544         764 :             AddSamples_fx( src_exc, dst_exc, nFrameLength, nSamplesDelta, iMinPos, iDeltaSamples, add( k, 2 ) );
     545             :         }
     546             :     }
     547             : }

Generated by: LCOV version 1.14