leaf/Src/leaf-effects.c
/*
 Function pitchdown() is called to read samples from the delay buffer when pitch
 factor is between 0.25 and 1. The read pointer lags behind because of the slowed
 down speed, and it must jump forward towards the write pointer soon as there is
 sufficient space to jump. That is, if there is at least one period of the input
 signal between read pointer and write pointer.  When short periods follow up on
 long periods, the read pointer may have space to jump over more than one period
 lenghts. Jump length must be [periodlength ^ 2] in any case.
 
 A linear crossfade function joins the jump-from point with the jump-to point.
 The crossfade must be completed before another read pointer jump is allowed.
 Length of the crossfade function is stored as a number of samples in terms of
 the input sample rate. This length is dynamically translated
 to a crossfade length expressed in output reading rate, according to pitch
 factor which can change before the crossfade is completed. Crossfade length does
 not cover an invariable length in periods for all pitch transposition factors.
 For pitch factors from 0.5 till 1, crossfade length is stretched in the
 output just as much as the signal itself, as crossfade speed is set to equal
 pitch factor. For pitch factors below 0.5, the read pointer wants to jump
 forward before one period is read, therefore the crossfade length as expressed
 in output periods must be shorter. Crossfade speed is set to [1 - pitchfactor]
 for those cases. Pitch factor 0.5 is the natural switch point between crossfade
 speeds [pitchfactor] and [1 - pitchfactor] because 0.5 == 1 - 0.5. The crossfade
 speed modification for pitch factors below 0.5 also means that much of the
 original signal content will be skipped.
 */
Function pitchdown() is called to read samples from the delay buffer when pitch
factor is between 0.25 and 1. The read pointer lags behind because of the slowed
down speed, and it must jump forward towards the write pointer soon as there is
sufficient space to jump. That is, if there is at least one period of the input
signal between read pointer and write pointer.  When short periods follow up on
long periods, the read pointer may have space to jump over more than one period
lenghts. Jump length must be [periodlength ^ 2] in any case.

