The Synthesis ToolKit in C++ (STK)

Home Information Classes Download Usage Mail List Requirements Links FAQ Tutorial

# stk::LentPitShift Class Reference

Pitch shifter effect class based on the Lent algorithm. More...

`#include <LentPitShift.h>`

Inheritance diagram for stk::LentPitShift:

List of all members.

## Public Member Functions
| LentPitShift (StkFloat periodRatio=1.0, int tMax=RT_BUFFER_SIZE)
| Class constructor.
void | clear (void)
| Reset and clear all internal state.
void | setShift (StkFloat shift)
| Set the pitch shift factor (1.0 produces no shift).
StkFloat | tick (StkFloat input)
| Input one sample to the filter and return one output.
StkFrames & | tick (StkFrames &frames, unsigned int channel=0)
| Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
StkFrames & | tick (StkFrames &iFrames, StkFrames &oFrames, unsigned int iChannel=0, unsigned int oChannel=0)
| Take a channel of the `iFrames` object as inputs to the filter and write outputs to the `oFrames` object.
## Protected Member Functions
void | process ()
| Apply the effect on the input samples and store it.

## Detailed Description

Pitch shifter effect class based on the Lent algorithm.

This class implements a pitch shifter using pitch tracking and sample windowing and shifting.

by Francois Germain, 2009.

## Member Function Documentation

StkFrames & stk::LentPitShift::tick | ( | StkFrames & | frames,
|  | unsigned int | channel = `0` |
| ) |  |  | `[inline]`

Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.

The StkFrames argument reference is returned. The `channel` argument must be less than the number of channels in the StkFrames argument (the first channel is specified by 0). However, range checking is only performed if _STK_DEBUG_ is defined during compilation, in which case an out-of-range value will trigger an StkError exception.

    00224 {
    00225 #if defined(_STK_DEBUG_)
    00226   if ( channel >= frames.channels() ) {
    00227     oStream_ << "LentPitShift::tick(): channel and StkFrames arguments are incompatible!";
    00228     handleError( StkError::FUNCTION_ARGUMENT );
    00229   }
    00230 #endif
    00231
    00232   StkFloat *samples = &frames[channel];
    00233   unsigned int hop = frames.channels();
    00234   for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
    00235     *samples = tick( *samples );
    00236   }
    00237
    00238   return frames;
    00239 }

StkFrames & stk::LentPitShift::tick | ( | StkFrames & | iFrames,
|  | StkFrames & | oFrames,
|  | unsigned int | iChannel = `0`,
|  | unsigned int | oChannel = `0` |
| ) |  |  | `[inline]`

Take a channel of the `iFrames` object as inputs to the filter and write outputs to the `oFrames` object.

The `iFrames` object reference is returned. Each channel argument must be less than the number of channels in the corresponding StkFrames argument (the first channel is specified by 0). However, range checking is only performed if _STK_DEBUG_ is defined during compilation, in which case an out-of-range value will trigger an StkError exception.

    00242 {
    00243 #if defined(_STK_DEBUG_)
    00244   if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
    00245     oStream_ << "LentPitShift::tick(): channel and StkFrames arguments are incompatible!";
    00246     handleError( StkError::FUNCTION_ARGUMENT );
    00247   }
    00248 #endif
    00249
    00250   StkFloat *iSamples = &iFrames[iChannel];
    00251   StkFloat *oSamples = &oFrames[oChannel];
    00252   unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
    00253   for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
    00254     *oSamples = tick( *iSamples );
    00255   }
    00256
    00257   return iFrames;
    00258 }

void stk::LentPitShift::process | ( |  | ) | `[inline, protected]`

Apply the effect on the input samples and store it.

