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:
stk::Effect stk::Stk

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.
StkFramestick (StkFrames &frames, unsigned int channel=0)
 Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
StkFramestick (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:

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