A linear crossfade function joins the jump-from point with the jump-to point.
The crossfade must be completed before another read pointer jump is allowed.
Length of the crossfade function is stored as a number of samples in terms of
the input sample rate. This length is dynamically translated
to a crossfade length expressed in output reading rate, according to pitch
factor which can change before the crossfade is completed. Crossfade length does
not cover an invariable length in periods for all pitch transposition factors.
For pitch factors from 0.5 till 1, crossfade length is stretched in the
output just as much as the signal itself, as crossfade speed is set to equal
pitch factor. For pitch factors below 0.5, the read pointer wants to jump
forward before one period is read, therefore the crossfade length as expressed
in output periods must be shorter. Crossfade speed is set to [1 - pitchfactor]
for those cases. Pitch factor 0.5 is the natural switch point between crossfade
speeds [pitchfactor] and [1 - pitchfactor] because 0.5 == 1 - 0.5. The crossfade
speed modification for pitch factors below 0.5 also means that much of the
original signal content will be skipped.
Function pitchdown () is called to read samples from the delay buffer when pitch factor is between 0 . 25 and 1 . The read pointer lags behind because of the slowed down speed and it must jump forward towards the write pointer soon as there is sufficient space to jump . That is if there is at least one period of the input signal between read pointer and write pointer . When short periods follow up on long periods the read pointer may have space to jump over more than one period lenghts . Jump length must be [ periodlength ^ 2 ] in any case . A linear crossfade function joins the jump - from point with the jump - to point . The crossfade must be completed before another read pointer jump is allowed . Length of the crossfade function is stored as a number of samples in terms of the input sample rate . This length is dynamically translated to a crossfade length expressed in output reading rate according to pitch factor which can change before the crossfade is completed . Crossfade length does not cover an invariable length in periods for all pitch transposition factors . For pitch factors from 0 . 5 till 1 crossfade length is stretched in the output just as much as the signal itself as crossfade speed is set to equal pitch factor . For pitch factors below 0 . 5 the read pointer wants to jump forward before one period is read therefore the crossfade length as expressed in output periods must be shorter . Crossfade speed is set to [ 1 - pitchfactor ] for those cases . Pitch factor 0 . 5 is the natural switch point between crossfade speeds [ pitchfactor ] and [ 1 - pitchfactor ] because 0 . 5 == 1 - 0 . 5 . The crossfade speed modification for pitch factors below 0 . 5 also means that much of the original signal content will be skipped .
static void pitchdown(_tSOLAD* const w, float *out)
{
    int n = w->blocksize;
    float refindex = (float)(w->timeindex + w->loopSize); 
    float pitchfactor = w->pitchfactor;
    float period = w->period;
    float readlag = w->readlag;
    float readlagstep = 1 - pitchfactor;
    float jump = w->jump;
    float xfadevalue = w->xfadevalue;
    float xfadelength = w->xfadelength;
    float xfadespeed, xfadestep, readindex, outputsample;
    if(pitchfactor > 0.5) xfadespeed = pitchfactor;
    else xfadespeed = 1 - pitchfactor;
    xfadestep = xfadespeed / xfadelength;
    while(n--)
    {
        if(readlag > period)        
        {
            if(xfadevalue <= 0)      
            {
                jump = period;                           
                while((jump * 2) < readlag) jump *= 2;   
                readlag -= jump;                         
                xfadevalue = 1;                          
                xfadelength = period - 1;
                xfadestep = xfadespeed / xfadelength;
            }
        }
        readindex = refindex - readlag;
        outputsample = read_sample(w, readindex);
        if(xfadevalue > 0)
        {
            outputsample *= (1 - xfadevalue);                               
            outputsample += read_sample(w, readindex - jump) * xfadevalue;  
            xfadevalue -= xfadestep;
        }
        *out++ += outputsample;
        refindex += 1;
        readlag += readlagstep;
    }
    w->jump = jump;                 
    w->readlag = readlag;
    w->xfadevalue = xfadevalue;
    w->xfadelength = xfadelength;
}
static void pitchdown ( _tSOLAD * const w , float * out ) { int n = w -> blocksize ; float refindex = ( float ) ( w -> timeindex + w -> loopSize ) ; float pitchfactor = w -> pitchfactor ; float period = w -> period ; float readlag = w -> readlag ; float readlagstep = 1 - pitchfactor ; float jump = w -> jump ; float xfadevalue = w -> xfadevalue ; float xfadelength = w -> xfadelength ; float xfadespeed , xfadestep , readindex , outputsample ; if ( pitchfactor > 0.5 ) xfadespeed = pitchfactor ; else xfadespeed = 1 - pitchfactor ; xfadestep = xfadespeed / xfadelength ; while ( n -- ) { if ( readlag > period ) { if ( xfadevalue <= 0 ) { jump = period ; while ( ( jump * 2 ) < readlag ) jump *= 2 ; readlag -= jump ; xfadevalue = 1 ; xfadelength = period - 1 ; xfadestep = xfadespeed / xfadelength ; } } readindex = refindex - readlag ; outputsample = read_sample ( w , readindex ) ; if ( xfadevalue > 0 ) { outputsample *= ( 1 - xfadevalue ) ; outputsample += read_sample ( w , readindex - jump ) * xfadevalue ; xfadevalue -= xfadestep ; } * out ++ += outputsample ; refindex += 1 ; readlag += readlagstep ; } w -> jump = jump ; w -> readlag = readlag ; w -> xfadevalue = xfadevalue ; w -> xfadelength = xfadelength ; }
Function pitchdown() is called to read samples from the delay buffer when pitch
factor is between 0.25 and 1.
Function pitchdown () is called to read samples from the delay buffer when pitch factor is between 0 . 25 and 1 .
// no negative values!
 // check if read pointer may jump forward...
 // ...but do not interrupt crossfade
 // jump forward
 // use available space
 // reduce read pointer lag
 // start crossfade
 // fadein
 // fadeout
 // state variables
