Home   Information   Classes   Download   Usage   Mail List   Requirements   Links   FAQ   Tutorial


Guitar.h

00001 #ifndef STK_GUITAR_H
00002 #define STK_GUITAR_H
00003 
00004 #include "Stk.h"
00005 #include "Twang.h"
00006 #include "OnePole.h"
00007 #include "OneZero.h"
00008 
00009 namespace stk {
00010 
00011 /***************************************************/
00039 /***************************************************/
00040 
00041 class Guitar : public Stk
00042 {
00043  public:
00045   Guitar( unsigned int nStrings = 6, std::string bodyfile = "" );
00046 
00048   void clear( void );
00049 
00051 
00056   void setBodyFile( std::string bodyfile = "" );
00057 
00059 
00063   void setPluckPosition( StkFloat position, int string = -1 );
00064 
00066 
00070   void setLoopGain( StkFloat gain, int string = -1 );
00071 
00073   void setFrequency( StkFloat frequency, unsigned int string = 0 );
00074 
00076 
00080   void noteOn( StkFloat frequency, StkFloat amplitude, unsigned int string = 0 );
00081 
00083   void noteOff( StkFloat amplitude, unsigned int string = 0 );
00084 
00086 
00090   void controlChange( int number, StkFloat value, int string = -1 );
00091 
00093   StkFloat lastOut( void ) { return lastFrame_[0]; };
00094 
00096   StkFloat tick( StkFloat input = 0.0 );
00097 
00099 
00107   StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
00108 
00110 
00118   StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
00119 
00120  protected:
00121 
00122   std::vector< stk::Twang > strings_;
00123   std::vector< int > stringState_; // 0 = off, 1 = decaying, 2 = on
00124   std::vector< unsigned int > decayCounter_;
00125   std::vector< unsigned int > filePointer_;
00126   std::vector< StkFloat > pluckGains_;
00127 
00128   OnePole   pickFilter_;
00129   OnePole   couplingFilter_;
00130   StkFloat  couplingGain_;
00131   StkFrames excitation_;
00132   StkFrames lastFrame_;
00133 };
00134 
00135 inline StkFloat Guitar :: tick( StkFloat input )
00136 {
00137   StkFloat temp, output = 0.0;
00138   lastFrame_[0] /= strings_.size(); // evenly spread coupling across strings
00139   for ( unsigned int i=0; i<strings_.size(); i++ ) {
00140     if ( stringState_[i] ) {
00141       temp = input;
00142       // If pluckGain < 0.2, let string ring but don't pluck it.
00143       if ( filePointer_[i] < excitation_.frames() && pluckGains_[i] > 0.2 )
00144         temp += pluckGains_[i] * excitation_[filePointer_[i]++];
00145       temp += couplingGain_ * couplingFilter_.tick( lastFrame_[0] ); // bridge coupling
00146       output += strings_[i].tick( temp );
00147       // Check if string energy has decayed sufficiently to turn it off.
00148       if ( stringState_[i] == 1 ) {
00149         if ( fabs( strings_[i].lastOut() ) < 0.001 ) decayCounter_[i]++;
00150         else decayCounter_[i] = 0;
00151         if ( decayCounter_[i] > (unsigned int) floor( 0.1 * Stk::sampleRate() ) ) {
00152           stringState_[i] = 0;
00153           decayCounter_[i] = 0;
00154         }
00155       }
00156     }
00157   }
00158 
00159   return lastFrame_[0] = output;
00160 }
00161 
00162 inline StkFrames& Guitar :: tick( StkFrames& frames, unsigned int channel )
00163 {
00164 #if defined(_STK_DEBUG_)
00165   if ( channel >= frames.channels() ) {
00166     oStream_ << "Guitar::tick(): channel and StkFrames arguments are incompatible!";
00167     handleError( StkError::FUNCTION_ARGUMENT );
00168   }
00169 #endif
00170 
00171   StkFloat *samples = &frames[channel];
00172   unsigned int hop = frames.channels();
00173   for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
00174     *samples = tick( *samples );
00175 
00176   return frames;
00177 }
00178 
00179 inline StkFrames& Guitar :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
00180 {
00181 #if defined(_STK_DEBUG_)
00182   if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
00183     oStream_ << "Guitar::tick(): channel and StkFrames arguments are incompatible!";
00184     handleError( StkError::FUNCTION_ARGUMENT );
00185   }
00186 #endif
00187 
00188   StkFloat *iSamples = &iFrames[iChannel];
00189   StkFloat *oSamples = &oFrames[oChannel];
00190   unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
00191   for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop )
00192     *oSamples = tick( *iSamples );
00193 
00194   return iFrames;
00195 }
00196 
00197 } // stk namespace
00198 
00199 #endif

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