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

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

Generated by: LCOV version 1.14