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.

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

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.

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

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

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


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

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