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

Generated by: LCOV version 1.14