Arduino STK  4.6.2
Guitar.h
1 #ifndef STK_GUITAR_H
2 #define STK_GUITAR_H
3 
4 #include "Stk.h"
5 #include "Twang.h"
6 #include "OnePole.h"
7 #include "OneZero.h"
8 
9 namespace stk {
10 
11 /***************************************************/
39 /***************************************************/
40 
41 class Guitar : public Stk
42 {
43  public:
45  Guitar( unsigned int nStrings = 6, std::string bodyfile = "" );
46 
48  void clear( void );
49 
51 
56  void setBodyFile( std::string bodyfile = "" );
57 
59 
63  void setPluckPosition( StkFloat position, int string = -1 );
64 
66 
70  void setLoopGain( StkFloat gain, int string = -1 );
71 
73  void setFrequency( StkFloat frequency, unsigned int string = 0 );
74 
76 
80  void noteOn( StkFloat frequency, StkFloat amplitude, unsigned int string = 0 );
81 
83  void noteOff( StkFloat amplitude, unsigned int string = 0 );
84 
86 
90  void controlChange( int number, StkFloat value, int string = -1 );
91 
93  StkFloat lastOut( void ) { return lastFrame_[0]; };
94 
96  StkFloat tick( StkFloat input = 0.0 );
97 
99 
107  StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
108 
110 
118  StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
119 
120  protected:
121 
122  std::vector< stk::Twang > strings_;
123  std::vector< int > stringState_; // 0 = off, 1 = decaying, 2 = on
124  std::vector< unsigned int > decayCounter_;
125  std::vector< unsigned int > filePointer_;
126  std::vector< StkFloat > pluckGains_;
127 
128  OnePole pickFilter_;
129  OnePole couplingFilter_;
130  StkFloat couplingGain_;
131  StkFrames excitation_;
132  StkFrames lastFrame_;
133 };
134 
135 inline StkFloat Guitar :: tick( StkFloat input )
136 {
137  StkFloat temp, output = 0.0;
138  lastFrame_[0] /= strings_.size(); // evenly spread coupling across strings
139  for ( unsigned int i=0; i<strings_.size(); i++ ) {
140  if ( stringState_[i] ) {
141  temp = input;
142  // If pluckGain < 0.2, let string ring but don't pluck it.
143  if ( filePointer_[i] < excitation_.frames() && pluckGains_[i] > 0.2 )
144  temp += pluckGains_[i] * excitation_[filePointer_[i]++];
145  temp += couplingGain_ * couplingFilter_.tick( lastFrame_[0] ); // bridge coupling
146  output += strings_[i].tick( temp );
147  // Check if string energy has decayed sufficiently to turn it off.
148  if ( stringState_[i] == 1 ) {
149  if ( fabs( strings_[i].lastOut() ) < 0.001 ) decayCounter_[i]++;
150  else decayCounter_[i] = 0;
151  if ( decayCounter_[i] > (unsigned int) floor( 0.1 * Stk::sampleRate() ) ) {
152  stringState_[i] = 0;
153  decayCounter_[i] = 0;
154  }
155  }
156  }
157  }
158 
159  return lastFrame_[0] = output;
160 }
161 
162 inline StkFrames& Guitar :: tick( StkFrames& frames, unsigned int channel )
163 {
164 #if defined(_STK_DEBUG_)
165  if ( channel >= frames.channels() ) {
166  oStream_ << "Guitar::tick(): channel and StkFrames arguments are incompatible!";
167  handleError( StkError::FUNCTION_ARGUMENT );
168  }
169 #endif
170 
171  StkFloat *samples = &frames[channel];
172  unsigned int hop = frames.channels();
173  for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
174  *samples = tick( *samples );
175 
176  return frames;
177 }
178 
179 inline StkFrames& Guitar :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
180 {
181 #if defined(_STK_DEBUG_)
182  if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
183  oStream_ << "Guitar::tick(): channel and StkFrames arguments are incompatible!";
184  handleError( StkError::FUNCTION_ARGUMENT );
185  }
186 #endif
187 
188  StkFloat *iSamples = &iFrames[iChannel];
189  StkFloat *oSamples = &oFrames[oChannel];
190  unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
191  for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop )
192  *oSamples = tick( *iSamples );
193 
194  return iFrames;
195 }
196 
197 } // stk namespace
198 
199 #endif
STK guitar model class.
Definition: Guitar.h:42
StkFloat tick(StkFloat input=0.0)
Take an optional input sample and compute one output sample.
Definition: Guitar.h:135
void setPluckPosition(StkFloat position, int string=-1)
Set the pluck position for one or all strings.
Guitar(unsigned int nStrings=6, std::string bodyfile="")
Class constructor, specifying an arbitrary number of strings (default = 6).
void setFrequency(StkFloat frequency, unsigned int string=0)
Set instrument parameters for a particular frequency.
void setBodyFile(std::string bodyfile="")
Set the string excitation, using either a soundfile or computed noise.
void noteOn(StkFloat frequency, StkFloat amplitude, unsigned int string=0)
Start a note with the given frequency and amplitude.
void noteOff(StkFloat amplitude, unsigned int string=0)
Stop a note with the given amplitude (speed of decay).
void clear(void)
Reset and clear all internal state.
void setLoopGain(StkFloat gain, int string=-1)
Set the loop gain for one or all strings.
void controlChange(int number, StkFloat value, int string=-1)
Perform the control change specified by number and value (0.0 - 128.0).
StkFloat lastOut(void)
Return the last computed output value.
Definition: Guitar.h:93
STK one-pole filter class.
Definition: OnePole.h:21
StkFloat tick(StkFloat input)
Input one sample to the filter and return one output.
Definition: OnePole.h:80
An STK class to handle vectorized audio data.
Definition: Stk.h:287
unsigned int channels(void) const
Return the number of channels represented by the data.
Definition: Stk.h:415
unsigned int frames(void) const
Return the number of sample frames represented by the data.
Definition: Stk.h:418
STK base class.
Definition: Stk.h:144
static void handleError(const char *message, StkError::Type type)
Static function for error reporting and handling using c-strings.
static StkFloat sampleRate(void)
Static method that returns the current STK sample rate.
Definition: Stk.h:156
The STK namespace.
Definition: ADSR.h:8