The samples stored in the input frame vector are processed and the delayed result are stored in the output frame vector.

    00110 {
    00111   StkFloat x_t;    // input coefficient
    00112   StkFloat x_t_T;  // previous input coefficient at T samples
    00113   StkFloat coeff;  // new coefficient for the difference function
    00114
    00115   int alternativePitch = tMax_;  // Global minimum storage
    00116   lastPeriod_ = tMax_+1;         // Storage of the lowest local minimum under the threshold
    00117
    00118   // Loop variables
    00119   unsigned long delay_;
    00120   unsigned int n;
    00121
    00122   // Initialization of the dt coefficients.  Since the
    00123   // frames are of tMax_ length, there is no overlapping
    00124   // between the successive windows where pitch tracking
    00125   // is performed.
    00126   for ( delay_=1; delay_<=tMax_; delay_++ )
    00127     dt[delay_] = 0.;
    00128
    00129   // Calculation of the dt coefficients and update of the input delay line.
    00130   for ( n=0; n<inputFrames.size(); n++ ) {
    00131     x_t = inputLine_.tick( inputFrames[ n ] );
    00132     for ( delay_=1; delay_<= tMax_; delay_++ ) {
    00133       x_t_T = inputLine_.tapOut( delay_ );
    00134       coeff = x_t - x_t_T;
    00135       dt[delay_] += coeff * coeff;
    00136     }
    00137   }
    00138
    00139   // Calculation of the pitch tracking function and test for the minima.
    00140   for ( delay_=1; delay_<=tMax_; delay_++ ) {
    00141     cumDt[delay_] = dt[delay_] + cumDt[delay_-1];
    00142     dpt[delay_] = dt[delay_] * delay_ / cumDt[delay_];
    00143
    00144     // Look for a minimum
    00145     if ( dpt[delay_-1]-dpt[delay_-2] < 0 && dpt[delay_]-dpt[delay_-1] > 0 ) {
    00146       // Check if the minimum is under the threshold
    00147       if ( dpt[delay_-1] < threshold_ ){
    00148         lastPeriod_ = delay_-1;
    00149         // If a minimum is found, we can stop the loop
    00150         break;
    00151       }
    00152       else if ( dpt[alternativePitch] > dpt[delay_-1] )
    00153         // Otherwise we store it if it is the current global minimum
    00154         alternativePitch = delay_-1;
    00155     }
    00156   }
    00157
    00158   // Test for the last period length.
    00159   if ( dpt[delay_]-dpt[delay_-1] < 0 ) {
    00160     if ( dpt[delay_] < threshold_ )
    00161       lastPeriod_ = delay_;
    00162     else if ( dpt[alternativePitch] > dpt[delay_] )
    00163       alternativePitch = delay_;
    00164   }
    00165
    00166   if ( lastPeriod_ == tMax_+1 )
    00167     // No period has been under the threshold so we used the global minimum
    00168     lastPeriod_ = alternativePitch;
    00169
    00170   // We put the new zero output coefficients in the output delay line and
    00171   // we get the previous calculated coefficients
    00172   outputLine_.tick( zeroFrame, outputFrames );
    00173
    00174   // Initialization of the Hamming window used in the algorithm
    00175   for ( int n=-(int)lastPeriod_; n<(int)lastPeriod_; n++ )
    00176     window[n+lastPeriod_] = (1 + cos(PI*n/lastPeriod_)) / 2    ;
    00177
    00178   int M;  // Index of reading in the input delay line
    00179   int N;  // Index of writing in the output delay line
    00180   double sample;  // Temporary storage for the new coefficient
    00181
    00182   // We loop for all the frames of length lastPeriod_ presents between inputPtr and tMax_
    00183   for ( ; inputPtr<(int)(tMax_-lastPeriod_); inputPtr+=lastPeriod_ ) {
    00184     // Test for the decision of compression/expansion
    00185     while ( outputPtr < inputPtr ) {
    00186       // Coefficients for the linear interpolation
    00187       env[1] = fmod( outputPtr + tMax_, 1.0 );
    00188       env[0] = 1.0 - env[1];
    00189       M = tMax_ - inputPtr + lastPeriod_ - 1; // New reading pointer
    00190       N = 2*tMax_ - (unsigned long)floor(outputPtr + tMax_) + lastPeriod_ - 1; // New writing pointer
    00191       for ( unsigned int j=0; j<2*lastPeriod_; j++,M--,N-- ) {
    00192         sample = inputLine_.tapOut(M) * window[j] / 2.;
    00193         // Linear interpolation
    00194         outputLine_.addTo(env[0] * sample, N);
    00195         outputLine_.addTo(env[1] * sample, N-1);
    00196       }
    00197       outputPtr = outputPtr + lastPeriod_ * periodRatio_; // new output pointer
    00198     }
    00199   }
    00200   // Shifting of the pointers waiting for the new frame of length tMax_.
    00201   outputPtr -= tMax_;
    00202   inputPtr  -= tMax_;
    00203 }

The documentation for this class was generated from the following file:

- LentPitShift.h

The Synthesis ToolKit in C++ (STK)
©1995-2012 Perry R. Cook and Gary P. Scavone. All Rights Reserved.