+
+How to Use Treesed
+
+Go to the directory where you want to search or make changes.
+
+
+There are two choices you can make when using treesed:
+
+- Do I just want to search for a text, or do I want to search for a
+text and replace it with something else?
+
+If you are just searching you are using Treesed in "search mode", otherwise it is in
+"replace mode."
+ - Do I want to search/replace only in files in my current directory,
+or should files in all subdirectories (and all directories below that)
+also be done?
+
+Some examples will make this clear.
+
+Searching
+Say you are faced with the situation that the author of a slew of web-pages, Nathan Brazil, has left and has been succeeded by Mavra Chang. First, let us see which files are affected by this (what you type in is shown in bold):
+
+[localhost] treesed "Nathan Brazil" -files *.html
+search_pattern: Nathan\ Brazil
+replacement_pattern:
+
+** Search mode
+
+.
+midnight.html: 1 lines on: 2
+..
+well.html: 1 lines on: 3
+
+
+We notice the following:
+
+- The search text "Nathan Brazil" is enclosed in
+double-quotes (").
+
- You specify which files to search with -files followed by a
+list of file names--in this case *.html.
+
- Treesed reports the search pattern ("pattern" is just a fancy word
+for "text") you specified (you can ignore
+that \).
+
- Treesed reports an empty replacement_pattern. This is
+correct, because you haven't entered one.
+
- It therefore deduces that is is in search mode.
+
- It finds two files containing "Nathan Brazil", and reports on which
+lines of these files it found it; it does not show the lines themselves.
+
+Because you used -files, Treesed will search in the files you
+specify in the current directory. You can also search files in
+the current directory and all directories below it. However, in
+that case you can not specify which file names to use, all files will be
+searched:
+
+[localhost] treesed "Nathan Brazil" -tree
+search_pattern: Nathan\ Brazil
+replacement_pattern:
+
+** Search mode
+
+.
+midnight.html: 1 lines on: 2
+...
+well.html: 1 lines on: 3
+.
+new/echoes.html: 1 lines on: 2
+
+
+We notice the following:
+
+- Instead of -files we now see -tree.
+
- We do not see a specification of file names.
+
- Treesed finds an occurence of "Nathan Brazil" in the file
+echoes.html in the subdirectory new; it did not
+find this file in the previous example (as it shouldn't).
+
+
+Replacing
+To replace a text you simply add the replacement text right after the
+search text:
+
+[localhost] treesed "Nathan Brazil" "Mavra Change" -files *.html
+search_pattern: Nathan\ Brazil
+replacement_pattern: Mavra Chang
+
+** EDIT MODE!
+
+.
+midnight.html: 1 lines on: 2
+
+Replaced Nathan\ Brazil by Mavra Chang on 1 lines in midnight.html
+..
+well.html: 1 lines on: 3
+
+Replaced Nathan\ Brazil by Mavra Chang on 1 lines in well.html
+
+
+We notice the following:
+
+- Right after the search text "Nathan Brazil" you specify the
+replacement text "Mavra Chang".
+
- As a result, Treesed now reports a non-empty
+replacement_pattern.
+
- Hence it concludes it is in "edit mode", which means replacment mode.
+
- Treesed dutifully reports on which lines in which files it did the
+replacement.
+
+To replace a text in all files in the current directory and the ones
+below it, we do the following:
+
+[localhost] treesed "Nathan Brazil" "Mavra Chang" -tree
+search_pattern: Nathan\ Brazil
+replacement_pattern: Mavra Chang
+
+** EDIT MODE!
+
+.
+midnight.html: 1 lines on: 2
+
+Replaced Nathan\ Brazil by Mavra Chang on 1 lines in midnight.html
+
+....
+well.html: 1 lines on: 3
+
+Replaced Nathan\ Brazil by Mavra Chang on 1 lines in well.html
+.
+new/echoes.html: 1 lines on: 2
+
+Replaced Nathan\ Brazil by Mavra Chang on 1 lines in new/echoes.html
+
+
+and we get the expected results, including the replace in
+new/echoes.html.
+
+Old Versions
+Treesed leaves behind quite a mess of old versions of the files it
+changed (only in change-mode, of course). These old files have the same
+name as the original file, with .ddddd appended to it. For
+example, if treesed makes a change to midnight.html it will
+leave the original version as something like
+midnight.html.26299. You'll have to remove these files lest
+your disk area clutters up. Here is a command that does that, but
+beware! This command removes all files in the current directory and
+all below it, that end in a period followed by one or more
+digits:
+
+find . -name "*.[0-9]*" -exec rm {} \;
+
+
+
+It is interesting to note that if you use treesed again without cleaning
+up, you may get files like midnight.html.26299.27654. These
+will also be cleaned up by the above slightly dangerous command.
+
+
+About Treesed
+treesed is public domain software developed
+and designed by Rick Jansen from Sara, Amsterdam, Netherlands, January
+1996.
+
+
+
+ About This Document
+This usage document was created by the Division of Information Technology Services at The
+University of Western Ontario.
+
+
\ No newline at end of file
diff --git a/include/ADSR.h b/include/ADSR.h
index c1971e8..afa6040 100644
--- a/include/ADSR.h
+++ b/include/ADSR.h
@@ -1,86 +1,163 @@
+#ifndef STK_ADSR_H
+#define STK_ADSR_H
+
+#include "Generator.h"
+
+namespace stk {
+
/***************************************************/
/*! \class ADSR
\brief STK ADSR envelope class.
- This Envelope subclass implements a
- traditional ADSR (Attack, Decay,
- Sustain, Release) envelope. It
- responds to simple keyOn and keyOff
- messages, keeping track of its state.
- The \e state = ADSR::DONE after the
- envelope value reaches 0.0 in the
- ADSR::RELEASE state.
+ This class implements a traditional ADSR (Attack, Decay, Sustain,
+ Release) envelope. It responds to simple keyOn and keyOff
+ messages, keeping track of its state. The \e state = ADSR::DONE
+ after the envelope value reaches 0.0 in the ADSR::RELEASE state.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_ADSR_H
-#define STK_ADSR_H
-
-#include "Envelope.h"
-
-class ADSR : public Envelope
+class ADSR : public Generator
{
public:
- //! Envelope states.
- enum { ATTACK, DECAY, SUSTAIN, RELEASE, DONE };
+ //! ADSR envelope states.
+ enum {
+ ATTACK, /*!< Attack */
+ DECAY, /*!< Decay */
+ SUSTAIN, /*!< Sustain */
+ RELEASE, /*!< Release */
+ DONE /*!< End of release */
+ };
//! Default constructor.
- ADSR(void);
+ ADSR( void );
//! Class destructor.
- ~ADSR(void);
+ ~ADSR( void );
//! Set target = 1, state = \e ADSR::ATTACK.
- void keyOn(void);
+ void keyOn( void );
//! Set target = 0, state = \e ADSR::RELEASE.
- void keyOff(void);
+ void keyOff( void );
//! Set the attack rate.
- void setAttackRate(StkFloat rate);
+ void setAttackRate( StkFloat rate );
//! Set the decay rate.
- void setDecayRate(StkFloat rate);
+ void setDecayRate( StkFloat rate );
//! Set the sustain level.
- void setSustainLevel(StkFloat level);
+ void setSustainLevel( StkFloat level );
//! Set the release rate.
- void setReleaseRate(StkFloat rate);
+ void setReleaseRate( StkFloat rate );
//! Set the attack rate based on a time duration.
- void setAttackTime(StkFloat time);
+ void setAttackTime( StkFloat time );
//! Set the decay rate based on a time duration.
- void setDecayTime(StkFloat time);
+ void setDecayTime( StkFloat time );
//! Set the release rate based on a time duration.
- void setReleaseTime(StkFloat time);
+ void setReleaseTime( StkFloat time );
//! Set sustain level and attack, decay, and release time durations.
- void setAllTimes(StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime);
+ void setAllTimes( StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime );
//! Set the target value.
- void setTarget(StkFloat target);
+ void setTarget( StkFloat target );
//! Return the current envelope \e state (ATTACK, DECAY, SUSTAIN, RELEASE, DONE).
- int getState(void) const;
+ int getState( void ) const { return state_; };
- //! Set to state = ADSR::SUSTAIN with current and target values of \e aValue.
- void setValue(StkFloat value);
+ //! Set to state = ADSR::SUSTAIN with current and target values of \e value.
+ void setValue( StkFloat value );
+
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Compute and return one output sample.
+ StkFloat tick( void );
+
+ //! Fill a channel of the StkFrames object with computed outputs.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
+ int state_;
+ StkFloat value_;
+ StkFloat target_;
StkFloat attackRate_;
StkFloat decayRate_;
- StkFloat sustainLevel_;
StkFloat releaseRate_;
+ StkFloat sustainLevel_;
};
+inline StkFloat ADSR :: tick( void )
+{
+ switch ( state_ ) {
+
+ case ATTACK:
+ value_ += attackRate_;
+ if ( value_ >= target_ ) {
+ value_ = target_;
+ target_ = sustainLevel_;
+ state_ = DECAY;
+ }
+ lastFrame_[0] = value_;
+ break;
+
+ case DECAY:
+ value_ -= decayRate_;
+ if ( value_ <= sustainLevel_ ) {
+ value_ = sustainLevel_;
+ state_ = SUSTAIN;
+ }
+ lastFrame_[0] = value_;
+ break;
+
+ case RELEASE:
+ value_ -= releaseRate_;
+ if ( value_ <= 0.0 ) {
+ value_ = (StkFloat) 0.0;
+ state_ = DONE;
+ }
+ lastFrame_[0] = value_;
+
+ }
+
+ return value_;
+}
+
+inline StkFrames& ADSR :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "ADSR::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i 0).
/*!
@@ -53,21 +55,89 @@ class Asymp : public Envelope
fast approach rates, while values greater than 1.0 produce rather
slow rates.
*/
- void setTau(StkFloat tau);
+ void setTau( StkFloat tau );
//! Set the asymptotic rate based on a time duration (must be > 0).
- void setTime(StkFloat time);
+ void setTime( StkFloat time );
//! Set the target value.
- void setTarget(StkFloat target);
+ void setTarget( StkFloat target );
+
+ //! Set current and target values to \e value.
+ void setValue( StkFloat value );
+
+ //! Return the current envelope \e state (0 = at target, 1 otherwise).
+ int getState( void ) const { return state_; };
+
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Compute and return one output sample.
+ StkFloat tick( void );
+
+ //! Fill a channel of the StkFrames object with computed outputs.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
+ StkFloat value_;
+ StkFloat target_;
StkFloat factor_;
StkFloat constant_;
+ int state_;
};
+inline StkFloat Asymp :: tick( void )
+{
+ if ( state_ ) {
+
+ value_ = factor_ * value_ + constant_;
+
+ // Check threshold.
+ if ( target_ > value_ ) {
+ if ( target_ - value_ <= TARGET_THRESHOLD ) {
+ value_ = target_;
+ state_ = 0;
+ }
+ }
+ else {
+ if ( value_ - target_ <= TARGET_THRESHOLD ) {
+ value_ = target_;
+ state_ = 0;
+ }
+ }
+ lastFrame_[0] = value_;
+ }
+
+ return value_;
+}
+
+inline StkFrames& Asymp :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Asymp::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i 0.0 ) {
+ temp = 1.0 + ( modDepth_ * vibrato_.tick() * 0.1 );
+ waves_[0]->setFrequency( baseFrequency_ * temp * ratios_[0] );
+ waves_[1]->setFrequency( baseFrequency_ * temp * ratios_[1] );
+ waves_[2]->setFrequency( baseFrequency_ * temp * ratios_[2] );
+ waves_[3]->setFrequency( baseFrequency_ * temp * ratios_[3] );
+ }
+
+ waves_[3]->addPhaseOffset( twozero_.lastOut() );
+ temp = control1_ * 2.0 * gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
+ twozero_.tick( temp );
+
+ temp += control2_ * 2.0 * gains_[2] * adsr_[2]->tick() * waves_[2]->tick();
+ temp += gains_[1] * adsr_[1]->tick() * waves_[1]->tick();
+ temp += gains_[0] * adsr_[0]->tick() * waves_[0]->tick();
+
+ lastFrame_[0] = temp * 0.125;
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/BiQuad.h b/include/BiQuad.h
index d1951f6..c4640de 100644
--- a/include/BiQuad.h
+++ b/include/BiQuad.h
@@ -1,23 +1,23 @@
-/***************************************************/
-/*! \class BiQuad
- \brief STK biquad (two-pole, two-zero) filter class.
-
- This protected Filter subclass implements a
- two-pole, two-zero digital filter. A method
- is provided for creating a resonance in the
- frequency response while maintaining a constant
- filter gain.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
#ifndef STK_BIQUAD_H
#define STK_BIQUAD_H
#include "Filter.h"
-class BiQuad : protected Filter
+namespace stk {
+
+/***************************************************/
+/*! \class BiQuad
+ \brief STK biquad (two-pole, two-zero) filter class.
+
+ This class implements a two-pole, two-zero digital filter.
+ Methods are provided for creating a resonance or notch in the
+ frequency response while maintaining a constant filter gain.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
+*/
+/***************************************************/
+
+class BiQuad : public Filter
{
public:
@@ -25,28 +25,28 @@ public:
BiQuad();
//! Class destructor.
- virtual ~BiQuad();
+ ~BiQuad();
//! A function to enable/disable the automatic updating of class data when the STK sample rate changes.
void ignoreSampleRateChange( bool ignore = true ) { ignoreSampleRateChange_ = ignore; };
- //! Clears all internal states of the filter.
- void clear(void);
+ //! Set all filter coefficients.
+ void setCoefficients( StkFloat b0, StkFloat b1, StkFloat b2, StkFloat a1, StkFloat a2, bool clearState = false );
//! Set the b[0] coefficient value.
- void setB0(StkFloat b0);
+ void setB0( StkFloat b0 ) { b_[0] = b0; };
//! Set the b[1] coefficient value.
- void setB1(StkFloat b1);
+ void setB1( StkFloat b1 ) { b_[1] = b1; };
//! Set the b[2] coefficient value.
- void setB2(StkFloat b2);
+ void setB2( StkFloat b2 ) { b_[2] = b2; };
//! Set the a[1] coefficient value.
- void setA1(StkFloat a1);
+ void setA1( StkFloat a1 ) { a_[1] = a1; };
//! Set the a[2] coefficient value.
- void setA2(StkFloat a2);
+ void setA2( StkFloat a2 ) { a_[2] = a2; };
//! Sets the filter coefficients for a resonance at \e frequency (in Hz).
/*!
@@ -60,7 +60,7 @@ public:
frequency. The closer the poles are to the unit-circle (\e radius
close to one), the narrower the resulting resonance width.
*/
- void setResonance(StkFloat frequency, StkFloat radius, bool normalize = false);
+ void setResonance( StkFloat frequency, StkFloat radius, bool normalize = false );
//! Set the filter coefficients for a notch at \e frequency (in Hz).
/*!
@@ -69,7 +69,7 @@ public:
and \e radius from the z-plane origin. No filter normalization
is attempted.
*/
- void setNotch(StkFloat frequency, StkFloat radius);
+ void setNotch( StkFloat frequency, StkFloat radius );
//! Sets the filter zeroes for equal resonance gain.
/*!
@@ -78,62 +78,106 @@ public:
where R is the pole radius setting.
*/
- void setEqualGainZeroes();
-
- //! Set the filter gain.
- /*!
- The gain is applied at the filter input and does not affect the
- coefficient values. The default gain value is 1.0.
- */
- void setGain(StkFloat gain);
-
- //! Return the current filter gain.
- StkFloat getGain(void) const;
+ void setEqualGainZeroes( void );
//! Return the last computed output value.
- StkFloat lastOut(void) const;
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
- //! Input one sample to the filter and return one output.
- virtual StkFloat tick(StkFloat sample);
+ //! Input one sample to the filter and return a reference to one output.
+ StkFloat tick( StkFloat input );
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
- The \c channel argument should be zero or greater (the first
- channel is specified by 0). An StkError will be thrown if the \c
- channel argument is equal to or greater than the number of
- channels in the StkFrames object.
+ The StkFrames argument reference is returned. The \c 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.
*/
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+ //! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
- // This function must be implemented in all subclasses. It is used
- // to get around a C++ problem with overloaded virtual functions.
- virtual StkFloat computeSample( StkFloat input );
virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
};
-inline StkFloat BiQuad :: computeSample( StkFloat input )
+inline StkFloat BiQuad :: tick( StkFloat input )
{
inputs_[0] = gain_ * input;
- outputs_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2];
- outputs_[0] -= a_[2] * outputs_[2] + a_[1] * outputs_[1];
+ lastFrame_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2];
+ lastFrame_[0] -= a_[2] * outputs_[2] + a_[1] * outputs_[1];
inputs_[2] = inputs_[1];
inputs_[1] = inputs_[0];
outputs_[2] = outputs_[1];
- outputs_[1] = outputs_[0];
+ outputs_[1] = lastFrame_[0];
- return outputs_[0];
-}
-
-inline StkFloat BiQuad :: tick( StkFloat input )
-{
- return this->computeSample( input );
+ return lastFrame_[0];
}
inline StkFrames& BiQuad :: tick( StkFrames& frames, unsigned int channel )
{
- return Filter::tick( frames, channel );
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "BiQuad::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "BiQuad::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i
+#include
+
+namespace stk {
+
/***************************************************/
/*! \class Blit
\brief STK band-limited impulse train class.
@@ -21,11 +30,6 @@
*/
/***************************************************/
-#ifndef STK_BLIT_H
-#define STK_BLIT_H
-
-#include "Generator.h"
-
class Blit: public Generator
{
public:
@@ -68,10 +72,25 @@ class Blit: public Generator
*/
void setHarmonics( unsigned int nHarmonics = 0 );
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Compute and return one output sample.
+ StkFloat tick( void );
+
+ //! Fill a channel of the StkFrames object with computed outputs.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
protected:
void updateHarmonics( void );
- StkFloat computeSample( void );
unsigned int nHarmonics_;
unsigned int m_;
@@ -81,4 +100,52 @@ class Blit: public Generator
};
+inline StkFloat Blit :: tick( void )
+{
+ // The code below implements the SincM algorithm of Stilson and
+ // Smith with an additional scale factor of P / M applied to
+ // normalize the output.
+
+ // A fully optimized version of this code would replace the two sin
+ // calls with a pair of fast sin oscillators, for which stable fast
+ // two-multiply algorithms are well known. In the spirit of STK,
+ // which favors clarity over performance, the optimization has not
+ // been made here.
+
+ // Avoid a divide by zero at the sinc peak, which has a limiting
+ // value of 1.0.
+ StkFloat tmp, denominator = sin( phase_ );
+ if ( denominator <= std::numeric_limits::epsilon() )
+ tmp = 1.0;
+ else {
+ tmp = sin( m_ * phase_ );
+ tmp /= m_ * denominator;
+ }
+
+ phase_ += rate_;
+ if ( phase_ >= PI ) phase_ -= PI;
+
+ lastFrame_[0] = tmp;
+ return lastFrame_[0];
+}
+
+inline StkFrames& Blit :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Blit::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i
+#include
+
+namespace stk {
+
/***************************************************/
/*! \class BlitSaw
\brief STK band-limited sawtooth wave class.
@@ -19,11 +28,6 @@
*/
/***************************************************/
-#ifndef STK_BLITSAW_H
-#define STK_BLITSAW_H
-
-#include "Generator.h"
-
class BlitSaw: public Generator
{
public:
@@ -54,10 +58,25 @@ class BlitSaw: public Generator
*/
void setHarmonics( unsigned int nHarmonics = 0 );
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Compute and return one output sample.
+ StkFloat tick( void );
+
+ //! Fill a channel of the StkFrames object with computed outputs.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
protected:
void updateHarmonics( void );
- StkFloat computeSample( void );
unsigned int nHarmonics_;
unsigned int m_;
@@ -70,4 +89,60 @@ class BlitSaw: public Generator
};
+inline StkFloat BlitSaw :: tick( void )
+{
+ // The code below implements the BLIT algorithm of Stilson and
+ // Smith, followed by a summation and filtering operation to produce
+ // a sawtooth waveform. After experimenting with various approaches
+ // to calculate the average value of the BLIT over one period, I
+ // found that an estimate of C2_ = 1.0 / period (in samples) worked
+ // most consistently. A "leaky integrator" is then applied to the
+ // difference of the BLIT output and C2_. (GPS - 1 October 2005)
+
+ // A fully optimized version of this code would replace the two sin
+ // calls with a pair of fast sin oscillators, for which stable fast
+ // two-multiply algorithms are well known. In the spirit of STK,
+ // which favors clarity over performance, the optimization has
+ // not been made here.
+
+ // Avoid a divide by zero, or use of a denormalized divisor
+ // at the sinc peak, which has a limiting value of m_ / p_.
+ StkFloat tmp, denominator = sin( phase_ );
+ if ( fabs(denominator) <= std::numeric_limits::epsilon() )
+ tmp = a_;
+ else {
+ tmp = sin( m_ * phase_ );
+ tmp /= p_ * denominator;
+ }
+
+ tmp += state_ - C2_;
+ state_ = tmp * 0.995;
+
+ phase_ += rate_;
+ if ( phase_ >= PI ) phase_ -= PI;
+
+ lastFrame_[0] = tmp;
+ return lastFrame_[0];
+}
+
+inline StkFrames& BlitSaw :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "BlitSaw::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i
+#include
+
+namespace stk {
+
/***************************************************/
/*! \class BlitSquare
\brief STK band-limited square wave class.
@@ -30,11 +39,6 @@
*/
/***************************************************/
-#ifndef STK_BLITSQUARE_H
-#define STK_BLITSQUARE_H
-
-#include "Generator.h"
-
class BlitSquare: public Generator
{
public:
@@ -77,10 +81,25 @@ class BlitSquare: public Generator
*/
void setHarmonics( unsigned int nHarmonics = 0 );
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Compute and return one output sample.
+ StkFloat tick( void );
+
+ //! Fill a channel of the StkFrames object with computed outputs.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
protected:
void updateHarmonics( void );
- StkFloat computeSample( void );
unsigned int nHarmonics_;
unsigned int m_;
@@ -92,4 +111,60 @@ class BlitSquare: public Generator
StkFloat dcbState_;
};
+inline StkFloat BlitSquare :: tick( void )
+{
+ StkFloat temp = lastBlitOutput_;
+
+ // A fully optimized version of this would replace the two sin calls
+ // with a pair of fast sin oscillators, for which stable fast
+ // two-multiply algorithms are well known. In the spirit of STK,
+ // which favors clarity over performance, the optimization has
+ // not been made here.
+
+ // Avoid a divide by zero, or use of a denomralized divisor
+ // at the sinc peak, which has a limiting value of 1.0.
+ StkFloat denominator = sin( phase_ );
+ if ( fabs( denominator ) < std::numeric_limits::epsilon() ) {
+ // Inexact comparison safely distinguishes betwen *close to zero*, and *close to PI*.
+ if ( phase_ < 0.1f || phase_ > TWO_PI - 0.1f )
+ lastBlitOutput_ = a_;
+ else
+ lastBlitOutput_ = -a_;
+ }
+ else {
+ lastBlitOutput_ = sin( m_ * phase_ );
+ lastBlitOutput_ /= p_ * denominator;
+ }
+
+ lastBlitOutput_ += temp;
+
+ // Now apply DC blocker.
+ lastFrame_[0] = lastBlitOutput_ - dcbState_ + 0.999 * lastFrame_[0];
+ dcbState_ = lastBlitOutput_;
+
+ phase_ += rate_;
+ if ( phase_ >= TWO_PI ) phase_ -= TWO_PI;
+
+ return lastFrame_[0];
+}
+
+inline StkFrames& BlitSquare :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "BlitSquare::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i
+
+namespace stk {
+
/***************************************************/
/*! \class BowTable
\brief STK bowed string table class.
@@ -5,23 +13,15 @@
This class implements a simple bowed string
non-linear function, as described by Smith (1986).
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_BOWTABL_H
-#define STK_BOWTABL_H
-
-#include "Function.h"
-
class BowTable : public Function
{
public:
//! Default constructor.
- BowTable();
-
- //! Class destructor.
- ~BowTable();
+ BowTable( void ) : offset_(0.0), slope_(0.1) {};
//! Set the table offset value.
/*!
@@ -30,22 +30,111 @@ public:
friction to vary with direction, use a non-zero
value for the offset. The default value is zero.
*/
- void setOffset(StkFloat offset);
+ void setOffset( StkFloat offset ) { offset_ = offset; };
//! Set the table slope value.
/*!
The table slope controls the width of the friction
pulse, which is related to bow force.
*/
- void setSlope(StkFloat slope);
+ void setSlope( StkFloat slope ) { slope_ = slope; };
+
+ //! Take one sample input and map to one sample of output.
+ StkFloat tick( StkFloat input );
+
+ //! Take a channel of the StkFrames object as inputs to the table and replace with corresponding outputs.
+ /*!
+ The StkFrames argument reference is returned. The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+ //! Take a channel of the \c iFrames object as inputs to the table and write outputs to the \c oFrames object.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
- StkFloat computeSample( StkFloat input );
-
StkFloat offset_;
StkFloat slope_;
};
+inline StkFloat BowTable :: tick( StkFloat input )
+{
+ // The input represents differential string vs. bow velocity.
+ StkFloat sample = input + offset_; // add bias to input
+ sample *= slope_; // then scale it
+ lastFrame_[0] = (StkFloat) fabs( (double) sample ) + (StkFloat) 0.75;
+ lastFrame_[0] = (StkFloat) pow( lastFrame_[0], (StkFloat) -4.0 );
+
+ // Set minimum friction to 0.0
+ // if ( lastFrame_[0] < 0.0 ) lastFrame_[0] = 0.0;
+
+ // Set maximum friction to 1.0.
+ if ( lastFrame_[0] > 1.0 ) lastFrame_[0] = (StkFloat) 1.0;
+
+ return lastFrame_[0];
+}
+
+inline StkFrames& BowTable :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "BowTable::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i 1.0) *samples = 1.0;
+ }
+
+ lastFrame_[0] = *(samples-hop);
+ return frames;
+}
+
+inline StkFrames& BowTable :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
+{
+#if defined(_STK_DEBUG_)
+ if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "BowTable::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i 1.0) *oSamples = 1.0;
+ }
+
+ lastFrame_[0] = *(oSamples-oHop);
+ return iFrames;
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Bowed.h b/include/Bowed.h
index e077ba9..b0b0fba 100644
--- a/include/Bowed.h
+++ b/include/Bowed.h
@@ -1,3 +1,16 @@
+#ifndef STK_BOWED_H
+#define STK_BOWED_H
+
+#include "Instrmnt.h"
+#include "DelayL.h"
+#include "BowTable.h"
+#include "OnePole.h"
+#include "BiQuad.h"
+#include "SineWave.h"
+#include "ADSR.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Bowed
\brief STK bowed string instrument class.
@@ -17,58 +30,48 @@
- Vibrato Gain = 1
- Volume = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_BOWED_H
-#define STK_BOWED_H
-
-#include "Instrmnt.h"
-#include "DelayL.h"
-#include "BowTable.h"
-#include "OnePole.h"
-#include "BiQuad.h"
-#include "SineWave.h"
-#include "ADSR.h"
-
class Bowed : public Instrmnt
{
public:
//! Class constructor, taking the lowest desired playing frequency.
- Bowed(StkFloat lowestFrequency);
+ Bowed( StkFloat lowestFrequency );
//! Class destructor.
- ~Bowed();
+ ~Bowed( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set instrument parameters for a particular frequency.
- void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Set vibrato gain.
- void setVibrato(StkFloat gain);
+ void setVibrato( StkFloat gain );
//! Apply breath pressure to instrument with given amplitude and rate of increase.
- void startBowing(StkFloat amplitude, StkFloat rate);
+ void startBowing( StkFloat amplitude, StkFloat rate );
//! Decrease breath pressure with given rate of decrease.
- void stopBowing(StkFloat rate);
+ void stopBowing( StkFloat rate );
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
DelayL neckDelay_;
DelayL bridgeDelay_;
BowTable bowTable_;
@@ -83,4 +86,27 @@ class Bowed : public Instrmnt
};
+inline StkFloat Bowed :: tick( unsigned int )
+{
+ StkFloat bowVelocity = maxVelocity_ * adsr_.tick();
+ StkFloat bridgeRefl = -stringFilter_.tick( bridgeDelay_.lastOut() );
+ StkFloat nutRefl = -neckDelay_.lastOut();
+ StkFloat stringVel = bridgeRefl + nutRefl; // Sum is string velocity
+ StkFloat velDiff = bowVelocity - stringVel; // Differential velocity
+ StkFloat newVel = velDiff * bowTable_.tick( velDiff ); // Non-Linear bow function
+ neckDelay_.tick(bridgeRefl + newVel); // Do string propagations
+ bridgeDelay_.tick(nutRefl + newVel);
+
+ if ( vibratoGain_ > 0.0 ) {
+ neckDelay_.setDelay( (baseDelay_ * (1.0 - betaRatio_) ) +
+ (baseDelay_ * vibratoGain_ * vibrato_.tick()) );
+ }
+
+ lastFrame_[0] = bodyFilter_.tick( bridgeDelay_.lastOut() );
+
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Brass.h b/include/Brass.h
index da13dde..76633d1 100644
--- a/include/Brass.h
+++ b/include/Brass.h
@@ -1,3 +1,15 @@
+#ifndef STK_BRASS_H
+#define STK_BRASS_H
+
+#include "Instrmnt.h"
+#include "DelayA.h"
+#include "BiQuad.h"
+#include "PoleZero.h"
+#include "ADSR.h"
+#include "SineWave.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Brass
\brief STK simple brass instrument class.
@@ -16,20 +28,10 @@
- Vibrato Gain = 1
- Volume = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_BRASS_H
-#define STK_BRASS_H
-
-#include "Instrmnt.h"
-#include "DelayA.h"
-#include "BiQuad.h"
-#include "PoleZero.h"
-#include "ADSR.h"
-#include "SineWave.h"
-
class Brass: public Instrmnt
{
public:
@@ -37,39 +39,40 @@ class Brass: public Instrmnt
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
- Brass(StkFloat lowestFrequency);
+ Brass( StkFloat lowestFrequency );
//! Class destructor.
- ~Brass();
+ ~Brass( );
//! Reset and clear all internal state.
- void clear();
+ void clear( );
//! Set instrument parameters for a particular frequency.
- void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Set the lips frequency.
- void setLip(StkFloat frequency);
+ void setLip( StkFloat frequency );
//! Apply breath pressure to instrument with given amplitude and rate of increase.
- void startBlowing(StkFloat amplitude, StkFloat rate);
+ void startBlowing( StkFloat amplitude, StkFloat rate );
//! Decrease breath pressure with given rate of decrease.
- void stopBlowing(StkFloat rate);
+ void stopBlowing( StkFloat rate );
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
DelayA delayLine_;
BiQuad lipFilter_;
PoleZero dcBlock_;
@@ -83,4 +86,25 @@ class Brass: public Instrmnt
};
+inline StkFloat Brass :: tick( unsigned int )
+{
+ StkFloat breathPressure = maxPressure_ * adsr_.tick();
+ breathPressure += vibratoGain_ * vibrato_.tick();
+
+ StkFloat mouthPressure = 0.3 * breathPressure;
+ StkFloat borePressure = 0.85 * delayLine_.lastOut();
+ StkFloat deltaPressure = mouthPressure - borePressure; // Differential pressure.
+ deltaPressure = lipFilter_.tick( deltaPressure ); // Force - > position.
+ deltaPressure *= deltaPressure; // Basic position to area mapping.
+ if ( deltaPressure > 1.0 ) deltaPressure = 1.0; // Non-linear saturation.
+
+ // The following input scattering assumes the mouthPressure = area.
+ lastFrame_[0] = deltaPressure * mouthPressure + ( 1.0 - deltaPressure) * borePressure;
+ lastFrame_[0] = delayLine_.tick( dcBlock_.tick( lastFrame_[0] ) );
+
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Chorus.h b/include/Chorus.h
index 046f6c8..cab498a 100644
--- a/include/Chorus.h
+++ b/include/Chorus.h
@@ -1,20 +1,23 @@
+#ifndef STK_CHORUS_H
+#define STK_CHORUS_H
+
+#include "Effect.h"
+#include "DelayL.h"
+#include "SineWave.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Chorus
\brief STK chorus effect class.
- This class implements a chorus effect.
+ This class implements a chorus effect. It takes a monophonic
+ input signal and produces a stereo output signal.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_CHORUS_H
-#define STK_CHORUS_H
-
-#include "Effect.h"
-#include "DelayL.h"
-#include "SineWave.h"
-
class Chorus : public Effect
{
public:
@@ -24,22 +27,62 @@ class Chorus : public Effect
*/
Chorus( StkFloat baseDelay = 6000 );
- //! Class destructor.
- ~Chorus();
-
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set modulation depth.
- void setModDepth(StkFloat depth);
+ void setModDepth( StkFloat depth ) { modDepth_ = depth; };
//! Set modulation frequency.
- void setModFrequency(StkFloat frequency);
+ void setModFrequency( StkFloat frequency );
+
+ //! Return the specified channel value of the last computed stereo frame.
+ /*!
+ Use the lastFrame() function to get both values of the last
+ computed stereo frame. The \c channel argument must be 0 or 1
+ (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.
+ */
+ StkFloat lastOut( unsigned int channel = 0 );
+
+ //! Input one sample to the effect and return the specified \c channel value of the computed stereo frame.
+ /*!
+ Use the lastFrame() function to get both values of the computed
+ stereo output frame. The \c channel argument must be 0 or 1 (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.
+ */
+ StkFloat tick( StkFloat input, unsigned int channel = 0 );
+
+ //! Take a channel of the StkFrames object as inputs to the effect and replace with stereo outputs.
+ /*!
+ The StkFrames argument reference is returned. The stereo
+ outputs are written to the StkFrames argument starting at the
+ specified \c channel. Therefore, the \c channel argument must be
+ less than ( channels() - 1 ) of 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+ //! Take a channel of the \c iFrames object as inputs to the effect and write stereo outputs to the \c oFrames object.
+ /*!
+ The \c iFrames object reference is returned. The \c iChannel
+ argument must be less than the number of channels in the \c
+ iFrames argument (the first channel is specified by 0). The \c
+ oChannel argument must be less than ( channels() - 1 ) of the \c
+ oFrames argument. 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.
+ */
+ StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
- StkFloat computeSample( StkFloat input );
-
DelayL delayLine_[2];
SineWave mods_[2];
StkFloat baseLength_;
@@ -47,5 +90,79 @@ class Chorus : public Effect
};
+inline StkFloat Chorus :: lastOut( unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel > 1 ) {
+ errorString_ << "Chorus::lastOut(): channel argument must be less than 2!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ return lastFrame_[channel];
+}
+
+inline StkFloat Chorus :: tick( StkFloat input, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel > 1 ) {
+ errorString_ << "Chorus::tick(): channel argument must be less than 2!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ delayLine_[0].setDelay( baseLength_ * 0.707 * ( 1.0 + modDepth_ * mods_[0].tick() ) );
+ delayLine_[1].setDelay( baseLength_ * 0.5 * ( 1.0 - modDepth_ * mods_[1].tick() ) );
+ lastFrame_[0] = effectMix_ * ( delayLine_[0].tick( input ) - input ) + input;
+ lastFrame_[1] = effectMix_ * ( delayLine_[1].tick( input ) - input ) + input;
+ return lastFrame_[channel];
+}
+
+inline StkFrames& Chorus :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() - 1 ) {
+ errorString_ << "Chorus::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels() - 1;
+ for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() - 1 ) {
+ errorString_ << "Chorus::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i= frames.channels() ) {
+ errorString_ << "Delay::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
#endif
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "Delay::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i= frames.channels() ) {
+ errorString_ << "DelayA::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "DelayA::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i= frames.channels() ) {
+ errorString_ << "DelayL::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "DelayL::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i soundOrder_;
@@ -60,4 +63,30 @@ class Drummer : public Instrmnt
int nSounding_;
};
+inline StkFloat Drummer :: tick( unsigned int )
+{
+ lastFrame_[0] = 0.0;
+ if ( nSounding_ == 0 ) return lastFrame_[0];
+
+ for ( int i=0; i= 0 ) {
+ if ( waves_[i].isFinished() ) {
+ // Re-order the list.
+ for ( int j=0; j soundOrder_[i] )
+ soundOrder_[j] -= 1;
+ }
+ soundOrder_[i] = -1;
+ nSounding_--;
+ }
+ else
+ lastFrame_[0] += filters_[i].tick( waves_[i].tick() );
+ }
+ }
+
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Echo.h b/include/Echo.h
index f9a6fff..2f57f45 100644
--- a/include/Echo.h
+++ b/include/Echo.h
@@ -1,19 +1,21 @@
+#ifndef STK_ECHO_H
+#define STK_ECHO_H
+
+#include "Effect.h"
+#include "Delay.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Echo
\brief STK echo effect class.
This class implements an echo effect.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_ECHO_H
-#define STK_ECHO_H
-
-#include "Effect.h"
-#include "Delay.h"
-
class Echo : public Effect
{
public:
@@ -23,9 +25,6 @@ class Echo : public Effect
*/
Echo( unsigned long maximumDelay = (unsigned long) Stk::sampleRate() );
- //! Class destructor.
- ~Echo();
-
//! Reset and clear all internal state.
void clear();
@@ -35,14 +34,87 @@ class Echo : public Effect
//! Set the delay line length in samples.
void setDelay( unsigned long delay );
- protected:
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
- StkFloat computeSample( StkFloat input );
+ //! Input one sample to the effect and return one output.
+ StkFloat tick( StkFloat input );
+
+ //! Take a channel of the StkFrames object as inputs to the effect and replace with corresponding outputs.
+ /*!
+ The StkFrames argument reference is returned. The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+ //! Take a channel of the \c iFrames object as inputs to the effect and write outputs to the \c oFrames object.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
+
+ protected:
Delay delayLine_;
unsigned long length_;
};
+inline StkFloat Echo :: tick( StkFloat input )
+{
+ lastFrame_[0] = effectMix_ * ( delayLine_.tick( input ) - input ) + input;
+ return lastFrame_[0];
+}
+
+inline StkFrames& Echo :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Echo::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "Echo::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i
+
+namespace stk {
+
/***************************************************/
/*! \class Effect
\brief STK abstract effects parent class.
- This class provides common functionality for
- STK effects subclasses.
+ This class provides common functionality for STK effects
+ subclasses. It is general enough to support both monophonic and
+ polyphonic input/output classes.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#include "Stk.h"
-
-#ifndef STK_EFFECT_H
-#define STK_EFFECT_H
-
class Effect : public Stk
{
public:
//! Class constructor.
- Effect();
+ Effect( void ) { lastFrame_.resize( 1, 1, 0.0 ); };
- //! Class destructor.
- virtual ~Effect();
+ //! Return the number of output channels for the class.
+ unsigned int channelsOut( void ) const { return lastFrame_.channels(); };
+
+ //! Return an StkFrames reference to the last output sample frame.
+ const StkFrames& lastFrame( void ) const { return lastFrame_; };
//! Reset and clear all internal state.
virtual void clear() = 0;
- //! Set the mixture of input and "effected" levels in the output (0.0 = input only, 1.0 = reverb only).
- void setEffectMix(StkFloat mix);
-
- //! Return the last output value.
- StkFloat lastOut() const;
-
- //! Return the last left output value.
- StkFloat lastOutLeft() const;
-
- //! Return the last right output value.
- StkFloat lastOutRight() const;
-
- //! Take one sample input and compute one sample of output.
- StkFloat tick( StkFloat input );
-
- //! Take a channel of the StkFrames object as inputs to the effect and replace with corresponding outputs.
- /*!
- The \c channel argument should be zero or greater (the first
- channel is specified by 0). An StkError will be thrown if the \c
- channel argument is equal to or greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+ //! Set the mixture of input and "effected" levels in the output (0.0 = input only, 1.0 = effect only).
+ void setEffectMix( StkFloat mix );
protected:
- // This abstract function must be implemented in all subclasses.
- // It is used to get around a C++ problem with overloaded virtual
- // functions.
- virtual StkFloat computeSample( StkFloat input ) = 0;
-
// Returns true if argument value is prime.
- bool isPrime( int number );
+ bool isPrime( unsigned int number );
- StkFloat lastOutput_[2];
+ StkFrames lastFrame_;
StkFloat effectMix_;
};
+inline void Effect :: setEffectMix( StkFloat mix )
+{
+ if ( mix < 0.0 ) {
+ errorString_ << "Effect::setEffectMix: mix parameter is less than zero ... setting to zero!";
+ handleError( StkError::WARNING );
+ effectMix_ = 0.0;
+ }
+ else if ( mix > 1.0 ) {
+ errorString_ << "Effect::setEffectMix: mix parameter is greater than 1.0 ... setting to one!";
+ handleError( StkError::WARNING );
+ effectMix_ = 1.0;
+ }
+ else
+ effectMix_ = mix;
+}
+
+inline bool Effect :: isPrime( unsigned int number )
+{
+ if ( number == 2 ) return true;
+ if ( number & 1 ) {
+ for ( int i=3; i<(int)sqrt((double)number)+1; i+=2 )
+ if ( (number % i) == 0 ) return false;
+ return true; // prime
+ }
+ else return false; // even
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Envelope.h b/include/Envelope.h
index 23c97d6..7530dd2 100644
--- a/include/Envelope.h
+++ b/include/Envelope.h
@@ -1,64 +1,76 @@
-/***************************************************/
-/*! \class Envelope
- \brief STK envelope base class.
-
- This class implements a simple envelope
- generator which is capable of ramping to
- a target value by a specified \e rate.
- It also responds to simple \e keyOn and
- \e keyOff messages, ramping to 1.0 on
- keyOn and to 0.0 on keyOff.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
#ifndef STK_ENVELOPE_H
#define STK_ENVELOPE_H
#include "Generator.h"
+namespace stk {
+
+/***************************************************/
+/*! \class Envelope
+ \brief STK linear line envelope class.
+
+ This class implements a simple linear line envelope generator
+ which is capable of ramping to an arbitrary target value by a
+ specified \e rate. It also responds to simple \e keyOn and \e
+ keyOff messages, ramping to 1.0 on keyOn and to 0.0 on keyOff.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
+*/
+/***************************************************/
+
class Envelope : public Generator
{
public:
//! Default constructor.
- Envelope(void);
-
- //! Copy constructor.
- Envelope( const Envelope& e );
+ Envelope( void );
//! Class destructor.
- virtual ~Envelope(void);
+ ~Envelope( void );
//! Assignment operator.
Envelope& operator= ( const Envelope& e );
//! Set target = 1.
- virtual void keyOn(void);
+ void keyOn( void ) { this->setTarget( 1.0 ); };
//! Set target = 0.
- virtual void keyOff(void);
+ void keyOff( void ) { this->setTarget( 0.0 ); };
//! Set the \e rate.
- void setRate(StkFloat rate);
+ void setRate( StkFloat rate );
//! Set the \e rate based on a time duration.
- void setTime(StkFloat time);
+ void setTime( StkFloat time );
//! Set the target value.
- virtual void setTarget(StkFloat target);
+ void setTarget( StkFloat target );
- //! Set current and target values to \e aValue.
- virtual void setValue(StkFloat value);
+ //! Set current and target values to \e value.
+ void setValue( StkFloat value );
//! Return the current envelope \e state (0 = at target, 1 otherwise).
- virtual int getState(void) const;
+ int getState( void ) const { return state_; };
+
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Compute and return one output sample.
+ StkFloat tick( void );
+
+ //! Fill a channel of the StkFrames object with computed outputs.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
- virtual StkFloat computeSample( void );
- virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
+ void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
StkFloat value_;
StkFloat target_;
@@ -66,4 +78,85 @@ class Envelope : public Generator
int state_;
};
+inline void Envelope :: setRate( StkFloat rate )
+{
+#if defined(_STK_DEBUG_)
+ if ( rate < 0.0 ) {
+ errorString_ << "Envelope::setRate: negative rates not allowed ... correcting!";
+ handleError( StkError::WARNING );
+ rate_ = -rate;
+ }
+ else
+#endif
+ rate_ = rate;
+}
+
+inline void Envelope :: setTime( StkFloat time )
+{
+#if defined(_STK_DEBUG_)
+ if ( time < 0.0 ) {
+ errorString_ << "Envelope::setTime: negative times not allowed ... correcting!";
+ handleError( StkError::WARNING );
+ rate_ = 1.0 / ( -time * Stk::sampleRate() );
+ }
+ else
+#endif
+ rate_ = 1.0 / ( time * Stk::sampleRate() );
+}
+
+inline void Envelope :: setTarget( StkFloat target )
+{
+ target_ = target;
+ if ( value_ != target_ ) state_ = 1;
+}
+
+inline void Envelope :: setValue( StkFloat value )
+{
+ state_ = 0;
+ target_ = value;
+ value_ = value;
+}
+
+inline StkFloat Envelope :: tick( void )
+{
+ if ( state_ ) {
+ if ( target_ > value_ ) {
+ value_ += rate_;
+ if ( value_ >= target_ ) {
+ value_ = target_;
+ state_ = 0;
+ }
+ }
+ else {
+ value_ -= rate_;
+ if ( value_ <= target_ ) {
+ value_ = target_;
+ state_ = 0;
+ }
+ }
+ lastFrame_[0] = value_;
+ }
+
+ return value_;
+}
+
+inline StkFrames& Envelope :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Envelope::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i adsr_;
- std::vector waves_;
+ std::vector waves_;
SineWave vibrato_;
TwoZero twozero_;
unsigned int nOperators_;
@@ -104,4 +107,6 @@ class FM : public Instrmnt
};
+} // stk namespace
+
#endif
diff --git a/include/FMVoices.h b/include/FMVoices.h
index ec8dff1..a25583a 100644
--- a/include/FMVoices.h
+++ b/include/FMVoices.h
@@ -1,3 +1,10 @@
+#ifndef STK_FMVOICES_H
+#define STK_FMVOICES_H
+
+#include "FM.h"
+
+namespace stk {
+
/***************************************************/
/*! \class FMVoices
\brief STK singing FM synthesis instrument.
@@ -26,15 +33,10 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_FMVOICES_H
-#define STK_FMVOICES_H
-
-#include "FM.h"
-
class FMVoices : public FM
{
public:
@@ -42,27 +44,55 @@ class FMVoices : public FM
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
- FMVoices();
+ FMVoices( void );
//! Class destructor.
- ~FMVoices();
+ ~FMVoices( void );
//! Set instrument parameters for a particular frequency.
- virtual void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- virtual void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
int currentVowel_;
StkFloat tilt_[3];
StkFloat mods_[3];
};
+inline StkFloat FMVoices :: tick( unsigned int )
+{
+ register StkFloat temp, temp2;
+
+ temp = gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
+ temp2 = vibrato_.tick() * modDepth_ * 0.1;
+
+ waves_[0]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[0]);
+ waves_[1]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[1]);
+ waves_[2]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[2]);
+ waves_[3]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[3]);
+
+ waves_[0]->addPhaseOffset(temp * mods_[0]);
+ waves_[1]->addPhaseOffset(temp * mods_[1]);
+ waves_[2]->addPhaseOffset(temp * mods_[2]);
+ waves_[3]->addPhaseOffset( twozero_.lastOut() );
+ twozero_.tick( temp );
+ temp = gains_[0] * tilt_[0] * adsr_[0]->tick() * waves_[0]->tick();
+ temp += gains_[1] * tilt_[1] * adsr_[1]->tick() * waves_[1]->tick();
+ temp += gains_[2] * tilt_[2] * adsr_[2]->tick() * waves_[2]->tick();
+
+ lastFrame_[0] = temp * 0.33;
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/FileLoop.h b/include/FileLoop.h
new file mode 100644
index 0000000..0050070
--- /dev/null
+++ b/include/FileLoop.h
@@ -0,0 +1,161 @@
+#ifndef STK_FILELOOP_H
+#define STK_FILELOOP_H
+
+#include "FileWvIn.h"
+
+namespace stk {
+
+/***************************************************/
+/*! \class FileLoop
+ \brief STK file looping / oscillator class.
+
+ This class provides audio file looping functionality. Any audio
+ file that can be loaded by FileRead can be looped using this
+ class.
+
+ FileLoop supports multi-channel data. It is important to
+ distinguish the tick() method that computes a single frame (and
+ returns only the specified sample of a multi-channel frame) from
+ the overloaded one that takes an StkFrames object for
+ multi-channel and/or multi-frame data.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
+*/
+/***************************************************/
+
+class FileLoop : protected FileWvIn
+{
+ public:
+ //! Default constructor.
+ FileLoop( unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 );
+
+ //! Class constructor that opens a specified file.
+ FileLoop( std::string fileName, bool raw = false, bool doNormalize = true,
+ unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 );
+
+ //! Class destructor.
+ ~FileLoop( void );
+
+ //! Open the specified file and load its data.
+ /*!
+ Data from a previously opened file will be overwritten by this
+ function. An StkError will be thrown if the file is not found,
+ its format is unknown, or a read error occurs. If the file data
+ is to be loaded incrementally from disk and normalization is
+ specified, a scaling will be applied with respect to fixed-point
+ limits. If the data format is floating-point, no scaling is
+ performed.
+ */
+ void openFile( std::string fileName, bool raw = false, bool doNormalize = true );
+
+ //! Close a file if one is open.
+ void closeFile( void ) { FileWvIn::closeFile(); };
+
+ //! Clear outputs and reset time (file) pointer to zero.
+ void reset( void ) { FileWvIn::reset(); };
+
+ //! Normalize data to a maximum of +-1.0.
+ /*!
+ This function has no effect when data is incrementally loaded
+ from disk.
+ */
+ void normalize( void ) { FileWvIn::normalize( 1.0 ); };
+
+ //! Normalize data to a maximum of \e +-peak.
+ /*!
+ This function has no effect when data is incrementally loaded
+ from disk.
+ */
+ void normalize( StkFloat peak ) { FileWvIn::normalize( peak ); };
+
+ //! Return the file size in sample frames.
+ unsigned long getSize( void ) const { return data_.frames(); };
+
+ //! Return the input file sample rate in Hz (not the data read rate).
+ /*!
+ WAV, SND, and AIF formatted files specify a sample rate in
+ their headers. STK RAW files have a sample rate of 22050 Hz
+ by definition. MAT-files are assumed to have a rate of 44100 Hz.
+ */
+ StkFloat getFileRate( void ) const { return data_.dataRate(); };
+
+ //! Set the data read rate in samples. The rate can be negative.
+ /*!
+ If the rate value is negative, the data is read in reverse order.
+ */
+ void setRate( StkFloat rate );
+
+ //! Set the data interpolation rate based on a looping frequency.
+ /*!
+ This function determines the interpolation rate based on the file
+ size and the current Stk::sampleRate. The \e frequency value
+ corresponds to file cycles per second. The frequency can be
+ negative, in which case the loop is read in reverse order.
+ */
+ void setFrequency( StkFloat frequency ) { this->setRate( file_.fileSize() * frequency / Stk::sampleRate() ); };
+
+ //! Increment the read pointer by \e time samples, modulo file size.
+ void addTime( StkFloat time );
+
+ //! Increment current read pointer by \e angle, relative to a looping frequency.
+ /*!
+ This function increments the read pointer based on the file
+ size and the current Stk::sampleRate. The \e anAngle value
+ is a multiple of file size.
+ */
+ void addPhase( StkFloat angle );
+
+ //! Add a phase offset to the current read pointer.
+ /*!
+ This function determines a time offset based on the file
+ size and the current Stk::sampleRate. The \e angle value
+ is a multiple of file size.
+ */
+ void addPhaseOffset( StkFloat angle );
+
+ //! Return the specified channel value of the last computed frame.
+ /*!
+ For multi-channel files, use the lastFrame() function to get
+ all values from the last computed frame. If no file data is
+ loaded, the returned value is 0.0. The \c channel argument must
+ be less than the number of channels in the file data (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.
+ */
+ StkFloat lastOut( unsigned int channel = 0 ) { return FileWvIn::lastOut( channel ); };
+
+ //! Compute a sample frame and return the specified \c channel value.
+ /*!
+ For multi-channel files, use the lastFrame() function to get
+ all values from the computed frame. If no file data is loaded,
+ the returned value is 0.0. The \c channel argument must be less
+ than the number of channels in the file data (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.
+ */
+ StkFloat tick( unsigned int channel = 0 );
+
+ //! Fill the StkFrames argument with computed frames and return the same reference.
+ /*!
+ The number of channels in the StkFrames argument should equal
+ the number of channels in the file data. However, this is only
+ checked if _STK_DEBUG_ is defined during compilation, in which
+ case an incompatibility will trigger an StkError exception. If no
+ file data is loaded, the function does nothing (a warning will be
+ issued if _STK_DEBUG_ is defined during compilation and
+ Stk::showWarnings() has been set to \e true).
+ */
+ StkFrames& tick( StkFrames& frames );
+
+ protected:
+
+ StkFrames firstFrame_;
+ StkFloat phaseOffset_;
+
+};
+
+} // stk namespace
+
+#endif
diff --git a/include/FileRead.h b/include/FileRead.h
index 7bd04d4..7bf8414 100644
--- a/include/FileRead.h
+++ b/include/FileRead.h
@@ -1,3 +1,10 @@
+#ifndef STK_FILEREAD_H
+#define STK_FILEREAD_H
+
+#include "Stk.h"
+
+namespace stk {
+
/***************************************************/
/*! \class FileRead
\brief STK audio file input class.
@@ -25,20 +32,15 @@
filling a matrix row. The sample rate for
MAT-files is assumed to be 44100 Hz.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_FILEREAD_H
-#define STK_FILEREAD_H
-
-#include "Stk.h"
-
class FileRead : public Stk
{
public:
//! Default constructor.
- FileRead();
+ FileRead( void );
//! Overloaded constructor that opens a file during instantiation.
/*!
@@ -51,7 +53,7 @@ public:
StkFormat format = STK_SINT16, StkFloat rate = 22050.0 );
//! Class destructor.
- ~FileRead();
+ ~FileRead( void );
//! Open the specified file and determine its formatting.
/*!
@@ -126,4 +128,6 @@ protected:
StkFloat fileRate_;
};
+} // stk namespace
+
#endif
diff --git a/include/FileWrite.h b/include/FileWrite.h
index c43db1b..663f852 100644
--- a/include/FileWrite.h
+++ b/include/FileWrite.h
@@ -1,3 +1,10 @@
+#ifndef STK_FILEWRITE_H
+#define STK_FILEWRITE_H
+
+#include "Stk.h"
+
+namespace stk {
+
/***************************************************/
/*! \class FileWrite
\brief STK audio file output class.
@@ -17,15 +24,10 @@
type, the data type will automatically be modified. Compressed
data types are not supported.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_FILEWRITE_H
-#define STK_FILEWRITE_H
-
-#include "Stk.h"
-
class FileWrite : public Stk
{
public:
@@ -39,7 +41,7 @@ class FileWrite : public Stk
static const FILE_TYPE FILE_MAT; /*!< Matlab MAT-file type. */
//! Default constructor.
- FileWrite();
+ FileWrite( void );
//! Overloaded constructor used to specify a file name, type, and data format with this object.
/*!
@@ -109,4 +111,6 @@ class FileWrite : public Stk
};
+} // stk namespace
+
#endif
diff --git a/include/FileWvIn.h b/include/FileWvIn.h
index ec54032..dc0caab 100644
--- a/include/FileWvIn.h
+++ b/include/FileWvIn.h
@@ -1,17 +1,26 @@
+#ifndef STK_FILEWVIN_H
+#define STK_FILEWVIN_H
+
+#include "WvIn.h"
+#include "FileRead.h"
+
+namespace stk {
+
/***************************************************/
/*! \class FileWvIn
\brief STK audio file input class.
This class inherits from WvIn. It provides a "tick-level"
interface to the FileRead class. It also provides variable-rate
- "playback" functionality. Audio file support is provided by the
- FileRead class. Linear interpolation is used for fractional "read
- rates".
+ playback functionality. Audio file support is provided by the
+ FileRead class. Linear interpolation is used for fractional read
+ rates.
- FileWvIn supports multi-channel data. It is important to distinguish
- the tick() methods, which return samples produced by averaging
- across sample frames, from the tickFrame() methods, which return
- references to multi-channel sample frames.
+ FileWvIn supports multi-channel data. It is important to
+ distinguish the tick() method that computes a single frame (and
+ returns only the specified sample of a multi-channel frame) from
+ the overloaded one that takes an StkFrames object for
+ multi-channel and/or multi-frame data.
FileWvIn will either load the entire content of an audio file into
local memory or incrementally read file data from disk in chunks.
@@ -21,22 +30,15 @@
chunks of \e chunkSize each (also in sample frames).
When the file end is reached, subsequent calls to the tick()
- functions return zero-valued data and isFinished() returns \e
- true.
+ functions return zeros and isFinished() returns \e true.
See the FileRead class for a description of the supported audio
file formats.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_FILEWVIN_H
-#define STK_FILEWVIN_H
-
-#include "WvIn.h"
-#include "FileRead.h"
-
class FileWvIn : public WvIn
{
public:
@@ -52,7 +54,7 @@ public:
unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 );
//! Class destructor.
- virtual ~FileWvIn();
+ ~FileWvIn( void );
//! Open the specified file and load its data.
/*!
@@ -64,30 +66,30 @@ public:
limits. If the data format is floating-point, no scaling is
performed.
*/
- void openFile( std::string fileName, bool raw = false, bool doNormalize = true );
+ virtual void openFile( std::string fileName, bool raw = false, bool doNormalize = true );
//! Close a file if one is open.
- void closeFile( void );
+ virtual void closeFile( void );
//! Clear outputs and reset time (file) pointer to zero.
- void reset( void );
+ virtual void reset( void );
//! Normalize data to a maximum of +-1.0.
/*!
This function has no effect when data is incrementally loaded
from disk.
*/
- void normalize( void );
+ virtual void normalize( void );
//! Normalize data to a maximum of \e +-peak.
/*!
This function has no effect when data is incrementally loaded
from disk.
*/
- void normalize( StkFloat peak );
+ virtual void normalize( StkFloat peak );
//! Return the file size in sample frames.
- unsigned long getSize( void ) const { return data_.frames(); };
+ virtual unsigned long getSize( void ) const { return data_.frames(); };
//! Return the input file sample rate in Hz (not the data read rate).
/*!
@@ -95,7 +97,7 @@ public:
their headers. STK RAW files have a sample rate of 22050 Hz
by definition. MAT-files are assumed to have a rate of 44100 Hz.
*/
- StkFloat getFileRate( void ) const { return data_.dataRate(); };
+ virtual StkFloat getFileRate( void ) const { return data_.dataRate(); };
//! Query whether reading is complete.
bool isFinished( void ) const { return finished_; };
@@ -104,7 +106,7 @@ public:
/*!
If the rate value is negative, the data is read in reverse order.
*/
- void setRate( StkFloat rate );
+ virtual void setRate( StkFloat rate );
//! Increment the read pointer by \e time samples.
/*!
@@ -121,12 +123,44 @@ public:
*/
void setInterpolate( bool doInterpolate ) { interpolate_ = doInterpolate; };
- StkFloat lastOut( void ) const;
+ //! Return the specified channel value of the last computed frame.
+ /*!
+ If no file is loaded, the returned value is 0.0. The \c
+ channel argument must be less than the number of output channels,
+ which can be determined with the channelsOut() function (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. \sa
+ lastFrame()
+ */
+ StkFloat lastOut( unsigned int channel = 0 );
+
+ //! Compute a sample frame and return the specified \c channel value.
+ /*!
+ For multi-channel files, use the lastFrame() function to get
+ all values from the computed frame. If no file data is loaded,
+ the returned value is 0.0. The \c channel argument must be less
+ than the number of channels in the file data (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.
+ */
+ virtual StkFloat tick( unsigned int channel = 0 );
+
+ //! Fill the StkFrames argument with computed frames and return the same reference.
+ /*!
+ The number of channels in the StkFrames argument must equal
+ the number of channels in the file data. However, this is only
+ checked if _STK_DEBUG_ is defined during compilation, in which
+ case an incompatibility will trigger an StkError exception. If no
+ file data is loaded, the function does nothing (a warning will be
+ issued if _STK_DEBUG_ is defined during compilation).
+ */
+ virtual StkFrames& tick( StkFrames& frames );
protected:
- virtual void computeFrame( void );
- virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
+ void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
FileRead file_;
bool finished_;
@@ -141,4 +175,19 @@ protected:
};
+inline StkFloat FileWvIn :: lastOut( unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= data_.channels() ) {
+ errorString_ << "FileWvIn::lastOut(): channel argument and soundfile data are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ if ( finished_ ) return 0.0;
+ return lastFrame_[channel];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/FileWvOut.h b/include/FileWvOut.h
index 3af786f..eed517f 100644
--- a/include/FileWvOut.h
+++ b/include/FileWvOut.h
@@ -1,3 +1,11 @@
+#ifndef STK_FILEWVOUT_H
+#define STK_FILEWVOUT_H
+
+#include "WvOut.h"
+#include "FileWrite.h"
+
+namespace stk {
+
/***************************************************/
/*! \class FileWvOut
\brief STK audio file output class.
@@ -7,9 +15,9 @@
FileWvOut writes samples to an audio file and supports
multi-channel data. It is important to distinguish the tick()
- methods, which output single samples to all channels in a sample
- frame, from the tickFrame() methods, which take a pointer or
- reference to multi-channel sample frame data.
+ method that outputs a single sample to all channels in a sample
+ frame from the overloaded one that takes a reference to an
+ StkFrames object for multi-channel and/or multi-frame data.
See the FileWrite class for a description of the supported audio
file formats.
@@ -17,16 +25,10 @@
Currently, FileWvOut is non-interpolating and the output rate is
always Stk::sampleRate().
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_FILEWVOUT_H
-#define STK_FILEWVOUT_H
-
-#include "WvOut.h"
-#include "FileWrite.h"
-
class FileWvOut : public WvOut
{
public:
@@ -69,12 +71,23 @@ class FileWvOut : public WvOut
*/
void closeFile( void );
+ //! Output a single sample to all channels in a sample frame.
+ /*!
+ An StkError is thrown if an output error occurs.
+ */
+ void tick( const StkFloat sample );
+
+ //! Output the StkFrames data.
+ /*!
+ An StkError will be thrown if an output error occurs. An
+ StkError will also be thrown if _STK_DEBUG_ is defined during
+ compilation and there is an incompatability between the number of
+ channels in the FileWvOut object and that in the StkFrames object.
+ */
+ void tick( const StkFrames& frames );
+
protected:
- void computeSample( const StkFloat sample );
-
- void computeFrames( const StkFrames& frames );
-
void incrementFrame( void );
FileWrite file_;
@@ -84,4 +97,6 @@ class FileWvOut : public WvOut
};
+} // stk namespace
+
#endif
diff --git a/include/Filter.h b/include/Filter.h
index 2ed9106..76403f0 100644
--- a/include/Filter.h
+++ b/include/Filter.h
@@ -1,122 +1,86 @@
-/***************************************************/
-/*! \class Filter
- \brief STK filter class.
-
- This class implements a generic structure that
- can be used to create a wide range of filters.
- It can function independently or be subclassed
- to provide more specific controls based on a
- particular filter type.
-
- In particular, this class implements the standard
- difference equation:
-
- a[0]*y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb] -
- a[1]*y[n-1] - ... - a[na]*y[n-na]
-
- If a[0] is not equal to 1, the filter coeffcients
- are normalized by a[0].
-
- The \e gain parameter is applied at the filter
- input and does not affect the coefficient values.
- The default gain value is 1.0. This structure
- results in one extra multiply per computed sample,
- but allows easy control of the overall filter gain.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
#ifndef STK_FILTER_H
#define STK_FILTER_H
#include "Stk.h"
#include
+namespace stk {
+
+/***************************************************/
+/*! \class Filter
+ \brief STK abstract filter class.
+
+ This class provides limited common functionality for STK digital
+ filter subclasses. It is general enough to support both
+ monophonic and polyphonic input/output classes.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
+*/
+/***************************************************/
+
class Filter : public Stk
{
public:
- //! Default constructor creates a zero-order pass-through "filter".
- Filter(void);
+ //! Class constructor.
+ Filter( void ) { gain_ = 1.0; channelsIn_ = 1; lastFrame_.resize( 1, 1, 0.0 ); };
- //! Overloaded constructor which takes filter coefficients.
- /*!
- An StkError can be thrown if either of the coefficient vector
- sizes is zero, or if the a[0] coefficient is equal to zero.
- */
- Filter( std::vector &bCoefficients, std::vector &aCoefficients );
+ //! Return the number of input channels for the class.
+ unsigned int channelsIn( void ) const { return channelsIn_; };
- //! Class destructor.
- virtual ~Filter(void);
+ //! Return the number of output channels for the class.
+ unsigned int channelsOut( void ) const { return lastFrame_.channels(); };
- //! Sets all internal states of the filter to zero.
- void clear(void);
-
- //! Set filter coefficients.
- /*!
- An StkError can be thrown if either of the coefficient vector
- sizes is zero, or if the a[0] coefficient is equal to zero. If
- a[0] is not equal to 1, the filter coeffcients are normalized by
- a[0]. The internal state of the filter is not cleared unless the
- \e clearState flag is \c true.
- */
- void setCoefficients( std::vector &bCoefficients, std::vector &aCoefficients, bool clearState = false );
-
- //! Set numerator coefficients.
- /*!
- An StkError can be thrown if coefficient vector is empty. Any
- previously set denominator coefficients are left unaffected. Note
- that the default constructor sets the single denominator
- coefficient a[0] to 1.0. The internal state of the filter is not
- cleared unless the \e clearState flag is \c true.
- */
- void setNumerator( std::vector &bCoefficients, bool clearState = false );
-
- //! Set denominator coefficients.
- /*!
- An StkError can be thrown if the coefficient vector is empty or
- if the a[0] coefficient is equal to zero. Previously set
- numerator coefficients are unaffected unless a[0] is not equal to
- 1, in which case all coeffcients are normalized by a[0]. Note
- that the default constructor sets the single numerator coefficient
- b[0] to 1.0. The internal state of the filter is not cleared
- unless the \e clearState flag is \c true.
- */
- void setDenominator( std::vector &aCoefficients, bool clearState = false );
+ //! Clears all internal states of the filter.
+ virtual void clear( void );
//! Set the filter gain.
/*!
The gain is applied at the filter input and does not affect the
coefficient values. The default gain value is 1.0.
*/
- virtual void setGain(StkFloat gain);
+ void setGain( StkFloat gain ) { gain_ = gain; };
//! Return the current filter gain.
- virtual StkFloat getGain(void) const;
+ StkFloat getGain( void ) const { return gain_; };
- //! Return the last computed output value.
- virtual StkFloat lastOut(void) const;
-
- //! Input one sample to the filter and return one output.
- virtual StkFloat tick( StkFloat input );
+ //! Return an StkFrames reference to the last output sample frame.
+ const StkFrames& lastFrame( void ) const { return lastFrame_; };
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
- The \c channel argument should be zero or greater (the first
- channel is specified by 0). An StkError will be thrown if the \c
- channel argument is equal to or greater than the number of
- channels in the StkFrames object.
+ The StkFrames argument reference is returned. The \c 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.
*/
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+ virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ) = 0;
protected:
+ unsigned int channelsIn_;
+ StkFrames lastFrame_;
+
StkFloat gain_;
std::vector b_;
std::vector a_;
- std::vector outputs_;
- std::vector inputs_;
+ StkFrames outputs_;
+ StkFrames inputs_;
};
+inline void Filter :: clear( void )
+{
+ unsigned int i;
+ for ( i=0; i &coefficients );
+
+ //! Class destructor.
+ ~Fir( void );
+
+ //! Set filter coefficients.
+ /*!
+ An StkError can be thrown if the coefficient vector size is
+ zero. The internal state of the filter is not cleared unless the
+ \e clearState flag is \c true.
+ */
+ void setCoefficients( std::vector &coefficients, bool clearState = false );
+
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Input one sample to the filter and return one output.
+ StkFloat tick( StkFloat input );
+
+ //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
+ /*!
+ The StkFrames argument reference is returned. The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+ //! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
+
+protected:
+
+};
+
+inline StkFloat Fir :: tick( StkFloat input )
+{
+ lastFrame_[0] = 0.0;
+ inputs_[0] = gain_ * input;
+
+ for ( unsigned int i=b_.size()-1; i>0; i-- ) {
+ lastFrame_[0] += b_[i] * inputs_[i];
+ inputs_[i] = inputs_[i-1];
+ }
+ lastFrame_[0] += b_[0] * inputs_[0];
+
+ return lastFrame_[0];
+}
+
+inline StkFrames& Fir :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Fir::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int i, hop = frames.channels();
+ for ( unsigned int j=0; j0; i-- ) {
+ *samples += b_[i] * inputs_[i];
+ inputs_[i] = inputs_[i-1];
+ }
+ *samples += b_[0] * inputs_[0];
+ }
+
+ lastFrame_[0] = *(samples-hop);
+ return frames;
+}
+
+inline StkFrames& Fir :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
+{
+#if defined(_STK_DEBUG_)
+ if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "Fir::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int i, iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int j=0; j0; i-- ) {
+ *oSamples += b_[i] * inputs_[i];
+ inputs_[i] = inputs_[i-1];
+ }
+ *oSamples += b_[0] * inputs_[0];
+ }
+
+ lastFrame_[0] = *(oSamples-oHop);
+ return iFrames;
+}
+
+} // stk namespace
+
+#endif
diff --git a/include/Flute.h b/include/Flute.h
index 9b95f9f..fb4d904 100644
--- a/include/Flute.h
+++ b/include/Flute.h
@@ -1,3 +1,17 @@
+#ifndef STK_FLUTE_H
+#define STK_FLUTE_H
+
+#include "Instrmnt.h"
+#include "JetTable.h"
+#include "DelayL.h"
+#include "OnePole.h"
+#include "PoleZero.h"
+#include "Noise.h"
+#include "ADSR.h"
+#include "SineWave.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Flute
\brief STK flute physical model class.
@@ -18,22 +32,10 @@
- Vibrato Gain = 1
- Breath Pressure = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_FLUTE_H
-#define STK_FLUTE_H
-
-#include "Instrmnt.h"
-#include "JetTable.h"
-#include "DelayL.h"
-#include "OnePole.h"
-#include "PoleZero.h"
-#include "Noise.h"
-#include "ADSR.h"
-#include "SineWave.h"
-
class Flute : public Instrmnt
{
public:
@@ -41,45 +43,46 @@ class Flute : public Instrmnt
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
- Flute(StkFloat lowestFrequency);
+ Flute( StkFloat lowestFrequency );
//! Class destructor.
- ~Flute();
+ ~Flute( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set instrument parameters for a particular frequency.
- void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Set the reflection coefficient for the jet delay (-1.0 - 1.0).
- void setJetReflection(StkFloat coefficient);
+ void setJetReflection( StkFloat coefficient );
//! Set the reflection coefficient for the air column delay (-1.0 - 1.0).
- void setEndReflection(StkFloat coefficient);
+ void setEndReflection( StkFloat coefficient );
//! Set the length of the jet delay in terms of a ratio of jet delay to air column delay lengths.
- void setJetDelay(StkFloat aRatio);
+ void setJetDelay( StkFloat aRatio );
//! Apply breath velocity to instrument with given amplitude and rate of increase.
- void startBlowing(StkFloat amplitude, StkFloat rate);
+ void startBlowing( StkFloat amplitude, StkFloat rate );
//! Decrease breath velocity with given rate of decrease.
- void stopBlowing(StkFloat rate);
+ void stopBlowing( StkFloat rate );
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
DelayL jetDelay_;
DelayL boreDelay_;
JetTable jetTable_;
@@ -100,4 +103,27 @@ class Flute : public Instrmnt
};
+inline StkFloat Flute :: tick( unsigned int )
+{
+ StkFloat pressureDiff;
+ StkFloat breathPressure;
+
+ // Calculate the breath pressure (envelope + noise + vibrato)
+ breathPressure = maxPressure_ * adsr_.tick();
+ breathPressure += breathPressure * ( noiseGain_ * noise_.tick() + vibratoGain_ * vibrato_.tick() );
+
+ StkFloat temp = filter_.tick( boreDelay_.lastOut() );
+ temp = dcBlock_.tick( temp ); // Block DC on reflection.
+
+ pressureDiff = breathPressure - (jetReflection_ * temp);
+ pressureDiff = jetDelay_.tick( pressureDiff );
+ pressureDiff = jetTable_.tick( pressureDiff ) + (endReflection_ * temp);
+ lastFrame_[0] = (StkFloat) 0.3 * boreDelay_.tick( pressureDiff );
+
+ lastFrame_[0] *= outputGain_;
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/FormSwep.h b/include/FormSwep.h
index f7daf56..905d3db 100644
--- a/include/FormSwep.h
+++ b/include/FormSwep.h
@@ -1,32 +1,35 @@
+#ifndef STK_FORMSWEP_H
+#define STK_FORMSWEP_H
+
+#include "Filter.h"
+
+namespace stk {
+
/***************************************************/
/*! \class FormSwep
\brief STK sweepable formant filter class.
- This public BiQuad filter subclass implements
- a formant (resonance) which can be "swept"
- over time from one frequency setting to another.
- It provides methods for controlling the sweep
- rate and target frequency.
+ This class implements a formant (resonance) which can be "swept"
+ over time from one frequency setting to another. It provides
+ methods for controlling the sweep rate and target frequency.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_FORMSWEP_H
-#define STK_FORMSWEP_H
-
-#include "BiQuad.h"
-
-class FormSwep : public BiQuad
+class FormSwep : public Filter
{
public:
//! Default constructor creates a second-order pass-through filter.
- FormSwep();
+ FormSwep( void );
//! Class destructor.
~FormSwep();
+ //! A function to enable/disable the automatic updating of class data when the STK sample rate changes.
+ void ignoreSampleRateChange( bool ignore = true ) { ignoreSampleRateChange_ = ignore; };
+
//! Sets the filter coefficients for a resonance at \e frequency (in Hz).
/*!
This method determines the filter coefficients corresponding to
@@ -39,13 +42,13 @@ class FormSwep : public BiQuad
the unit-circle (\e radius close to one), the narrower the
resulting resonance width.
*/
- void setResonance(StkFloat frequency, StkFloat radius);
+ void setResonance( StkFloat frequency, StkFloat radius );
//! Set both the current and target resonance parameters.
- void setStates(StkFloat frequency, StkFloat radius, StkFloat gain = 1.0);
+ void setStates( StkFloat frequency, StkFloat radius, StkFloat gain = 1.0 );
//! Set target resonance parameters.
- void setTargets(StkFloat frequency, StkFloat radius, StkFloat gain = 1.0);
+ void setTargets( StkFloat frequency, StkFloat radius, StkFloat gain = 1.0 );
//! Set the sweep rate (between 0.0 - 1.0).
/*!
@@ -56,7 +59,7 @@ class FormSwep : public BiQuad
target values. A sweep rate of 0.0 will produce no
change in resonance parameters.
*/
- void setSweepRate(StkFloat rate);
+ void setSweepRate( StkFloat rate );
//! Set the sweep rate in terms of a time value in seconds.
/*!
@@ -64,11 +67,39 @@ class FormSwep : public BiQuad
given time for the formant parameters to reach
their target values.
*/
- void setSweepTime(StkFloat time);
+ void setSweepTime( StkFloat time );
+
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Input one sample to the filter and return a reference to one output.
+ StkFloat tick( StkFloat input );
+
+ //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
+ /*!
+ The StkFrames argument reference is returned. The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+ //! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
- StkFloat computeSample( StkFloat input );
+ virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
bool dirty_;
StkFloat frequency_;
@@ -87,4 +118,71 @@ class FormSwep : public BiQuad
};
+inline StkFloat FormSwep :: tick( StkFloat input )
+{
+ if ( dirty_ ) {
+ sweepState_ += sweepRate_;
+ if ( sweepState_ >= 1.0 ) {
+ sweepState_ = 1.0;
+ dirty_ = false;
+ radius_ = targetRadius_;
+ frequency_ = targetFrequency_;
+ gain_ = targetGain_;
+ }
+ else {
+ radius_ = startRadius_ + (deltaRadius_ * sweepState_);
+ frequency_ = startFrequency_ + (deltaFrequency_ * sweepState_);
+ gain_ = startGain_ + (deltaGain_ * sweepState_);
+ }
+ this->setResonance( frequency_, radius_ );
+ }
+
+ inputs_[0] = gain_ * input;
+ lastFrame_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2];
+ lastFrame_[0] -= a_[2] * outputs_[2] + a_[1] * outputs_[1];
+ inputs_[2] = inputs_[1];
+ inputs_[1] = inputs_[0];
+ outputs_[2] = outputs_[1];
+ outputs_[1] = lastFrame_[0];
+
+ return lastFrame_[0];
+}
+
+inline StkFrames& FormSwep :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "FormSwep::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "FormSwep::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i= lastFrame_.channels() ) {
+ errorString_ << "Granulate::lastOut(): channel argument is invalid!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ return lastFrame_[channel];
+}
+
+inline StkFrames& Granulate :: tick( StkFrames& frames, unsigned int channel )
+{
+ unsigned int nChannels = lastFrame_.channels();
+#if defined(_STK_DEBUG_)
+ if ( channel > frames.channels() - nChannels ) {
+ errorString_ << "Granulate::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int j, hop = frames.channels() - nChannels;
+ for ( unsigned int i=0; isetFrequency(baseFrequency_ * (1.0 + temp) * ratios_[0]);
+ waves_[1]->setFrequency(baseFrequency_ * (1.0 + temp) * ratios_[1]);
+ waves_[2]->setFrequency(baseFrequency_ * (1.0 + temp) * ratios_[2]);
+ waves_[3]->setFrequency(baseFrequency_ * (1.0 + temp) * ratios_[3]);
+
+ temp = gains_[2] * adsr_[2]->tick() * waves_[2]->tick();
+ waves_[1]->addPhaseOffset( temp );
+
+ waves_[3]->addPhaseOffset( twozero_.lastOut() );
+ temp = (1.0 - (control2_ * 0.5)) * gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
+ twozero_.tick(temp);
+
+ temp += control2_ * 0.5 * gains_[1] * adsr_[1]->tick() * waves_[1]->tick();
+ temp = temp * control1_;
+
+ waves_[0]->addPhaseOffset( temp );
+ temp = gains_[0] * adsr_[0]->tick() * waves_[0]->tick();
+
+ lastFrame_[0] = temp * 0.5;
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Iir.h b/include/Iir.h
new file mode 100644
index 0000000..f349cc7
--- /dev/null
+++ b/include/Iir.h
@@ -0,0 +1,202 @@
+#ifndef STK_IIR_H
+#define STK_IIR_H
+
+#include "Filter.h"
+
+namespace stk {
+
+/***************************************************/
+/*! \class Iir
+ \brief STK general infinite impulse response filter class.
+
+ This class provides a generic digital filter structure that can be
+ used to implement IIR filters. For filters containing only
+ feedforward terms, the Fir class is slightly more efficient.
+
+ In particular, this class implements the standard difference
+ equation:
+
+ a[0]*y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb] -
+ a[1]*y[n-1] - ... - a[na]*y[n-na]
+
+ If a[0] is not equal to 1, the filter coeffcients are normalized
+ by a[0].
+
+ The \e gain parameter is applied at the filter input and does not
+ affect the coefficient values. The default gain value is 1.0.
+ This structure results in one extra multiply per computed sample,
+ but allows easy control of the overall filter gain.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
+*/
+/***************************************************/
+
+class Iir : public Filter
+{
+public:
+ //! Default constructor creates a zero-order pass-through "filter".
+ Iir( void );
+
+ //! Overloaded constructor which takes filter coefficients.
+ /*!
+ An StkError can be thrown if either of the coefficient vector
+ sizes is zero, or if the a[0] coefficient is equal to zero.
+ */
+ Iir( std::vector &bCoefficients, std::vector &aCoefficients );
+
+ //! Class destructor.
+ ~Iir( void );
+
+ //! Set filter coefficients.
+ /*!
+ An StkError can be thrown if either of the coefficient vector
+ sizes is zero, or if the a[0] coefficient is equal to zero. If
+ a[0] is not equal to 1, the filter coeffcients are normalized by
+ a[0]. The internal state of the filter is not cleared unless the
+ \e clearState flag is \c true.
+ */
+ void setCoefficients( std::vector &bCoefficients, std::vector &aCoefficients, bool clearState = false );
+
+ //! Set numerator coefficients.
+ /*!
+ An StkError can be thrown if coefficient vector is empty. Any
+ previously set denominator coefficients are left unaffected. Note
+ that the default constructor sets the single denominator
+ coefficient a[0] to 1.0. The internal state of the filter is not
+ cleared unless the \e clearState flag is \c true.
+ */
+ void setNumerator( std::vector &bCoefficients, bool clearState = false );
+
+ //! Set denominator coefficients.
+ /*!
+ An StkError can be thrown if the coefficient vector is empty or
+ if the a[0] coefficient is equal to zero. Previously set
+ numerator coefficients are unaffected unless a[0] is not equal to
+ 1, in which case all coeffcients are normalized by a[0]. Note
+ that the default constructor sets the single numerator coefficient
+ b[0] to 1.0. The internal state of the filter is not cleared
+ unless the \e clearState flag is \c true.
+ */
+ void setDenominator( std::vector &aCoefficients, bool clearState = false );
+
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Input one sample to the filter and return one output.
+ StkFloat tick( StkFloat input );
+
+ //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
+ /*!
+ The StkFrames argument reference is returned. The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+ //! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
+
+protected:
+
+};
+
+inline StkFloat Iir :: tick( StkFloat input )
+{
+ unsigned int i;
+
+ outputs_[0] = 0.0;
+ inputs_[0] = gain_ * input;
+ for ( i=b_.size()-1; i>0; i-- ) {
+ outputs_[0] += b_[i] * inputs_[i];
+ inputs_[i] = inputs_[i-1];
+ }
+ outputs_[0] += b_[0] * inputs_[0];
+
+ for ( i=a_.size()-1; i>0; i-- ) {
+ outputs_[0] += -a_[i] * outputs_[i];
+ outputs_[i] = outputs_[i-1];
+ }
+
+ lastFrame_[0] = outputs_[0];
+ return lastFrame_[0];
+}
+
+inline StkFrames& Iir :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Iir::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int i, hop = frames.channels();
+ for ( unsigned int j=0; j0; i-- ) {
+ outputs_[0] += b_[i] * inputs_[i];
+ inputs_[i] = inputs_[i-1];
+ }
+ outputs_[0] += b_[0] * inputs_[0];
+
+ for ( i=a_.size()-1; i>0; i-- ) {
+ outputs_[0] += -a_[i] * outputs_[i];
+ outputs_[i] = outputs_[i-1];
+ }
+
+ *samples = outputs_[0];
+ }
+
+ lastFrame_[0] = *(samples-hop);
+ return frames;
+}
+
+inline StkFrames& Iir :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
+{
+#if defined(_STK_DEBUG_)
+ if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "Iir::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int i, iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int j=0; j0; i-- ) {
+ outputs_[0] += b_[i] * inputs_[i];
+ inputs_[i] = inputs_[i-1];
+ }
+ outputs_[0] += b_[0] * inputs_[0];
+
+ for ( i=a_.size()-1; i>0; i-- ) {
+ outputs_[0] += -a_[i] * outputs_[i];
+ outputs_[i] = outputs_[i-1];
+ }
+
+ *oSamples = outputs_[0];
+ }
+
+ lastFrame_[0] = *(oSamples-oHop);
+ return iFrames;
+}
+
+} // stk namespace
+
+#endif
diff --git a/include/InetWvIn.h b/include/InetWvIn.h
index c2aee83..71c10c3 100644
--- a/include/InetWvIn.h
+++ b/include/InetWvIn.h
@@ -1,3 +1,14 @@
+#ifndef STK_INETWVIN_H
+#define STK_INETWVIN_H
+
+#include "WvIn.h"
+#include "TcpServer.h"
+#include "UdpSocket.h"
+#include "Thread.h"
+#include "Mutex.h"
+
+namespace stk {
+
/***************************************************/
/*! \class InetWvIn
\brief STK internet streaming input class.
@@ -8,10 +19,10 @@
supported.
InetWvIn supports multi-channel data. It is important to
- distinguish the tick() methods, which return samples produced by
- averaging across sample frames, from the tickFrame() methods,
- which return references or pointers to multi-channel sample
- frames.
+ distinguish the tick() method that computes a single frame (and
+ returns only the specified sample of a multi-channel frame) from
+ the overloaded one that takes an StkFrames object for
+ multi-channel and/or multi-frame data.
This class implements a socket server. When using the TCP
protocol, the server "listens" for a single remote connection
@@ -20,19 +31,10 @@
data type for the incoming stream is signed 16-bit integers,
though any of the defined StkFormats are permissible.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_INETWVIN_H
-#define STK_INETWVIN_H
-
-#include "WvIn.h"
-#include "TcpServer.h"
-#include "UdpSocket.h"
-#include "Thread.h"
-#include "Mutex.h"
-
typedef struct {
bool finished;
void *object;
@@ -69,9 +71,46 @@ public:
*/
bool isConnected( void );
+ //! Return the specified channel value of the last computed frame.
+ /*!
+ For multi-channel files, use the lastFrame() function to get
+ all values from the last computed frame. If no connection exists,
+ the returned value is 0.0. The \c channel argument must be less
+ than the number of channels in the data stream (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.
+ */
+ StkFloat lastOut( unsigned int channel = 0 );
+
+ //! Compute a sample frame and return the specified \c channel value.
+ /*!
+ For multi-channel files, use the lastFrame() function to get
+ all values from the computed frame. If no connection exists, the
+ returned value is 0.0 (and a warning will be issued if _STK_DEBUG_
+ is defined during compilation). The \c channel argument must be
+ less than the number of channels in the data stream (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.
+ */
+ StkFloat tick( unsigned int channel = 0 );
+
+ //! Fill the StkFrames argument with computed frames and return the same reference.
+ /*!
+ The number of channels in the StkFrames argument must equal the
+ number of channels specified in the listen() function. However,
+ this is only checked if _STK_DEBUG_ is defined during compilation,
+ in which case an incompatibility will trigger an StkError
+ exception. If no connection exists, the function does
+ nothing (a warning will be issued if _STK_DEBUG_ is defined during
+ compilation).
+ */
+ StkFrames& tick( StkFrames& frames );
+
// Called by the thread routine to receive data via the socket connection
// and fill the socket buffer. This is not intended for general use but
- // had to be made public for access from the thread.
+ // must be public for access from the thread.
void receive( void );
protected:
@@ -79,8 +118,6 @@ protected:
// Read buffered socket data into the data buffer ... will block if none available.
int readData( void );
- void computeFrame( void );
-
Socket *soket_;
Thread thread_;
Mutex mutex_;
@@ -100,4 +137,21 @@ protected:
};
+inline StkFloat InetWvIn :: lastOut( unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= data_.channels() ) {
+ errorString_ << "InetWvIn::lastOut(): channel argument and data stream are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ // If no connection and we've output all samples in the queue, return.
+ if ( !connected_ && bytesFilled_ == 0 && bufferCounter_ == 0 ) return 0.0;
+
+ return lastFrame_[channel];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/InetWvOut.h b/include/InetWvOut.h
index 96c273e..fe4b996 100644
--- a/include/InetWvOut.h
+++ b/include/InetWvOut.h
@@ -1,3 +1,11 @@
+#ifndef STK_INETWVOUT_H
+#define STK_INETWVOUT_H
+
+#include "WvOut.h"
+#include "Socket.h"
+
+namespace stk {
+
/***************************************************/
/*! \class InetWvOut
\brief STK internet streaming output class.
@@ -7,25 +15,20 @@
order, if necessary, before being transmitted.
InetWvOut supports multi-channel data. It is important to
- distinguish the tick() methods, which output single samples to all
- channels in a sample frame, from the tickFrame() method, which
- takes a reference to multi-channel sample frame data.
+ distinguish the tick() method that outputs a single sample to all
+ channels in a sample frame from the overloaded one that takes a
+ reference to an StkFrames object for multi-channel and/or
+ multi-frame data.
This class connects to a socket server, the port and IP address of
which must be specified as constructor arguments. The default
data type is signed 16-bit integers but any of the defined
StkFormats are permissible.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_INETWVOUT_H
-#define STK_INETWVOUT_H
-
-#include "WvOut.h"
-#include "Socket.h"
-
class InetWvOut : public WvOut
{
public:
@@ -51,14 +54,30 @@ class InetWvOut : public WvOut
std::string hostname = "localhost", unsigned int nChannels = 1, Stk::StkFormat format = STK_SINT16 );
//! If a connection is open, write out remaining samples in the queue and then disconnect.
- void disconnect(void);
+ void disconnect( void );
+
+ //! Output a single sample to all channels in a sample frame.
+ /*!
+ An StkError is thrown if an output error occurs. If a socket
+ connection does not exist, the function does nothing (a warning
+ will be issued if _STK_DEBUG_ is defined during compilation).
+ */
+ void tick( const StkFloat sample );
+
+ //! Output the StkFrames data.
+ /*!
+ An StkError will be thrown if an output error occurs. An
+ StkError will also be thrown if _STK_DEBUG_ is defined during
+ compilation and there is an incompatability between the number of
+ channels in the FileWvOut object and that in the StkFrames object.
+ If a socket connection does not exist, the function does nothing
+ (a warning will be issued if _STK_DEBUG_ is defined during
+ compilation).
+ */
+ void tick( const StkFrames& frames );
protected:
- void computeSample( const StkFloat sample );
-
- void computeFrames( const StkFrames& frames );
-
void incrementFrame( void );
// Write a buffer of length frames via the socket connection.
@@ -74,4 +93,6 @@ class InetWvOut : public WvOut
Stk::StkFormat dataType_;
};
+} // stk namespace
+
#endif
diff --git a/include/Instrmnt.h b/include/Instrmnt.h
index 85b2c7e..ecec1ca 100644
--- a/include/Instrmnt.h
+++ b/include/Instrmnt.h
@@ -1,70 +1,129 @@
-/***************************************************/
-/*! \class Instrmnt
- \brief STK instrument abstract base class.
-
- This class provides a common interface for
- all STK instruments.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
#ifndef STK_INSTRMNT_H
#define STK_INSTRMNT_H
#include "Stk.h"
+namespace stk {
+
+/***************************************************/
+/*! \class Instrmnt
+ \brief STK instrument abstract base class.
+
+ This class provides a common interface for
+ all STK instruments.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
+*/
+/***************************************************/
+
class Instrmnt : public Stk
{
public:
- //! Default constructor.
- Instrmnt();
-
- //! Class destructor.
- virtual ~Instrmnt();
+ //! Class constructor.
+ Instrmnt( void ) { lastFrame_.resize( 1, 1, 0.0 ); };
//! Start a note with the given frequency and amplitude.
- virtual void noteOn(StkFloat frequency, StkFloat amplitude) = 0;
+ virtual void noteOn( StkFloat frequency, StkFloat amplitude ) = 0;
//! Stop a note with the given amplitude (speed of decay).
- virtual void noteOff(StkFloat amplitude) = 0;
+ virtual void noteOff( StkFloat amplitude ) = 0;
//! Set instrument parameters for a particular frequency.
- virtual void setFrequency(StkFloat frequency);
-
- //! Return the last output value.
- StkFloat lastOut() const;
-
- //! Return the last left output value.
- StkFloat lastOutLeft() const;
-
- //! Return the last right output value.
- StkFloat lastOutRight() const;
-
- //! Compute one sample and output.
- StkFloat tick( void );
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be zero or greater (the first
- channel is specified by 0). An StkError will be thrown if the \c
- channel argument is equal to or greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+ virtual void setFrequency( StkFloat frequency );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
virtual void controlChange(int number, StkFloat value);
+ //! Return the number of output channels for the class.
+ unsigned int channelsOut( void ) const { return lastFrame_.channels(); };
+
+ //! Return an StkFrames reference to the last output sample frame.
+ const StkFrames& lastFrame( void ) const { return lastFrame_; };
+
+ //! Return the specified channel value of the last computed frame.
+ /*!
+ The \c channel argument must be less than the number of output
+ channels, which can be determined with the channelsOut() function
+ (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. \sa lastFrame()
+ */
+ StkFloat lastOut( unsigned int channel = 0 );
+
+ //! Compute one sample frame and return the specified \c channel value.
+ /*!
+ For monophonic instruments, the \c channel argument is ignored.
+ */
+ virtual StkFloat tick( unsigned int channel = 0 ) = 0;
+
+ //! Fill the StkFrames object with computed sample frames, starting at the specified channel.
+ /*!
+ The \c channel argument plus the number of output channels 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
protected:
- // This abstract function must be implemented in all subclasses.
- // It is used to get around a C++ problem with overloaded virtual
- // functions.
- virtual StkFloat computeSample( void ) = 0;
-
- StkFloat lastOutput_;
+ StkFrames lastFrame_;
};
+inline void Instrmnt :: setFrequency(StkFloat frequency)
+{
+ errorString_ << "Instrmnt::setFrequency: virtual setFrequency function call!";
+ handleError( StkError::WARNING );
+}
+
+inline StkFloat Instrmnt :: lastOut( unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= lastFrame_.channels() ) {
+ errorString_ << "Instrmnt::lastOut(): channel argument is invalid!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ return lastFrame_[channel];
+}
+
+inline StkFrames& Instrmnt :: tick( StkFrames& frames, unsigned int channel )
+{
+ unsigned int nChannels = lastFrame_.channels();
+#if defined(_STK_DEBUG_)
+ if ( channel > frames.channels() - nChannels ) {
+ errorString_ << "Instrmnt::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int j, hop = frames.channels() - nChannels;
+ if ( nChannels == 1 ) {
+ for ( unsigned int i=0; i 1 ) {
+ errorString_ << "JCRev::lastOut(): channel argument must be less than 2!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ return lastFrame_[channel];
+}
+
+inline StkFloat JCRev :: tick( StkFloat input, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel > 1 ) {
+ errorString_ << "JCRev::tick(): channel argument must be less than 2!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat temp, temp0, temp1, temp2, temp3, temp4, temp5, temp6;
+ StkFloat filtout;
+
+ temp = allpassDelays_[0].lastOut();
+ temp0 = allpassCoefficient_ * temp;
+ temp0 += input;
+ allpassDelays_[0].tick(temp0);
+ temp0 = -(allpassCoefficient_ * temp0) + temp;
+
+ temp = allpassDelays_[1].lastOut();
+ temp1 = allpassCoefficient_ * temp;
+ temp1 += temp0;
+ allpassDelays_[1].tick(temp1);
+ temp1 = -(allpassCoefficient_ * temp1) + temp;
+
+ temp = allpassDelays_[2].lastOut();
+ temp2 = allpassCoefficient_ * temp;
+ temp2 += temp1;
+ allpassDelays_[2].tick(temp2);
+ temp2 = -(allpassCoefficient_ * temp2) + temp;
+
+ temp3 = temp2 + (combCoefficient_[0] * combDelays_[0].lastOut());
+ temp4 = temp2 + (combCoefficient_[1] * combDelays_[1].lastOut());
+ temp5 = temp2 + (combCoefficient_[2] * combDelays_[2].lastOut());
+ temp6 = temp2 + (combCoefficient_[3] * combDelays_[3].lastOut());
+
+ combDelays_[0].tick(temp3);
+ combDelays_[1].tick(temp4);
+ combDelays_[2].tick(temp5);
+ combDelays_[3].tick(temp6);
+
+ filtout = temp3 + temp4 + temp5 + temp6;
+
+ lastFrame_[0] = effectMix_ * (outLeftDelay_.tick(filtout));
+ lastFrame_[1] = effectMix_ * (outRightDelay_.tick(filtout));
+ temp = (1.0 - effectMix_) * input;
+ lastFrame_[0] += temp;
+ lastFrame_[1] += temp;
+
+ return lastFrame_[channel];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/JetTable.h b/include/JetTable.h
index 2a3f298..8059595 100644
--- a/include/JetTable.h
+++ b/include/JetTable.h
@@ -1,3 +1,10 @@
+#ifndef STK_JETTABL_H
+#define STK_JETTABL_H
+
+#include "Function.h"
+
+namespace stk {
+
/***************************************************/
/*! \class JetTable
\brief STK jet table class.
@@ -9,28 +16,97 @@
Consult Fletcher and Rossing, Karjalainen,
Cook, and others for more information.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_JETTABL_H
-#define STK_JETTABL_H
-
-#include "Function.h"
-
class JetTable : public Function
{
public:
- //! Default constructor.
- JetTable();
- //! Class destructor.
- ~JetTable();
+ //! Take one sample input and map to one sample of output.
+ StkFloat tick( StkFloat input );
-protected:
+ //! Take a channel of the StkFrames object as inputs to the table and replace with corresponding outputs.
+ /*!
+ The StkFrames argument reference is returned. The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
- StkFloat computeSample( StkFloat input );
+ //! Take a channel of the \c iFrames object as inputs to the table and write outputs to the \c oFrames object.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
};
+inline StkFloat JetTable :: tick( StkFloat input )
+{
+ // Perform "table lookup" using a polynomial
+ // calculation (x^3 - x), which approximates
+ // the jet sigmoid behavior.
+ lastFrame_[0] = input * (input * input - 1.0);
+
+ // Saturate at +/- 1.0.
+ if ( lastFrame_[0] > 1.0 ) lastFrame_[0] = 1.0;
+ if ( lastFrame_[0] < -1.0 ) lastFrame_[0] = -1.0;
+ return lastFrame_[0];
+}
+
+inline StkFrames& JetTable :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "JetTable::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i 1.0) *samples = 1.0;
+ if ( *samples < -1.0) *samples = -1.0;
+ }
+
+ lastFrame_[0] = *(samples-hop);
+ return frames;
+}
+
+inline StkFrames& JetTable :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
+{
+#if defined(_STK_DEBUG_)
+ if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "JetTable::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i 1.0) *oSamples = 1.0;
+ if ( *oSamples < -1.0) *oSamples = -1.0;
+ }
+
+ lastFrame_[0] = *(oSamples-oHop);
+ return iFrames;
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Mandolin.h b/include/Mandolin.h
index dee9637..9ceabe4 100644
--- a/include/Mandolin.h
+++ b/include/Mandolin.h
@@ -1,3 +1,11 @@
+#ifndef STK_MANDOLIN_H
+#define STK_MANDOLIN_H
+
+#include "PluckTwo.h"
+#include "FileWvIn.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Mandolin
\brief STK mandolin instrument model class.
@@ -23,48 +31,75 @@
- String Detuning = 1
- Microphone Position = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_MANDOLIN_H
-#define STK_MANDOLIN_H
-
-#include "PluckTwo.h"
-#include "FileWvIn.h"
-
class Mandolin : public PluckTwo
{
public:
//! Class constructor, taking the lowest desired playing frequency.
- Mandolin(StkFloat lowestFrequency);
+ Mandolin( StkFloat lowestFrequency );
//! Class destructor.
- ~Mandolin();
+ ~Mandolin( void );
//! Pluck the strings with the given amplitude (0.0 - 1.0) using the current frequency.
- void pluck(StkFloat amplitude);
+ void pluck( StkFloat amplitude );
//! Pluck the strings with the given amplitude (0.0 - 1.0) and position (0.0 - 1.0).
- void pluck(StkFloat amplitude,StkFloat position);
+ void pluck( StkFloat amplitude,StkFloat position );
//! Start a note with the given frequency and amplitude (0.0 - 1.0).
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Set the body size (a value of 1.0 produces the "default" size).
- void setBodySize(StkFloat size);
+ void setBodySize( StkFloat size );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
FileWvIn *soundfile_[12];
int mic_;
long dampTime_;
bool waveDone_;
};
+inline StkFloat Mandolin :: tick( unsigned int )
+{
+ StkFloat temp = 0.0;
+ if ( !waveDone_ ) {
+ // Scale the pluck excitation with comb
+ // filtering for the duration of the file.
+ temp = soundfile_[mic_]->tick() * pluckAmplitude_;
+ temp = temp - combDelay_.tick(temp);
+ waveDone_ = soundfile_[mic_]->isFinished();
+ }
+
+ // Damping hack to help avoid overflow on re-plucking.
+ if ( dampTime_ >=0 ) {
+ dampTime_ -= 1;
+ // Calculate 1st delay filtered reflection plus pluck excitation.
+ lastFrame_[0] = delayLine_.tick( filter_.tick( temp + (delayLine_.lastOut() * 0.7) ) );
+ // Calculate 2nd delay just like the 1st.
+ lastFrame_[0] += delayLine2_.tick( filter2_.tick( temp + (delayLine2_.lastOut() * 0.7) ) );
+ }
+ else { // No damping hack after 1 period.
+ // Calculate 1st delay filtered reflection plus pluck excitation.
+ lastFrame_[0] = delayLine_.tick( filter_.tick( temp + (delayLine_.lastOut() * loopGain_) ) );
+ // Calculate 2nd delay just like the 1st.
+ lastFrame_[0] += delayLine2_.tick( filter2_.tick( temp + (delayLine2_.lastOut() * loopGain_) ) );
+ }
+
+ lastFrame_[0] *= 0.3;
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Mesh2D.h b/include/Mesh2D.h
index e580367..91b83e4 100644
--- a/include/Mesh2D.h
+++ b/include/Mesh2D.h
@@ -1,3 +1,11 @@
+#ifndef STK_MESH2D_H
+#define STK_MESH2D_H
+
+#include "Instrmnt.h"
+#include "OnePole.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Mesh2D
\brief Two-dimensional rectilinear waveguide mesh class.
@@ -24,12 +32,6 @@
*/
/***************************************************/
-#ifndef STK_MESH2D_H
-#define STK_MESH2D_H
-
-#include "Instrmnt.h"
-#include "OnePole.h"
-
const short NXMAX = 12;
const short NYMAX = 12;
@@ -37,45 +39,46 @@ class Mesh2D : public Instrmnt
{
public:
//! Class constructor, taking the x and y dimensions in samples.
- Mesh2D(short nX, short nY);
+ Mesh2D( short nX, short nY );
//! Class destructor.
- ~Mesh2D();
+ ~Mesh2D( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set the x dimension size in samples.
- void setNX(short lenX);
+ void setNX( short lenX );
//! Set the y dimension size in samples.
- void setNY(short lenY);
+ void setNY( short lenY );
//! Set the x, y input position on a 0.0 - 1.0 scale.
- void setInputPosition(StkFloat xFactor, StkFloat yFactor);
+ void setInputPosition( StkFloat xFactor, StkFloat yFactor );
//! Set the loss filters gains (0.0 - 1.0).
- void setDecay(StkFloat decayFactor);
+ void setDecay( StkFloat decayFactor );
//! Impulse the mesh with the given amplitude (frequency ignored).
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay) ... currently ignored.
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
//! Calculate and return the signal energy stored in the mesh.
- StkFloat energy();
+ StkFloat energy( void );
//! Input a sample to the mesh and compute one output sample.
StkFloat inputTick( StkFloat input );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
StkFloat tick0();
StkFloat tick1();
void clearMesh();
@@ -99,4 +102,6 @@ class Mesh2D : public Instrmnt
int counter_; // time in samples
};
+} // stk namespace
+
#endif
diff --git a/include/Messager.h b/include/Messager.h
index 4607c8a..1a16db8 100644
--- a/include/Messager.h
+++ b/include/Messager.h
@@ -1,3 +1,21 @@
+#ifndef STK_MESSAGER_H
+#define STK_MESSAGER_H
+
+#include "Stk.h"
+#include "Skini.h"
+#include
+
+#if defined(__STK_REALTIME__)
+
+#include "Mutex.h"
+#include "Thread.h"
+#include "TcpServer.h"
+#include "RtMidi.h"
+
+#endif // __STK_REALTIME__
+
+namespace stk {
+
/***************************************************/
/*! \class Messager
\brief STK input control message parser.
@@ -28,32 +46,12 @@
This class is primarily for use in STK example programs but it is
generic enough to work in many other contexts.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_MESSAGER_H
-#define STK_MESSAGER_H
-
-#include "Stk.h"
-#include "Skini.h"
-#include
-
const int DEFAULT_QUEUE_LIMIT = 200;
-#if defined(__STK_REALTIME__)
-
-#include "Mutex.h"
-#include "Thread.h"
-#include "TcpServer.h"
-#include "RtMidi.h"
-
-extern "C" THREAD_RETURN THREAD_TYPE stdinHandler(void * ptr);
-
-extern "C" THREAD_RETURN THREAD_TYPE socketHandler(void * ptr);
-
-#endif // __STK_REALTIME__
-
class Messager : public Stk
{
public:
@@ -163,4 +161,6 @@ class Messager : public Stk
};
+} // stk namespace
+
#endif
diff --git a/include/MidiFileIn.h b/include/MidiFileIn.h
index b687b65..218bf2a 100644
--- a/include/MidiFileIn.h
+++ b/include/MidiFileIn.h
@@ -1,3 +1,14 @@
+#ifndef STK_MIDIFILEIN_H
+#define STK_MIDIFILEIN_H
+
+#include "Stk.h"
+#include
+#include
+#include
+#include
+
+namespace stk {
+
/**********************************************************************/
/*! \class MidiFileIn
\brief A standard MIDI file reading/parsing class.
@@ -11,19 +22,10 @@
Tempo changes are internally tracked by the class and reflected in
the values returned by the function getTickSeconds().
- by Gary P. Scavone, 2003.
+ by Gary P. Scavone, 2003 - 2009.
*/
/**********************************************************************/
-#ifndef STK_MIDIFILEIN_H
-#define STK_MIDIFILEIN_H
-
-#include "Stk.h"
-#include
-#include
-#include
-#include
-
class MidiFileIn : public Stk
{
public:
@@ -128,4 +130,6 @@ class MidiFileIn : public Stk
std::vector trackTempoIndex_;
};
+} // stk namespace
+
#endif
diff --git a/include/Modal.h b/include/Modal.h
index 576d931..77ead48 100644
--- a/include/Modal.h
+++ b/include/Modal.h
@@ -1,26 +1,28 @@
+#ifndef STK_MODAL_H
+#define STK_MODAL_H
+
+#include "Instrmnt.h"
+#include "Envelope.h"
+#include "FileLoop.h"
+#include "SineWave.h"
+#include "BiQuad.h"
+#include "OnePole.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Modal
- \brief STK resonance model instrument.
+ \brief STK resonance model abstract base class.
This class contains an excitation wavetable,
an envelope, an oscillator, and N resonances
(non-sweeping BiQuad filters), where N is set
during instantiation.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_MODAL_H
-#define STK_MODAL_H
-
-#include "Instrmnt.h"
-#include "Envelope.h"
-#include "WaveLoop.h"
-#include "SineWave.h"
-#include "BiQuad.h"
-#include "OnePole.h"
-
class Modal : public Instrmnt
{
public:
@@ -31,45 +33,46 @@ public:
Modal( unsigned int modes = 4 );
//! Class destructor.
- virtual ~Modal();
+ virtual ~Modal( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set instrument parameters for a particular frequency.
- virtual void setFrequency(StkFloat frequency);
+ virtual void setFrequency( StkFloat frequency );
//! Set the ratio and radius for a specified mode filter.
- void setRatioAndRadius(unsigned int modeIndex, StkFloat ratio, StkFloat radius);
+ void setRatioAndRadius( unsigned int modeIndex, StkFloat ratio, StkFloat radius );
//! Set the master gain.
- void setMasterGain(StkFloat aGain);
+ void setMasterGain( StkFloat aGain ) { masterGain_ = aGain; };
//! Set the direct gain.
- void setDirectGain(StkFloat aGain);
+ void setDirectGain( StkFloat aGain ) { directGain_ = aGain; };
//! Set the gain for a specified mode filter.
- void setModeGain(unsigned int modeIndex, StkFloat gain);
+ void setModeGain( unsigned int modeIndex, StkFloat gain );
//! Initiate a strike with the given amplitude (0.0 - 1.0).
- virtual void strike(StkFloat amplitude);
+ virtual void strike( StkFloat amplitude );
//! Damp modes with a given decay factor (0.0 - 1.0).
- void damp(StkFloat amplitude);
+ void damp( StkFloat amplitude );
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- virtual void controlChange(int number, StkFloat value) = 0;
+ virtual void controlChange( int number, StkFloat value ) = 0;
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
Envelope envelope_;
FileWvIn *wave_;
BiQuad **filters_;
@@ -88,4 +91,27 @@ protected:
StkFloat baseFrequency_;
};
+inline StkFloat Modal :: tick( unsigned int )
+{
+ StkFloat temp = masterGain_ * onepole_.tick( wave_->tick() * envelope_.tick() );
+
+ StkFloat temp2 = 0.0;
+ for ( unsigned int i=0; itick(temp);
+
+ temp2 -= temp2 * directGain_;
+ temp2 += directGain_ * temp;
+
+ if ( vibratoGain_ != 0.0 ) {
+ // Calculate AM and apply to master out
+ temp = 1.0 + ( vibrato_.tick() * vibratoGain_ );
+ temp2 = temp * temp2;
+ }
+
+ lastFrame_[0] = temp2;
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/ModalBar.h b/include/ModalBar.h
index aca13b8..7c9dd24 100644
--- a/include/ModalBar.h
+++ b/include/ModalBar.h
@@ -1,3 +1,10 @@
+#ifndef STK_MODALBAR_H
+#define STK_MODALBAR_H
+
+#include "Modal.h"
+
+namespace stk {
+
/***************************************************/
/*! \class ModalBar
\brief STK resonant bar instrument class.
@@ -24,38 +31,35 @@
- Two Fixed = 7
- Clump = 8
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_MODALBAR_H
-#define STK_MODALBAR_H
-
-#include "Modal.h"
-
class ModalBar : public Modal
{
public:
//! Class constructor.
- ModalBar();
+ ModalBar( void );
//! Class destructor.
- ~ModalBar();
+ ~ModalBar( void );
//! Set stick hardness (0.0 - 1.0).
- void setStickHardness(StkFloat hardness);
+ void setStickHardness( StkFloat hardness );
//! Set stick position (0.0 - 1.0).
- void setStrikePosition(StkFloat position);
+ void setStrikePosition( StkFloat position );
//! Select a bar preset (currently modulo 9).
- void setPreset(int preset);
+ void setPreset( int preset );
//! Set the modulation (vibrato) depth.
- void setModulationDepth(StkFloat mDepth);
+ void setModulationDepth( StkFloat mDepth );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
};
+} // stk namespace
+
#endif
diff --git a/include/Modulate.h b/include/Modulate.h
index 6573964..7429985 100644
--- a/include/Modulate.h
+++ b/include/Modulate.h
@@ -1,3 +1,13 @@
+#ifndef STK_MODULATE_H
+#define STK_MODULATE_H
+
+#include "Generator.h"
+#include "SineWave.h"
+#include "Noise.h"
+#include "OnePole.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Modulate
\brief STK periodic/random modulator.
@@ -6,18 +16,10 @@
modulations to give a nice, natural human
modulation function.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_MODULATE_H
-#define STK_MODULATE_H
-
-#include "Generator.h"
-#include "SineWave.h"
-#include "SubNoise.h"
-#include "OnePole.h"
-
class Modulate : public Generator
{
public:
@@ -25,33 +27,82 @@ class Modulate : public Generator
/*!
An StkError can be thrown if the rawwave path is incorrect.
*/
- Modulate();
+ Modulate( void );
//! Class destructor.
- ~Modulate();
+ ~Modulate( void );
//! Reset internal state.
- void reset();
+ void reset( void ) { lastFrame_[0] = 0.0; };
//! Set the periodic (vibrato) rate or frequency in Hz.
- void setVibratoRate(StkFloat rate);
+ void setVibratoRate( StkFloat rate ) { vibrato_.setFrequency( rate ); };
//! Set the periodic (vibrato) gain.
- void setVibratoGain(StkFloat gain);
+ void setVibratoGain( StkFloat gain ) { vibratoGain_ = gain; };
//! Set the random modulation gain.
- void setRandomGain(StkFloat gain);
+ void setRandomGain( StkFloat gain );
+
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Compute and return one output sample.
+ StkFloat tick( void );
+
+ //! Fill a channel of the StkFrames object with computed outputs.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
+ void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
SineWave vibrato_;
- SubNoise noise_;
+ Noise noise_;
OnePole filter_;
StkFloat vibratoGain_;
StkFloat randomGain_;
+ unsigned int noiseRate_;
+ unsigned int noiseCounter_;
};
+inline StkFloat Modulate :: tick( void )
+{
+ // Compute periodic and random modulations.
+ lastFrame_[0] = vibratoGain_ * vibrato_.tick();
+ if ( noiseCounter_++ >= noiseRate_ ) {
+ noise_.tick();
+ noiseCounter_ = 0;
+ }
+ lastFrame_[0] += filter_.tick( noise_.lastOut() );
+ return lastFrame_[0];
+}
+
+inline StkFrames& Modulate :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Modulate::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; isetFrequency( mSpeed ); };
//! Set the modulation (vibrato) depth.
- void setModulationDepth(StkFloat mDepth);
+ void setModulationDepth( StkFloat mDepth ) { modDepth_ = mDepth * 0.5; };
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
FormSwep filters_[2];
StkFloat modDepth_;
StkFloat filterQ_;
@@ -62,4 +65,24 @@ class Moog : public Sampler
};
+inline StkFloat Moog :: tick( unsigned int )
+{
+ StkFloat temp;
+
+ if ( modDepth_ != 0.0 ) {
+ temp = loops_[1]->tick() * modDepth_;
+ loops_[0]->setFrequency( baseFrequency_ * (1.0 + temp) );
+ }
+
+ temp = attackGain_ * attacks_[0]->tick();
+ temp += loopGain_ * loops_[0]->tick();
+ temp = filter_.tick( temp );
+ temp *= adsr_.tick();
+ temp = filters_[0].tick( temp );
+ lastFrame_[0] = filters_[1].tick( temp );
+ return lastFrame_[0] * 6.0;
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Mutex.h b/include/Mutex.h
index ac04384..7f40c6d 100644
--- a/include/Mutex.h
+++ b/include/Mutex.h
@@ -1,16 +1,3 @@
-/***************************************************/
-/*! \class Mutex
- \brief STK mutex class.
-
- This class provides a uniform interface for
- cross-platform mutex use. On Linux and IRIX
- systems, the pthread library is used. Under
- Windows, critical sections are used.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
#ifndef STK_MUTEX_H
#define STK_MUTEX_H
@@ -31,6 +18,21 @@
#endif
+namespace stk {
+
+/***************************************************/
+/*! \class Mutex
+ \brief STK mutex class.
+
+ This class provides a uniform interface for
+ cross-platform mutex use. On Linux and IRIX
+ systems, the pthread library is used. Under
+ Windows, critical sections are used.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
+*/
+/***************************************************/
+
class Mutex : public Stk
{
public:
@@ -67,4 +69,6 @@ class Mutex : public Stk
};
+} // stk namespace
+
#endif
diff --git a/include/NRev.h b/include/NRev.h
index dce31cd..f2d68df 100644
--- a/include/NRev.h
+++ b/include/NRev.h
@@ -1,45 +1,85 @@
+#ifndef STK_NREV_H
+#define STK_NREV_H
+
+#include "Effect.h"
+#include "Delay.h"
+
+namespace stk {
+
/***************************************************/
/*! \class NRev
\brief CCRMA's NRev reverberator class.
- This class is derived from the CLM NRev
- function, which is based on the use of
- networks of simple allpass and comb delay
- filters. This particular arrangement consists
- of 6 comb filters in parallel, followed by 3
- allpass filters, a lowpass filter, and another
- allpass in series, followed by two allpass
- filters in parallel with corresponding right
- and left outputs.
+ This class takes a monophonic input signal and produces a stereo
+ output signal. It is derived from the CLM NRev function, which is
+ based on the use of networks of simple allpass and comb delay
+ filters. This particular arrangement consists of 6 comb filters
+ in parallel, followed by 3 allpass filters, a lowpass filter, and
+ another allpass in series, followed by two allpass filters in
+ parallel with corresponding right and left outputs.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_NREV_H
-#define STK_NREV_H
-
-#include "Effect.h"
-#include "Delay.h"
-
class NRev : public Effect
{
public:
//! Class constructor taking a T60 decay time argument (one second default value).
NRev( StkFloat T60 = 1.0 );
- //! Class destructor.
- ~NRev();
-
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set the reverberation T60 decay time.
void setT60( StkFloat T60 );
- protected:
+ //! Return the specified channel value of the last computed stereo frame.
+ /*!
+ Use the lastFrame() function to get both values of the last
+ computed stereo frame. The \c channel argument must be 0 or 1
+ (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.
+ */
+ StkFloat lastOut( unsigned int channel = 0 );
- StkFloat computeSample( StkFloat input );
+ //! Input one sample to the effect and return the specified \c channel value of the computed stereo frame.
+ /*!
+ Use the lastFrame() function to get both values of the computed
+ stereo output frame. The \c channel argument must be 0 or 1 (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.
+ */
+ StkFloat tick( StkFloat input, unsigned int channel = 0 );
+
+ //! Take a channel of the StkFrames object as inputs to the effect and replace with stereo outputs.
+ /*!
+ The StkFrames argument reference is returned. The stereo
+ outputs are written to the StkFrames argument starting at the
+ specified \c channel. Therefore, the \c channel argument must be
+ less than ( channels() - 1 ) of 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+ //! Take a channel of the \c iFrames object as inputs to the effect and write stereo outputs to the \c oFrames object.
+ /*!
+ The \c iFrames object reference is returned. The \c iChannel
+ argument must be less than the number of channels in the \c
+ iFrames argument (the first channel is specified by 0). The \c
+ oChannel argument must be less than ( channels() - 1 ) of the \c
+ oFrames argument. 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.
+ */
+ StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
+
+ protected:
Delay allpassDelays_[8];
Delay combDelays_[6];
@@ -49,5 +89,72 @@ class NRev : public Effect
};
+inline StkFloat NRev :: lastOut( unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel > 1 ) {
+ errorString_ << "NRev::lastOut(): channel argument must be less than 2!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ return lastFrame_[channel];
+}
+
+inline StkFloat NRev :: tick( StkFloat input, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel > 1 ) {
+ errorString_ << "NRev::tick(): channel argument must be less than 2!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat temp, temp0, temp1, temp2, temp3;
+ int i;
+
+ temp0 = 0.0;
+ for ( i=0; i<6; i++ ) {
+ temp = input + (combCoefficient_[i] * combDelays_[i].lastOut());
+ temp0 += combDelays_[i].tick(temp);
+ }
+
+ for ( i=0; i<3; i++ ) {
+ temp = allpassDelays_[i].lastOut();
+ temp1 = allpassCoefficient_ * temp;
+ temp1 += temp0;
+ allpassDelays_[i].tick(temp1);
+ temp0 = -(allpassCoefficient_ * temp1) + temp;
+ }
+
+ // One-pole lowpass filter.
+ lowpassState_ = 0.7 * lowpassState_ + 0.3 * temp0;
+ temp = allpassDelays_[3].lastOut();
+ temp1 = allpassCoefficient_ * temp;
+ temp1 += lowpassState_;
+ allpassDelays_[3].tick( temp1 );
+ temp1 = -( allpassCoefficient_ * temp1 ) + temp;
+
+ temp = allpassDelays_[4].lastOut();
+ temp2 = allpassCoefficient_ * temp;
+ temp2 += temp1;
+ allpassDelays_[4].tick( temp2 );
+ lastFrame_[0] = effectMix_*( -( allpassCoefficient_ * temp2 ) + temp );
+
+ temp = allpassDelays_[5].lastOut();
+ temp3 = allpassCoefficient_ * temp;
+ temp3 += temp1;
+ allpassDelays_[5].tick( temp3 );
+ lastFrame_[1] = effectMix_*( - ( allpassCoefficient_ * temp3 ) + temp );
+
+ temp = ( 1.0 - effectMix_ ) * input;
+ lastFrame_[0] += temp;
+ lastFrame_[1] += temp;
+
+ return lastFrame_[channel];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Noise.h b/include/Noise.h
index 6d154e8..135bd32 100644
--- a/include/Noise.h
+++ b/include/Noise.h
@@ -1,3 +1,10 @@
+#ifndef STK_NOISE_H
+#define STK_NOISE_H
+
+#include "Generator.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Noise
\brief STK noise generator.
@@ -6,31 +13,20 @@
C rand() function. The quality of the rand()
function varies from one OS to another.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_NOISE_H
-#define STK_NOISE_H
-
-#include "Generator.h"
-
class Noise : public Generator
{
public:
- //! Default constructor which seeds the random number generator with the system time.
- Noise();
-
- //! Constructor which seeds the random number generator with a given seed.
+ //! Default constructor that can also take a specific seed value.
/*!
- If the seed value is zero, the random number generator is
+ If the seed value is zero (the default value), the random number generator is
seeded with the system time.
*/
- Noise( unsigned int seed );
-
- //! Class destructor.
- virtual ~Noise();
+ Noise( unsigned int seed = 0 );
//! Seed the random number generator with a specific seed value.
/*!
@@ -39,10 +35,49 @@ public:
*/
void setSeed( unsigned int seed = 0 );
-protected:
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
- virtual StkFloat computeSample( void );
+ //! Compute and return one output sample.
+ StkFloat tick( void );
+
+ //! Fill a channel of the StkFrames object with computed outputs.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+protected:
};
+inline StkFloat Noise :: tick( void )
+{
+ return lastFrame_[0] = (StkFloat) ( 2.0 * rand() / (RAND_MAX + 1.0) - 1.0 );
+}
+
+inline StkFrames& Noise :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Noise::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i= frames.channels() ) {
+ errorString_ << "OnePole::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "OnePole::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i= frames.channels() ) {
+ errorString_ << "OneZero::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "OneZero::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i 1 ) {
+ errorString_ << "PRCRev::lastOut(): channel argument must be less than 2!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ return lastFrame_[channel];
+}
+
+ inline StkFloat PRCRev :: tick( StkFloat input, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel > 1 ) {
+ errorString_ << "PRCRev::tick(): channel argument must be less than 2!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat temp, temp0, temp1, temp2, temp3;
+
+ temp = allpassDelays_[0].lastOut();
+ temp0 = allpassCoefficient_ * temp;
+ temp0 += input;
+ allpassDelays_[0].tick(temp0);
+ temp0 = -(allpassCoefficient_ * temp0) + temp;
+
+ temp = allpassDelays_[1].lastOut();
+ temp1 = allpassCoefficient_ * temp;
+ temp1 += temp0;
+ allpassDelays_[1].tick(temp1);
+ temp1 = -(allpassCoefficient_ * temp1) + temp;
+
+ temp2 = temp1 + (combCoefficient_[0] * combDelays_[0].lastOut());
+ temp3 = temp1 + (combCoefficient_[1] * combDelays_[1].lastOut());
+
+ lastFrame_[0] = effectMix_ * (combDelays_[0].tick(temp2));
+ lastFrame_[1] = effectMix_ * (combDelays_[1].tick(temp3));
+ temp = (1.0 - effectMix_) * input;
+ lastFrame_[0] += temp;
+ lastFrame_[1] += temp;
+
+ return lastFrame_[channel];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/PercFlut.h b/include/PercFlut.h
index 5745466..8ddc7f8 100644
--- a/include/PercFlut.h
+++ b/include/PercFlut.h
@@ -1,3 +1,10 @@
+#ifndef STK_PERCFLUT_H
+#define STK_PERCFLUT_H
+
+#include "FM.h"
+
+namespace stk {
+
/***************************************************/
/*! \class PercFlut
\brief STK percussive flute FM synthesis instrument.
@@ -22,15 +29,10 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_PERCFLUT_H
-#define STK_PERCFLUT_H
-
-#include "FM.h"
-
class PercFlut : public FM
{
public:
@@ -38,20 +40,51 @@ class PercFlut : public FM
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
- PercFlut();
+ PercFlut( void );
//! Class destructor.
- ~PercFlut();
+ ~PercFlut( void );
//! Set instrument parameters for a particular frequency.
- void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
};
+inline StkFloat PercFlut :: tick( unsigned int )
+{
+ register StkFloat temp;
+
+ temp = vibrato_.tick() * modDepth_ * 0.2;
+ waves_[0]->setFrequency(baseFrequency_ * (1.0 + temp) * ratios_[0]);
+ waves_[1]->setFrequency(baseFrequency_ * (1.0 + temp) * ratios_[1]);
+ waves_[2]->setFrequency(baseFrequency_ * (1.0 + temp) * ratios_[2]);
+ waves_[3]->setFrequency(baseFrequency_ * (1.0 + temp) * ratios_[3]);
+
+ waves_[3]->addPhaseOffset( twozero_.lastOut() );
+ temp = gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
+
+ twozero_.tick(temp);
+ waves_[2]->addPhaseOffset( temp );
+ temp = (1.0 - (control2_ * 0.5)) * gains_[2] * adsr_[2]->tick() * waves_[2]->tick();
+
+ temp += control2_ * 0.5 * gains_[1] * adsr_[1]->tick() * waves_[1]->tick();
+ temp = temp * control1_;
+
+ waves_[0]->addPhaseOffset(temp);
+ temp = gains_[0] * adsr_[0]->tick() * waves_[0]->tick();
+
+ lastFrame_[0] = temp * 0.5;
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Phonemes.h b/include/Phonemes.h
index 21773ad..94a0214 100644
--- a/include/Phonemes.h
+++ b/include/Phonemes.h
@@ -1,3 +1,10 @@
+#ifndef STK_PHONEMES_H
+#define STK_PHONEMES_H
+
+#include "Stk.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Phonemes
\brief STK phonemes table.
@@ -6,15 +13,10 @@
set of 32 static phoneme formant parameters
and provide access to those values.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_PHONEMES_H
-#define STK_PHONEMES_H
-
-#include "Stk.h"
-
class Phonemes : public Stk
{
public:
@@ -47,4 +49,6 @@ private:
static const StkFloat phonemeParameters[][4][3];
};
+} // stk namespace
+
#endif
diff --git a/include/PitShift.h b/include/PitShift.h
index 521bb57..ab6b63f 100644
--- a/include/PitShift.h
+++ b/include/PitShift.h
@@ -1,3 +1,11 @@
+#ifndef STK_PITSHIFT_H
+#define STK_PITSHIFT_H
+
+#include "Effect.h"
+#include "DelayL.h"
+
+namespace stk {
+
/***************************************************/
/*! \class PitShift
\brief STK simple pitch shifter effect class.
@@ -5,43 +13,95 @@
This class implements a simple pitch shifter
using delay lines.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_PITSHIFT_H
-#define STK_PITSHIFT_H
-
-#include "Effect.h"
-#include "DelayL.h"
+const int maxDelay = 5024;
class PitShift : public Effect
{
public:
//! Class constructor.
- PitShift();
-
- //! Class destructor.
- ~PitShift();
+ PitShift( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set the pitch shift factor (1.0 produces no shift).
- void setShift(StkFloat shift);
+ void setShift( StkFloat shift );
+
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Input one sample to the effect and return one output.
+ StkFloat tick( StkFloat input );
+
+ //! Take a channel of the StkFrames object as inputs to the effect and replace with corresponding outputs.
+ /*!
+ The StkFrames argument reference is returned. The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+ //! Take a channel of the \c iFrames object as inputs to the effect and write outputs to the \c oFrames object.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
- StkFloat computeSample( StkFloat input );
-
DelayL delayLine_[2];
StkFloat delay_[2];
StkFloat env_[2];
StkFloat rate_;
- unsigned long delayLength;
- unsigned long halfLength;
+ unsigned long delayLength_;
+ unsigned long halfLength_;
};
+inline StkFloat PitShift :: tick( StkFloat input )
+{
+ // Calculate the two delay length values, keeping them within the
+ // range 12 to maxDelay-12.
+ delay_[0] += rate_;
+ while ( delay_[0] > maxDelay-12 ) delay_[0] -= delayLength_;
+ while ( delay_[0] < 12 ) delay_[0] += delayLength_;
+
+ delay_[1] = delay_[0] + halfLength_;
+ while ( delay_[1] > maxDelay-12 ) delay_[1] -= delayLength_;
+ while ( delay_[1] < 12 ) delay_[1] += delayLength_;
+
+ // Set the new delay line lengths.
+ delayLine_[0].setDelay( delay_[0] );
+ delayLine_[1].setDelay( delay_[1] );
+
+ // Calculate a triangular envelope.
+ env_[1] = fabs( ( delay_[0] - halfLength_ + 12 ) * ( 1.0 / (halfLength_ + 12 ) ) );
+ env_[0] = 1.0 - env_[1];
+
+ // Delay input and apply envelope.
+ lastFrame_[0] = env_[0] * delayLine_[0].tick( input );
+ lastFrame_[0] += env_[1] * delayLine_[1].tick( input );
+
+ // Compute effect mix and output.
+ lastFrame_[0] *= effectMix_;
+ lastFrame_[0] += ( 1.0 - effectMix_ ) * input;
+
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/PluckTwo.h b/include/PluckTwo.h
index 3e479ec..95616ac 100644
--- a/include/PluckTwo.h
+++ b/include/PluckTwo.h
@@ -1,3 +1,13 @@
+#ifndef STK_PLUCKTWO_H
+#define STK_PLUCKTWO_H
+
+#include "Instrmnt.h"
+#include "DelayL.h"
+#include "DelayA.h"
+#include "OneZero.h"
+
+namespace stk {
+
/***************************************************/
/*! \class PluckTwo
\brief STK enhanced plucked string model class.
@@ -14,41 +24,33 @@
use possibly subject to patents held by
Stanford University, Yamaha, and others.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_PLUCKTWO_H
-#define STK_PLUCKTWO_H
-
-#include "Instrmnt.h"
-#include "DelayL.h"
-#include "DelayA.h"
-#include "OneZero.h"
-
class PluckTwo : public Instrmnt
{
public:
//! Class constructor, taking the lowest desired playing frequency.
- PluckTwo(StkFloat lowestFrequency);
+ PluckTwo( StkFloat lowestFrequency );
//! Class destructor.
- virtual ~PluckTwo();
+ virtual ~PluckTwo( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set instrument parameters for a particular frequency.
- virtual void setFrequency(StkFloat frequency);
+ virtual void setFrequency( StkFloat frequency );
//! Detune the two strings by the given factor. A value of 1.0 produces unison strings.
- void setDetune(StkFloat detune);
+ void setDetune( StkFloat detune );
//! Efficient combined setting of frequency and detuning.
- void setFreqAndDetune(StkFloat frequency, StkFloat detune);
+ void setFreqAndDetune( StkFloat frequency, StkFloat detune );
//! Set the pluck or "excitation" position along the string (0.0 - 1.0).
- void setPluckPosition(StkFloat position);
+ void setPluckPosition( StkFloat position );
//! Set the base loop gain.
/*!
@@ -56,15 +58,15 @@ class PluckTwo : public Instrmnt
Because of high-frequency loop filter roll-off, higher
frequency settings have greater loop gains.
*/
- void setBaseLoopGain(StkFloat aGain);
+ void setBaseLoopGain( StkFloat aGain );
//! Stop a note with the given amplitude (speed of decay).
- virtual void noteOff(StkFloat amplitude);
+ virtual void noteOff( StkFloat amplitude );
+
+ virtual StkFloat tick( unsigned int channel = 0 ) = 0;
protected:
- virtual StkFloat computeSample( void ) = 0;
-
DelayA delayLine_;
DelayA delayLine2_;
DelayL combDelay_;
@@ -82,4 +84,6 @@ class PluckTwo : public Instrmnt
};
+} // stk namespace
+
#endif
diff --git a/include/Plucked.h b/include/Plucked.h
index ceba36c..c081883 100644
--- a/include/Plucked.h
+++ b/include/Plucked.h
@@ -1,3 +1,14 @@
+#ifndef STK_PLUCKED_H
+#define STK_PLUCKED_H
+
+#include "Instrmnt.h"
+#include "DelayA.h"
+#include "OneZero.h"
+#include "OnePole.h"
+#include "Noise.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Plucked
\brief STK plucked string model class.
@@ -13,47 +24,39 @@
Stanford, bearing the names of Karplus and/or
Strong.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_PLUCKED_H
-#define STK_PLUCKED_H
-
-#include "Instrmnt.h"
-#include "DelayA.h"
-#include "OneZero.h"
-#include "OnePole.h"
-#include "Noise.h"
-
class Plucked : public Instrmnt
{
public:
//! Class constructor, taking the lowest desired playing frequency.
- Plucked(StkFloat lowestFrequency);
+ Plucked( StkFloat lowestFrequency );
//! Class destructor.
- ~Plucked();
+ ~Plucked( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set instrument parameters for a particular frequency.
- virtual void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Pluck the string with the given amplitude using the current frequency.
- void pluck(StkFloat amplitude);
+ void pluck( StkFloat amplitude );
//! Start a note with the given frequency and amplitude.
- virtual void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- virtual void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
DelayA delayLine_;
OneZero loopFilter_;
OnePole pickFilter_;
@@ -63,5 +66,13 @@ class Plucked : public Instrmnt
};
+inline StkFloat Plucked :: tick( unsigned int )
+{
+ // Here's the whole inner loop of the instrument!!
+ return lastFrame_[0] = 3.0 * delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ ) );
+}
+
+} // stk namespace
+
#endif
diff --git a/include/PoleZero.h b/include/PoleZero.h
index 5f1b520..a064a87 100644
--- a/include/PoleZero.h
+++ b/include/PoleZero.h
@@ -1,23 +1,24 @@
-/***************************************************/
-/*! \class PoleZero
- \brief STK one-pole, one-zero filter class.
-
- This protected Filter subclass implements
- a one-pole, one-zero digital filter. A
- method is provided for creating an allpass
- filter with a given coefficient. Another
- method is provided to create a DC blocking filter.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
#ifndef STK_POLEZERO_H
#define STK_POLEZERO_H
#include "Filter.h"
-class PoleZero : protected Filter
+namespace stk {
+
+/***************************************************/
+/*! \class PoleZero
+ \brief STK one-pole, one-zero filter class.
+
+ This class implements a one-pole, one-zero digital filter. A
+ method is provided for creating an allpass filter with a given
+ coefficient. Another method is provided to create a DC blocking
+ filter.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
+*/
+/***************************************************/
+
+class PoleZero : public Filter
{
public:
@@ -27,17 +28,17 @@ class PoleZero : protected Filter
//! Class destructor.
~PoleZero();
- //! Clears the internal states of the filter.
- void clear(void);
-
//! Set the b[0] coefficient value.
- void setB0(StkFloat b0);
+ void setB0( StkFloat b0 ) { b_[0] = b0; };
//! Set the b[1] coefficient value.
- void setB1(StkFloat b1);
+ void setB1( StkFloat b1 ) { b_[1] = b1; };
//! Set the a[1] coefficient value.
- void setA1(StkFloat a1);
+ void setA1( StkFloat a1 ) { a_[1] = a1; };
+
+ //! Set all filter coefficients.
+ void setCoefficients( StkFloat b0, StkFloat b1, StkFloat a1, bool clearState = false );
//! Set the filter for allpass behavior using \e coefficient.
/*!
@@ -45,7 +46,7 @@ class PoleZero : protected Filter
which has unity gain at all frequencies. Note that the \e
coefficient magnitude must be less than one to maintain stability.
*/
- void setAllpass(StkFloat coefficient);
+ void setAllpass( StkFloat coefficient );
//! Create a DC blocking filter with the given pole position in the z-plane.
/*!
@@ -54,33 +55,58 @@ class PoleZero : protected Filter
close to one to minimize low-frequency attenuation.
*/
- void setBlockZero(StkFloat thePole = 0.99);
-
- //! Set the filter gain.
- /*!
- The gain is applied at the filter input and does not affect the
- coefficient values. The default gain value is 1.0.
- */
- void setGain( StkFloat gain );
-
- //! Return the current filter gain.
- StkFloat getGain( void ) const;
+ void setBlockZero( StkFloat thePole = 0.99 );
//! Return the last computed output value.
- StkFloat lastOut( void ) const;
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Input one sample to the filter and return one output.
- StkFloat tick( StkFloat sample );
+ StkFloat tick( StkFloat input );
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
- The \c channel argument should be zero or greater (the first
- channel is specified by 0). An StkError will be thrown if the \c
- channel argument is equal to or greater than the number of
- channels in the StkFrames object.
+ The \c 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.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
};
+inline StkFloat PoleZero :: tick( StkFloat input )
+{
+ inputs_[0] = gain_ * input;
+ lastFrame_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] - a_[1] * outputs_[1];
+ inputs_[1] = inputs_[0];
+ outputs_[1] = lastFrame_[0];
+
+ return lastFrame_[0];
+}
+
+inline StkFrames& PoleZero :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "PoleZero::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i 1, the reed has slammed shut and the
+ // reflection function value saturates at 1.0.
+ if ( lastFrame_[0] > 1.0) lastFrame_[0] = (StkFloat) 1.0;
+
+ // This is nearly impossible in a physical system, but
+ // a reflection function value of -1.0 corresponds to
+ // an open end (and no discontinuity in bore profile).
+ if ( lastFrame_[0] < -1.0) lastFrame_[0] = (StkFloat) -1.0;
+
+ return lastFrame_[0];
+}
+
+inline StkFrames& ReedTable :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "ReedTable::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i 1.0) *samples = 1.0;
+ if ( *samples < -1.0) *samples = -1.0;
+ }
+
+ lastFrame_[0] = *(samples-hop);
+ return frames;
+}
+
+inline StkFrames& ReedTable :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
+{
+#if defined(_STK_DEBUG_)
+ if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "ReedTable::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i 1.0) *oSamples = 1.0;
+ if ( *oSamples < -1.0) *oSamples = -1.0;
+ }
+
+ lastFrame_[0] = *(oSamples-oHop);
+ return iFrames;
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Resonate.h b/include/Resonate.h
index b5b3f05..4152ad8 100644
--- a/include/Resonate.h
+++ b/include/Resonate.h
@@ -1,3 +1,13 @@
+#ifndef STK_RESONATE_H
+#define STK_RESONATE_H
+
+#include "Instrmnt.h"
+#include "ADSR.h"
+#include "BiQuad.h"
+#include "Noise.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Resonate
\brief STK noise driven formant filter.
@@ -13,58 +23,51 @@
- Zero Radii = 1
- Envelope Gain = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_RESONATE_H
-#define STK_RESONATE_H
-
-#include "Instrmnt.h"
-#include "ADSR.h"
-#include "BiQuad.h"
-#include "Noise.h"
-
class Resonate : public Instrmnt
{
public:
//! Class constructor.
- Resonate();
+ Resonate( void );
//! Class destructor.
- ~Resonate();
+ ~Resonate( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set the filter for a resonance at the given frequency (Hz) and radius.
- void setResonance(StkFloat frequency, StkFloat radius);
+ void setResonance( StkFloat frequency, StkFloat radius );
//! Set the filter for a notch at the given frequency (Hz) and radius.
- void setNotch(StkFloat frequency, StkFloat radius);
+ void setNotch( StkFloat frequency, StkFloat radius );
//! Set the filter zero coefficients for contant resonance gain.
- void setEqualGainZeroes();
+ void setEqualGainZeroes( void ) { filter_.setEqualGainZeroes(); };
//! Initiate the envelope with a key-on event.
- void keyOn();
+ void keyOn( void ) { adsr_.keyOn(); };
//! Signal a key-off event to the envelope.
- void keyOff();
+ void keyOff( void ) { adsr_.keyOff(); };
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
ADSR adsr_;
BiQuad filter_;
Noise noise_;
@@ -75,4 +78,13 @@ class Resonate : public Instrmnt
};
+inline StkFloat Resonate :: tick( unsigned int )
+{
+ lastFrame_[0] = filter_.tick( noise_.tick() );
+ lastFrame_[0] *= adsr_.tick();
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Rhodey.h b/include/Rhodey.h
index d7ab2b3..9f845cb 100644
--- a/include/Rhodey.h
+++ b/include/Rhodey.h
@@ -1,3 +1,10 @@
+#ifndef STK_RHODEY_H
+#define STK_RHODEY_H
+
+#include "FM.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Rhodey
\brief STK Fender Rhodes electric piano FM
@@ -26,15 +33,10 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_RHODEY_H
-#define STK_RHODEY_H
-
-#include "FM.h"
-
class Rhodey : public FM
{
public:
@@ -42,20 +44,48 @@ class Rhodey : public FM
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
- Rhodey();
+ Rhodey( void );
//! Class destructor.
- ~Rhodey();
+ ~Rhodey( void );
//! Set instrument parameters for a particular frequency.
- void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
};
+inline StkFloat Rhodey :: tick( unsigned int )
+{
+ StkFloat temp, temp2;
+
+ temp = gains_[1] * adsr_[1]->tick() * waves_[1]->tick();
+ temp = temp * control1_;
+
+ waves_[0]->addPhaseOffset( temp );
+ waves_[3]->addPhaseOffset( twozero_.lastOut() );
+ temp = gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
+ twozero_.tick(temp);
+
+ waves_[2]->addPhaseOffset( temp );
+ temp = ( 1.0 - (control2_ * 0.5)) * gains_[0] * adsr_[0]->tick() * waves_[0]->tick();
+ temp += control2_ * 0.5 * gains_[2] * adsr_[2]->tick() * waves_[2]->tick();
+
+ // Calculate amplitude modulation and apply it to output.
+ temp2 = vibrato_.tick() * modDepth_;
+ temp = temp * (1.0 + temp2);
+
+ lastFrame_[0] = temp * 0.5;
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/RtAudio.h b/include/RtAudio.h
index 5acc9a5..5c5fd6f 100644
--- a/include/RtAudio.h
+++ b/include/RtAudio.h
@@ -4,13 +4,13 @@
RtAudio provides a common API (Application Programming Interface)
for realtime audio input/output across Linux (native ALSA, Jack,
- and OSS), SGI, Macintosh OS X (CoreAudio and Jack), and Windows
+ and OSS), Macintosh OS X (CoreAudio and Jack), and Windows
(DirectSound and ASIO) operating systems.
RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/
RtAudio: realtime audio i/o C++ classes
- Copyright (c) 2001-2007 Gary P. Scavone
+ Copyright (c) 2001-2009 Gary P. Scavone
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
@@ -42,7 +42,7 @@
\file RtAudio.h
*/
-// RtAudio: Version 4.0.3
+// RtAudio: Version 4.0.5
#ifndef __RTAUDIO_H
#define __RTAUDIO_H
@@ -108,11 +108,15 @@ static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; // Normalized between plus/mi
If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to
open the input and/or output stream device(s) for exclusive use.
Note that this is not possible with all supported audio APIs.
+
+ If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt
+ to select realtime scheduling (round-robin) for the callback thread.
*/
typedef unsigned int RtAudioStreamFlags;
static const RtAudioStreamFlags RTAUDIO_NONINTERLEAVED = 0x1; // Use non-interleaved buffers (default = interleaved).
static const RtAudioStreamFlags RTAUDIO_MINIMIZE_LATENCY = 0x2; // Attempt to set stream parameters for lowest possible latency.
static const RtAudioStreamFlags RTAUDIO_HOG_DEVICE = 0x4; // Attempt grab device and prevent use by others.
+static const RtAudioStreamFlags RTAUDIO_SCHEDULE_REALTIME = 0x8; // Try to select realtime scheduling for callback thread.
/*! \typedef typedef unsigned long RtAudioStreamStatus;
\brief RtAudio stream status (over- or underflow) flags.
@@ -240,9 +244,10 @@ class RtAudio
The following flags can be OR'ed together to allow a client to
make changes to the default stream behavior:
- - \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved).
- - \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency.
- - \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use.
+ - \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved).
+ - \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency.
+ - \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use.
+ - \e RTAUDIO_SCHEDULE_REALTIME: Attempt to select realtime scheduling for callback thread.
By default, RtAudio streams pass and receive audio data from the
client in an interleaved format. By passing the
@@ -268,6 +273,11 @@ class RtAudio
open the input and/or output stream device(s) for exclusive use.
Note that this is not possible with all supported audio APIs.
+ If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt
+ to select realtime scheduling (round-robin) for the callback thread.
+ The \c priority parameter will only be used if the RTAUDIO_SCHEDULE_REALTIME
+ flag is set. It defines the thread's realtime priority.
+
The \c numberOfBuffers parameter can be used to control stream
latency in the Windows DirectSound, Linux OSS, and Linux Alsa APIs
only. A value of two is usually the smallest allowed. Larger
@@ -285,10 +295,11 @@ class RtAudio
RtAudioStreamFlags flags; /*!< A bit-mask of stream flags (RTAUDIO_NONINTERLEAVED, RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE). */
unsigned int numberOfBuffers; /*!< Number of stream buffers. */
std::string streamName; /*!< A stream name (currently used only in Jack). */
+ int priority; /*!< Scheduling priority of callback thread (only used with flag RTAUDIO_SCHEDULE_REALTIME). */
// Default constructor.
StreamOptions()
- : flags(0), numberOfBuffers(0) {}
+ : flags(0), numberOfBuffers(0), priority(0) {}
};
//! A static function to determine the available compiled audio APIs.
@@ -440,10 +451,10 @@ class RtAudio
void abortStream( void );
//! Returns true if a stream is open and false if not.
- bool isStreamOpen( void ) throw();
+ bool isStreamOpen( void ) const throw();
//! Returns true if the stream is running and false if it is stopped or not open.
- bool isStreamRunning( void ) throw();
+ bool isStreamRunning( void ) const throw();
//! Returns the number of elapsed seconds since the stream was started.
/*!
@@ -462,6 +473,14 @@ class RtAudio
*/
long getStreamLatency( void );
+ //! Returns actual sample rate in use by the stream.
+ /*!
+ On some systems, the sample rate used may be slightly different
+ than that specified in the stream parameters. If a stream is not
+ open, an RtError (type = INVALID_USE) will be thrown.
+ */
+ unsigned int getStreamSampleRate( void );
+
//! Specify whether warning messages should be printed to stderr.
void showWarnings( bool value = true ) throw();
@@ -551,9 +570,10 @@ public:
virtual void stopStream( void ) = 0;
virtual void abortStream( void ) = 0;
long getStreamLatency( void );
+ unsigned int getStreamSampleRate( void );
virtual double getStreamTime( void );
- bool isStreamOpen( void ) { return stream_.state != STREAM_CLOSED; };
- bool isStreamRunning( void ) { return stream_.state == STREAM_RUNNING; };
+ bool isStreamOpen( void ) const { return stream_.state != STREAM_CLOSED; };
+ bool isStreamRunning( void ) const { return stream_.state == STREAM_RUNNING; };
void showWarnings( bool value ) { showWarnings_ = value; };
@@ -617,7 +637,7 @@ protected:
#endif
RtApiStream()
- :apiHandle(0), deviceBuffer(0) {}
+ :apiHandle(0), deviceBuffer(0) { device[0] = 11111; device[1] = 11111; }
};
typedef signed short Int16;
@@ -688,9 +708,10 @@ inline void RtAudio :: closeStream( void ) throw() { return rtapi_->closeStream(
inline void RtAudio :: startStream( void ) { return rtapi_->startStream(); }
inline void RtAudio :: stopStream( void ) { return rtapi_->stopStream(); }
inline void RtAudio :: abortStream( void ) { return rtapi_->abortStream(); }
-inline bool RtAudio :: isStreamOpen( void ) throw() { return rtapi_->isStreamOpen(); }
-inline bool RtAudio :: isStreamRunning( void ) throw() { return rtapi_->isStreamRunning(); }
+inline bool RtAudio :: isStreamOpen( void ) const throw() { return rtapi_->isStreamOpen(); }
+inline bool RtAudio :: isStreamRunning( void ) const throw() { return rtapi_->isStreamRunning(); }
inline long RtAudio :: getStreamLatency( void ) { return rtapi_->getStreamLatency(); }
+inline unsigned int RtAudio :: getStreamSampleRate( void ) { return rtapi_->getStreamSampleRate(); };
inline double RtAudio :: getStreamTime( void ) { return rtapi_->getStreamTime(); }
inline void RtAudio :: showWarnings( bool value ) throw() { rtapi_->showWarnings( value ); }
@@ -867,6 +888,8 @@ public:
private:
+ std::vector devices_;
+ void saveDeviceInfo( void );
bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
unsigned int firstChannel, unsigned int sampleRate,
RtAudioFormat format, unsigned int *bufferSize,
diff --git a/include/RtMidi.h b/include/RtMidi.h
index e443e2a..2928eaf 100644
--- a/include/RtMidi.h
+++ b/include/RtMidi.h
@@ -8,7 +8,7 @@
RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/
RtMidi: realtime MIDI i/o C++ classes
- Copyright (c) 2003-2007 Gary P. Scavone
+ Copyright (c) 2003-2009 Gary P. Scavone
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
@@ -35,7 +35,7 @@
*/
/**********************************************************************/
-// RtMidi: Version 1.0.7
+// RtMidi: Version 1.0.9
#ifndef RTMIDI_H
#define RTMIDI_H
@@ -48,7 +48,7 @@ class RtMidi
public:
//! Pure virtual openPort() function.
- virtual void openPort( unsigned int portNumber = 0 ) = 0;
+ virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0;
//! Pure virtual openVirtualPort() function.
virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0;
@@ -91,7 +91,7 @@ class RtMidi
to open a virtual input port to which other MIDI software clients
can connect.
- by Gary P. Scavone, 2003-2004.
+ by Gary P. Scavone, 2003-2008.
*/
/**********************************************************************/
@@ -105,11 +105,11 @@ class RtMidiIn : public RtMidi
//! User callback function type definition.
typedef void (*RtMidiCallback)( double timeStamp, std::vector *message, void *userData);
- //! Default constructor.
+ //! Default constructor that allows an optional client name.
/*!
An exception will be thrown if a MIDI system initialization error occurs.
*/
- RtMidiIn();
+ RtMidiIn( const std::string clientName = std::string( "RtMidi Input Client") );
//! If a MIDI connection is still open, it will be closed by the destructor.
~RtMidiIn();
@@ -119,7 +119,7 @@ class RtMidiIn : public RtMidi
An optional port number greater than 0 can be specified.
Otherwise, the default or first port found is opened.
*/
- void openPort( unsigned int portNumber = 0 );
+ void openPort( unsigned int portNumber = 0, const std::string Portname = std::string( "RtMidi Input" ) );
//! Create a virtual input port, with optional name, to allow software connections (OS X and ALSA only).
/*!
@@ -200,6 +200,7 @@ class RtMidiIn : public RtMidi
// the MIDI input handling function or thread.
struct RtMidiInData {
std::queue queue;
+ MidiMessage message;
unsigned int queueLimit;
unsigned char ignoreFlags;
bool doInput;
@@ -208,16 +209,18 @@ class RtMidiIn : public RtMidi
bool usingCallback;
void *userCallback;
void *userData;
+ bool continueSysex;
// Default constructor.
RtMidiInData()
: queueLimit(1024), ignoreFlags(7), doInput(false), firstMessage(true),
- apiData(0), usingCallback(false), userCallback(0), userData(0) {}
+ apiData(0), usingCallback(false), userCallback(0), userData(0),
+ continueSysex(false) {}
};
private:
- void initialize( void );
+ void initialize( const std::string& clientName );
RtMidiInData inputData_;
};
@@ -232,7 +235,7 @@ class RtMidiIn : public RtMidi
the connection. Create multiple instances of this class to
connect to more than one MIDI device at the same time.
- by Gary P. Scavone, 2003-2004.
+ by Gary P. Scavone, 2003-2008.
*/
/**********************************************************************/
@@ -240,11 +243,11 @@ class RtMidiOut : public RtMidi
{
public:
- //! Default constructor.
+ //! Default constructor that allows an optional client name.
/*!
An exception will be thrown if a MIDI system initialization error occurs.
*/
- RtMidiOut();
+ RtMidiOut( const std::string clientName = std::string( "RtMidi Output Client" ) );
//! The destructor closes any open MIDI connections.
~RtMidiOut();
@@ -256,7 +259,7 @@ class RtMidiOut : public RtMidi
exception is thrown if an error occurs while attempting to make
the port connection.
*/
- void openPort( unsigned int portNumber = 0 );
+ void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi Output" ) );
//! Close an open MIDI connection (if one exists).
void closePort();
@@ -290,7 +293,7 @@ class RtMidiOut : public RtMidi
private:
- void initialize( void );
+ void initialize( const std::string& clientName );
};
#endif
diff --git a/include/RtWvIn.h b/include/RtWvIn.h
index 8b625a2..8cc5cd0 100644
--- a/include/RtWvIn.h
+++ b/include/RtWvIn.h
@@ -1,3 +1,12 @@
+#ifndef STK_RTWVIN_H
+#define STK_RTWVIN_H
+
+#include "WvIn.h"
+#include "RtAudio.h"
+#include "Mutex.h"
+
+namespace stk {
+
/***************************************************/
/*! \class RtWvIn
\brief STK realtime audio (blocking) input class.
@@ -10,36 +19,28 @@
RtWvIn supports multi-channel data in both interleaved and
non-interleaved formats. It is important to distinguish the
- tick() methods, which return samples produced by averaging across
- sample frames, from the tickFrame() methods, which return
- references or pointers to multi-channel sample frames.
+ tick() method that computes a single frame (and returns only the
+ specified sample of a multi-channel frame) from the overloaded one
+ that takes an StkFrames object for multi-channel and/or
+ multi-frame data.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_RTWVIN_H
-#define STK_RTWVIN_H
-
-#include "WvIn.h"
-#include "RtAudio.h"
-
class RtWvIn : public WvIn
{
public:
//! Default constructor.
/*!
- The \e device argument is passed to RtAudio during
- instantiation. The default value (zero) will select the default
- device on your system or the first device found meeting the
- specified parameters. On systems with multiple
- soundcards/devices, values greater than zero can be specified in
- accordance with the order that the devices are enumerated by the
- underlying audio API. The default buffer size of RT_BUFFER_SIZE
- is defined in Stk.h. An StkError will be thrown if an error
- occurs duing instantiation.
+ The default \e device argument value (zero) will select the
+ default input device on your system. The first device enumerated
+ by the underlying audio API is specified with a value of one. The
+ default buffer size of RT_BUFFER_SIZE is defined in Stk.h. An
+ StkError will be thrown if an error occurs duing instantiation.
*/
- RtWvIn( unsigned int nChannels = 1, StkFloat sampleRate = Stk::sampleRate(), int device = 0, int bufferFrames = RT_BUFFER_SIZE, int nBuffers = 20 );
+ RtWvIn( unsigned int nChannels = 1, StkFloat sampleRate = Stk::sampleRate(),
+ int device = 0, int bufferFrames = RT_BUFFER_SIZE, int nBuffers = 20 );
//! Class destructor.
~RtWvIn();
@@ -58,15 +59,48 @@ public:
*/
void stop( void );
- // This function is not intended for general use but had to be made
+ //! Return the specified channel value of the last computed frame.
+ /*!
+ For multi-channel files, use the lastFrame() function to get
+ all values from the last computed frame. If the device is
+ stopped, the returned value is 0.0. The \c channel argument must
+ be less than the number of channels in the audio stream (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.
+ */
+ StkFloat lastOut( unsigned int channel = 0 );
+
+ //! Compute a sample frame and return the specified \c channel value.
+ /*!
+ For multi-channel files, use the lastFrame() function to get
+ all values from the computed frame. If the device is "stopped",
+ it is "started". The \c channel argument must be less than the
+ number of channels in the audio stream (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.
+ */
+ StkFloat tick( unsigned int channel = 0 );
+
+ //! Fill the StkFrames argument with computed frames and return the same reference.
+ /*!
+ If the device is "stopped", it is "started". The number of
+ channels in the StkFrames argument must equal the number of
+ channels specified during instantiation. However, this is only
+ checked if _STK_DEBUG_ is defined during compilation, in which
+ case an incompatibility will trigger an StkError exception.
+ */
+ StkFrames& tick( StkFrames& frames );
+
+ // This function is not intended for general use but must be
// public for access from the audio callback function.
void fillBuffer( void *buffer, unsigned int nFrames );
protected:
- void computeFrame( void );
-
RtAudio adc_;
+ Mutex mutex_;
bool stopped_;
unsigned int readIndex_;
unsigned int writeIndex_;
@@ -74,4 +108,18 @@ protected:
};
+inline StkFloat RtWvIn :: lastOut( unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= data_.channels() ) {
+ errorString_ << "RtWvIn::lastOut(): channel argument and audio stream are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ return lastFrame_[channel];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/RtWvOut.h b/include/RtWvOut.h
index 7e8545c..fdaa150 100644
--- a/include/RtWvOut.h
+++ b/include/RtWvOut.h
@@ -1,3 +1,12 @@
+#ifndef STK_RTWVOUT_H
+#define STK_RTWVOUT_H
+
+#include "WvOut.h"
+#include "RtAudio.h"
+#include "Mutex.h"
+
+namespace stk {
+
/***************************************************/
/*! \class RtWvOut
\brief STK realtime audio (blocking) output class.
@@ -9,35 +18,26 @@
low-latency is desired.
RtWvOut supports multi-channel data in interleaved format. It is
- important to distinguish the tick() methods, which output single
- samples to all channels in a sample frame, from the tickFrame()
- method, which take a pointer or reference to multi-channel sample
- frame data.
+ important to distinguish the tick() method that outputs a single
+ sample to all channels in a sample frame from the overloaded one
+ that takes a reference to an StkFrames object for multi-channel
+ and/or multi-frame data.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_RTWVOUT_H
-#define STK_RTWVOUT_H
-
-#include "WvOut.h"
-#include "RtAudio.h"
-
class RtWvOut : public WvOut
{
public:
//! Default constructor.
/*!
- The \e device argument is passed to RtAudio during
- instantiation. The default value (zero) will select the default
- device on your system. On systems with multiple
- soundcards/devices, values greater than zero can be specified in
- accordance with the order that the devices are enumerated by the
- underlying audio API. The default buffer size of RT_BUFFER_SIZE
- is defined in Stk.h. An StkError will be thrown if an error
- occurs duing instantiation.
+ The default \e device argument value (zero) will select the
+ default output device on your system. The first device enumerated
+ by the underlying audio API is specified with a value of one. The
+ default buffer size of RT_BUFFER_SIZE is defined in Stk.h. An
+ StkError will be thrown if an error occurs duing instantiation.
*/
RtWvOut( unsigned int nChannels = 1, StkFloat sampleRate = Stk::sampleRate(),
int device = 0, int bufferFrames = RT_BUFFER_SIZE, int nBuffers = 20 );
@@ -48,7 +48,7 @@ class RtWvOut : public WvOut
//! Start the audio output stream.
/*!
The stream is started automatically, if necessary, when a
- tick() or tickFrame method is called.
+ tick() method is called.
*/
void start( void );
@@ -59,16 +59,30 @@ class RtWvOut : public WvOut
*/
void stop( void );
- // This function is not intended for general use but had to be made
+ //! Output a single sample to all channels in a sample frame.
+ /*!
+ If the device is "stopped", it is "started".
+ */
+ void tick( const StkFloat sample );
+
+ //! Output the StkFrames data.
+ /*!
+ If the device is "stopped", it is "started". The number of
+ channels in the StkFrames argument must equal the number of
+ channels specified during instantiation. However, this is only
+ checked if _STK_DEBUG_ is defined during compilation, in which
+ case an incompatibility will trigger an StkError exception.
+ */
+ void tick( StkFrames& frames );
+
+ // This function is not intended for general use but must be
// public for access from the audio callback function.
int readBuffer( void *buffer, unsigned int frameCount );
protected:
- void computeSample( const StkFloat sample );
- void computeFrames( const StkFrames& frames );
-
RtAudio dac_;
+ Mutex mutex_;
bool stopped_;
unsigned int readIndex_;
unsigned int writeIndex_;
@@ -77,4 +91,6 @@ class RtWvOut : public WvOut
};
+} // stk namespace
+
#endif
diff --git a/include/SKINI.msg b/include/SKINI.msg
index 72bacf1..a161df9 100644
--- a/include/SKINI.msg
+++ b/include/SKINI.msg
@@ -9,10 +9,12 @@
where is the string used in the SKINI stream.
- by Perry R. Cook, 1995 - 2004.
+ by Perry R. Cook, 1995 - 2009.
*/
/*********************************************************/
+namespace stk {
+
#define NOPE -32767
#define YEP 1
#define SK_DBL -32766
@@ -124,4 +126,4 @@
#define __SK_SINGER_RndVibAmt_ 3008
#define __SK_SINGER_VibFreq_ __SK_Expression_
-
+} // stk namespace
diff --git a/include/SKINI.tbl b/include/SKINI.tbl
index e2a1877..6c9d47a 100644
--- a/include/SKINI.tbl
+++ b/include/SKINI.tbl
@@ -1,6 +1,8 @@
#include "SKINI.msg"
+namespace stk {
+
#define __SK_MaxMsgTypes_ 80
struct SkiniSpec { char messageString[32];
@@ -129,3 +131,5 @@ struct SkiniSpec skini_msgs[__SK_MaxMsgTypes_] =
/* message. */
/* */
/*************************************************************************/
+
+} // stk namespace
diff --git a/include/Sampler.h b/include/Sampler.h
index 0aa8e3b..433d85b 100644
--- a/include/Sampler.h
+++ b/include/Sampler.h
@@ -1,56 +1,59 @@
-/***************************************************/
-/*! \class Sampler
- \brief STK sampling synthesis abstract base class.
-
- This instrument provides an ADSR envelope, a one-pole filter, and
- structures for an arbitrary number of attack and loop waves.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
#ifndef STK_SAMPLER_H
#define STK_SAMPLER_H
#include "Instrmnt.h"
#include "ADSR.h"
-#include "WaveLoop.h"
+#include "FileLoop.h"
#include "OnePole.h"
+namespace stk {
+
+/***************************************************/
+/*! \class Sampler
+ \brief STK sampling synthesis abstract base class.
+
+ This instrument provides an ADSR envelope, a one-pole filter, and
+ structures for an arbitrary number of attack and looped files.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
+*/
+/***************************************************/
+
class Sampler : public Instrmnt
{
public:
//! Default constructor.
- Sampler();
+ Sampler( void );
//! Class destructor.
- virtual ~Sampler();
+ virtual ~Sampler( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set instrument parameters for a particular frequency.
- virtual void setFrequency(StkFloat frequency) = 0;
+ virtual void setFrequency( StkFloat frequency ) = 0;
//! Initiate the envelopes with a key-on event and reset the attack waves.
- void keyOn();
+ void keyOn( void );
//! Signal a key-off event to the envelopes.
- void keyOff();
+ void keyOff( void );
//! Stop a note with the given amplitude (speed of decay).
- virtual void noteOff(StkFloat amplitude);
+ virtual void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- virtual void controlChange(int number, StkFloat value) = 0;
+ virtual void controlChange( int number, StkFloat value ) = 0;
+
+ //! Compute and return one output sample.
+ virtual StkFloat tick( unsigned int channel = 0 ) = 0;
protected:
- virtual StkFloat computeSample( void ) = 0;
-
ADSR adsr_;
std::vector attacks_;
- std::vector loops_;
+ std::vector loops_;
OnePole filter_;
StkFloat baseFrequency_;
std::vector attackRatios_;
@@ -60,4 +63,6 @@ class Sampler : public Instrmnt
};
+} // stk namespace
+
#endif
diff --git a/include/Saxofony.h b/include/Saxofony.h
index 4f5b337..56e07dc 100644
--- a/include/Saxofony.h
+++ b/include/Saxofony.h
@@ -1,3 +1,16 @@
+#ifndef STK_SAXOFONY_H
+#define STK_SAXOFONY_H
+
+#include "Instrmnt.h"
+#include "DelayL.h"
+#include "ReedTable.h"
+#include "OneZero.h"
+#include "Envelope.h"
+#include "Noise.h"
+#include "SineWave.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Saxofony
\brief STK faux conical bore reed instrument class.
@@ -31,21 +44,10 @@
- Vibrato Gain = 1
- Breath Pressure = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_SAXOFONY_H
-#define STK_SAXOFONY_H
-
-#include "Instrmnt.h"
-#include "DelayL.h"
-#include "ReedTable.h"
-#include "OneZero.h"
-#include "Envelope.h"
-#include "Noise.h"
-#include "SineWave.h"
-
class Saxofony : public Instrmnt
{
public:
@@ -53,39 +55,40 @@ class Saxofony : public Instrmnt
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
- Saxofony(StkFloat lowestFrequency);
+ Saxofony( StkFloat lowestFrequency );
//! Class destructor.
- ~Saxofony();
+ ~Saxofony( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set instrument parameters for a particular frequency.
- void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Set the "blowing" position between the air column terminations (0.0 - 1.0).
- void setBlowPosition(StkFloat aPosition);
+ void setBlowPosition( StkFloat aPosition );
//! Apply breath pressure to instrument with given amplitude and rate of increase.
- void startBlowing(StkFloat amplitude, StkFloat rate);
+ void startBlowing( StkFloat amplitude, StkFloat rate );
//! Decrease breath pressure with given rate of decrease.
- void stopBlowing(StkFloat rate);
+ void stopBlowing( StkFloat rate );
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
DelayL delays_[2];
ReedTable reedTable_;
OneZero filter_;
@@ -100,4 +103,27 @@ class Saxofony : public Instrmnt
};
+inline StkFloat Saxofony :: tick( unsigned int )
+{
+ StkFloat pressureDiff;
+ StkFloat breathPressure;
+ StkFloat temp;
+
+ // Calculate the breath pressure (envelope + noise + vibrato)
+ breathPressure = envelope_.tick();
+ breathPressure += breathPressure * noiseGain_ * noise_.tick();
+ breathPressure += breathPressure * vibratoGain_ * vibrato_.tick();
+
+ temp = -0.95 * filter_.tick( delays_[0].lastOut() );
+ lastFrame_[0] = temp - delays_[1].lastOut();
+ pressureDiff = breathPressure - lastFrame_[0];
+ delays_[1].tick( temp );
+ delays_[0].tick( breathPressure - (pressureDiff * reedTable_.tick(pressureDiff)) - temp );
+
+ lastFrame_[0] *= outputGain_;
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Shakers.h b/include/Shakers.h
index e41ded4..ecf6d84 100644
--- a/include/Shakers.h
+++ b/include/Shakers.h
@@ -1,3 +1,10 @@
+#ifndef STK_SHAKERS_H
+#define STK_SHAKERS_H
+
+#include "Instrmnt.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Shakers
\brief PhISEM and PhOLIES class.
@@ -48,15 +55,10 @@
- Little Rocks = 21
- Tuned Bamboo Chimes = 22
- by Perry R. Cook, 1996 - 2004.
+ by Perry R. Cook, 1996 - 2009.
*/
/***************************************************/
-#ifndef STK_SHAKERS_H
-#define STK_SHAKERS_H
-
-#include "Instrmnt.h"
-
const int MAX_FREQS = 8;
const int NUM_INSTR = 24;
@@ -64,35 +66,37 @@ class Shakers : public Instrmnt
{
public:
//! Class constructor.
- Shakers();
+ Shakers( void );
//! Class destructor.
- ~Shakers();
+ ~Shakers( void );
//! Start a note with the given instrument and amplitude.
/*!
Use the instrument numbers above, converted to frequency values
as if MIDI note numbers, to select a particular instrument.
*/
- void noteOn(StkFloat instrument, StkFloat amplitude);
+ void noteOn( StkFloat instrument, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
- int setupName(char* instr);
- int setupNum(int inst);
- int setFreqAndReson(int which, StkFloat freq, StkFloat reson);
- void setDecays(StkFloat sndDecay, StkFloat sysDecay);
- void setFinalZs(StkFloat z0, StkFloat z1, StkFloat z2);
- StkFloat wuter_tick();
- StkFloat tbamb_tick();
- StkFloat ratchet_tick();
+ int setupName( char* instr );
+ int setupNum( int inst );
+ int setFreqAndReson( int which, StkFloat freq, StkFloat reson );
+ void setDecays( StkFloat sndDecay, StkFloat sysDecay );
+ void setFinalZs( StkFloat z0, StkFloat z1, StkFloat z2 );
+ StkFloat wuter_tick( void );
+ StkFloat tbamb_tick( void );
+ StkFloat ratchet_tick( void );
int instType_;
int ratchetPos_, lastRatchetPos_;
@@ -122,4 +126,6 @@ class Shakers : public Instrmnt
};
+} // stk namespace
+
#endif
diff --git a/include/Simple.h b/include/Simple.h
index 9230264..d38af25 100644
--- a/include/Simple.h
+++ b/include/Simple.h
@@ -1,3 +1,15 @@
+#ifndef STK_SIMPLE_H
+#define STK_SIMPLE_H
+
+#include "Instrmnt.h"
+#include "ADSR.h"
+#include "FileLoop.h"
+#include "OnePole.h"
+#include "BiQuad.h"
+#include "Noise.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Simple
\brief STK wavetable/noise instrument.
@@ -13,20 +25,10 @@
- Envelope Rate = 11
- Gain = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_SIMPLE_H
-#define STK_SIMPLE_H
-
-#include "Instrmnt.h"
-#include "ADSR.h"
-#include "WaveLoop.h"
-#include "OnePole.h"
-#include "BiQuad.h"
-#include "Noise.h"
-
class Simple : public Instrmnt
{
public:
@@ -34,38 +36,39 @@ class Simple : public Instrmnt
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
- Simple();
+ Simple( void );
//! Class destructor.
- ~Simple();
+ ~Simple( void );
//! Clear internal states.
- void clear();
+ void clear( void );
//! Set instrument parameters for a particular frequency.
- void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Start envelope toward "on" target.
- void keyOn();
+ void keyOn( void );
//! Start envelope toward "off" target.
- void keyOff();
+ void keyOff( void );
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
ADSR adsr_;
- WaveLoop *loop_;
+ FileLoop *loop_;
OnePole filter_;
BiQuad biquad_;
Noise noise_;
@@ -74,4 +77,16 @@ class Simple : public Instrmnt
};
+inline StkFloat Simple :: tick( unsigned int )
+{
+ lastFrame_[0] = loopGain_ * loop_->tick();
+ biquad_.tick( noise_.tick() );
+ lastFrame_[0] += (1.0 - loopGain_) * biquad_.lastOut();
+ lastFrame_[0] = filter_.tick( lastFrame_[0] );
+ lastFrame_[0] *= adsr_.tick();
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/SineWave.h b/include/SineWave.h
index ca1a0cd..cb7785f 100644
--- a/include/SineWave.h
+++ b/include/SineWave.h
@@ -1,3 +1,12 @@
+#ifndef STK_SINEWAVE_H
+#define STK_SINEWAVE_H
+
+const unsigned long TABLE_SIZE = 2048;
+
+#include "Generator.h"
+
+namespace stk {
+
/***************************************************/
/*! \class SineWave
\brief STK sinusoid oscillator class.
@@ -13,13 +22,6 @@
*/
/***************************************************/
-#ifndef STK_SINEWAVE_H
-#define STK_SINEWAVE_H
-
-const unsigned long TABLE_SIZE = 2048;
-
-#include "Generator.h"
-
class SineWave : public Generator
{
public:
@@ -27,7 +29,7 @@ public:
SineWave( void );
//! Class destructor.
- virtual ~SineWave( void );
+ ~SineWave( void );
//! Clear output and reset time pointer to zero.
void reset( void );
@@ -47,35 +49,111 @@ public:
*/
void setFrequency( StkFloat frequency );
- //! Increment the read pointer by \e time samples, modulo file size.
+ //! Increment the read pointer by \e time in samples, modulo the table size.
void addTime( StkFloat time );
- //! Increment current read pointer by \e angle, relative to a looping frequency.
+ //! Increment the read pointer by a normalized \e phase value.
/*!
- This function increments the read pointer based on the file
- size and the current Stk::sampleRate. The \e anAngle value
- is a multiple of file size.
+ This function increments the read pointer by a normalized phase
+ value, such that \e phase = 1.0 corresponds to a 360 degree phase
+ shift. Positive or negative values are possible.
*/
- void addPhase( StkFloat angle );
+ void addPhase( StkFloat phase );
- //! Add a phase offset to the current read pointer.
+ //! Add a normalized phase offset to the read pointer.
/*!
- This function determines a time offset based on the file
- size and the current Stk::sampleRate. The \e angle value
- is a multiple of file size.
+ A \e phaseOffset = 1.0 corresponds to a 360 degree phase
+ offset. Positive or negative values are possible.
*/
- void addPhaseOffset( StkFloat angle );
+ void addPhaseOffset( StkFloat phaseOffset );
+
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Compute and return one output sample.
+ StkFloat tick( void );
+
+ //! Fill a channel of the StkFrames object with computed outputs.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
static StkFrames table_;
StkFloat time_;
StkFloat rate_;
StkFloat phaseOffset_;
+ unsigned int iIndex_;
+ StkFloat alpha_;
};
+inline StkFloat SineWave :: tick( void )
+{
+ // Check limits of time address ... if necessary, recalculate modulo
+ // TABLE_SIZE.
+ while ( time_ < 0.0 )
+ time_ += TABLE_SIZE;
+ while ( time_ >= TABLE_SIZE )
+ time_ -= TABLE_SIZE;
+
+ iIndex_ = (unsigned int) time_;
+ alpha_ = time_ - iIndex_;
+ StkFloat tmp = table_[ iIndex_ ];
+ tmp += ( alpha_ * ( table_[ iIndex_ + 1 ] - tmp ) );
+
+ // Increment time, which can be negative.
+ time_ += rate_;
+
+ lastFrame_[0] = tmp;
+ return lastFrame_[0];
+}
+
+inline StkFrames& SineWave :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "SineWave::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
#endif
+
+ StkFloat *samples = &frames[channel];
+ StkFloat tmp = 0.0;
+
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i= TABLE_SIZE )
+ time_ -= TABLE_SIZE;
+
+ iIndex_ = (unsigned int) time_;
+ alpha_ = time_ - iIndex_;
+ tmp = table_[ iIndex_ ];
+ tmp += ( alpha_ * ( table_[ iIndex_ + 1 ] - tmp ) );
+ *samples = tmp;
+
+ // Increment time, which can be negative.
+ time_ += rate_;
+ }
+
+ lastFrame_[0] = tmp;
+ return frames;
+}
+
+} // stk namespace
+
+#endif
+
diff --git a/include/SingWave.h b/include/SingWave.h
index 34ff920..e330e39 100644
--- a/include/SingWave.h
+++ b/include/SingWave.h
@@ -1,79 +1,98 @@
+#ifndef STK_SINGWAVE_H
+#define STK_SINGWAVE_H
+
+#include "FileLoop.h"
+#include "Modulate.h"
+#include "Envelope.h"
+
+namespace stk {
+
/***************************************************/
/*! \class SingWave
\brief STK "singing" looped soundfile class.
- This class contains all that is needed to make
- a pitched musical sound, like a simple voice
- or violin. In general, it will not be used
- alone because of munchkinification effects
- from pitch shifting. It will be used as an
- excitation source for other instruments.
+ This class loops a specified soundfile and modulates it both
+ periodically and randomly to produce a pitched musical sound, like
+ a simple voice or violin. In general, it is not be used alone
+ because of "munchkinification" effects from pitch shifting.
+ Within STK, it is used as an excitation source for other
+ instruments.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_SINGWAVE_H
-#define STK_SINGWAVE_H
-
-#include "WaveLoop.h"
-#include "Modulate.h"
-#include "Envelope.h"
-
class SingWave : public Generator
{
public:
//! Class constructor taking filename argument.
/*!
- An StkError will be thrown if the file is not found, its format is
- unknown, a read error occurs, or the rawwave path is incorrectly set.
+ An StkError will be thrown if the file is not found, its format
+ is unknown, or a read error occurs. If the soundfile has no
+ header, the second argument should be \e true and the file data
+ will be assumed to consist of 16-bit signed integers in big-endian
+ byte order at a sample rate of 22050 Hz.
*/
- SingWave( std::string fileName, bool raw = false);
+ SingWave( std::string fileName, bool raw = false );
//! Class destructor.
- ~SingWave();
+ ~SingWave( void );
//! Reset file to beginning.
- void reset();
+ void reset( void ) { wave_.reset(); lastFrame_[0] = 0.0; };
//! Normalize the file to a maximum of +-1.0.
- void normalize();
+ void normalize( void ) { wave_.normalize(); };
//! Normalize the file to a maximum of \e +- peak.
- void normalize(StkFloat peak);
+ void normalize( StkFloat peak ) { wave_.normalize( peak ); };
- //! Set instrument parameters for a particular frequency.
- void setFrequency(StkFloat frequency);
+ //! Set looping parameters for a particular frequency.
+ void setFrequency( StkFloat frequency );
//! Set the vibrato frequency in Hz.
- void setVibratoRate(StkFloat rate);
+ void setVibratoRate( StkFloat rate ) { modulator_.setVibratoRate( rate ); };
//! Set the vibrato gain.
- void setVibratoGain(StkFloat gain);
+ void setVibratoGain( StkFloat gain ) { modulator_.setVibratoGain( gain ); };
//! Set the random-ness amount.
- void setRandomGain(StkFloat gain);
+ void setRandomGain( StkFloat gain ) { modulator_.setRandomGain( gain ); };
//! Set the sweep rate.
- void setSweepRate(StkFloat rate);
+ void setSweepRate( StkFloat rate ) { sweepRate_ = rate; };
//! Set the gain rate.
- void setGainRate(StkFloat rate);
+ void setGainRate( StkFloat rate ) { envelope_.setRate( rate ); };
//! Set the gain target value.
- void setGainTarget(StkFloat target);
+ void setGainTarget( StkFloat target ) { envelope_.setTarget( target ); };
//! Start a note.
- void noteOn();
+ void noteOn( void ) { envelope_.keyOn(); };
//! Stop a note.
- void noteOff();
+ void noteOff( void ) { envelope_.keyOff(); };
+
+ //! Return the last computed output value.
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
+
+ //! Compute and return one output sample.
+ StkFloat tick( void );
+
+ //! Fill a channel of the StkFrames object with computed outputs.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
- WaveLoop *wave_;
+ FileLoop wave_;
Modulate modulator_;
Envelope envelope_;
Envelope pitchEnvelope_;
@@ -82,4 +101,36 @@ class SingWave : public Generator
};
+inline StkFloat SingWave :: tick( void )
+{
+ // Set the wave rate.
+ StkFloat newRate = pitchEnvelope_.tick();
+ newRate += newRate * modulator_.tick();
+ wave_.setRate( newRate );
+
+ lastFrame_[0] = wave_.tick();
+ lastFrame_[0] *= envelope_.tick();
+
+ return lastFrame_[0];
+}
+
+inline StkFrames& SingWave :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "SingWave::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i
+
+namespace stk {
+
/***************************************************/
/*! \class Sitar
\brief STK sitar string model class.
@@ -13,19 +25,10 @@
Stanford, bearing the names of Karplus and/or
Strong.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_SITAR_H
-#define STK_SITAR_H
-
-#include "Instrmnt.h"
-#include "DelayA.h"
-#include "OneZero.h"
-#include "Noise.h"
-#include "ADSR.h"
-
class Sitar : public Instrmnt
{
public:
@@ -33,27 +36,28 @@ class Sitar : public Instrmnt
Sitar( StkFloat lowestFrequency = 20 );
//! Class destructor.
- ~Sitar();
+ ~Sitar( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set instrument parameters for a particular frequency.
- void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Pluck the string with the given amplitude using the current frequency.
- void pluck(StkFloat amplitude);
+ void pluck( StkFloat amplitude );
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
DelayA delayLine_;
OneZero loopFilter_;
Noise noise_;
@@ -66,5 +70,23 @@ class Sitar : public Instrmnt
};
+inline StkFloat Sitar :: tick( unsigned int )
+{
+ if ( fabs(targetDelay_ - delay_) > 0.001 ) {
+ if ( targetDelay_ < delay_ )
+ delay_ *= 0.99999;
+ else
+ delay_ *= 1.00001;
+ delayLine_.setDelay( delay_ );
+ }
+
+ lastFrame_[0] = delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ ) +
+ (amGain_ * envelope_.tick() * noise_.tick()));
+
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Skini.h b/include/Skini.h
index a7e92fe..a988c22 100644
--- a/include/Skini.h
+++ b/include/Skini.h
@@ -1,3 +1,13 @@
+#ifndef STK_SKINI_H
+#define STK_SKINI_H
+
+#include "Stk.h"
+#include
+#include
+#include
+
+namespace stk {
+
/***************************************************/
/*! \class Skini
\brief STK SKINI parsing class
@@ -21,18 +31,10 @@
\sa \ref skini
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_SKINI_H
-#define STK_SKINI_H
-
-#include "Stk.h"
-#include
-#include
-#include
-
class Skini : public Stk
{
public:
@@ -112,6 +114,8 @@ static const double Midi2Pitch[129] = {
8372.02,8869.84,9397.27,9956.06,10548.08,11175.30,11839.82,12543.85,
13289.75};
+} // stk namespace
+
#endif
diff --git a/include/Socket.h b/include/Socket.h
index fec4cde..6f59eae 100644
--- a/include/Socket.h
+++ b/include/Socket.h
@@ -1,16 +1,3 @@
-/***************************************************/
-/*! \class Socket
- \brief STK internet socket abstract base class.
-
- This class provides common functionality for TCP and UDP internet
- socket server and client subclasses. This class also provides a
- number of static functions for use with external socket
- descriptors.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
#ifndef STK_SOCKET_H
#define STK_SOCKET_H
@@ -33,6 +20,21 @@
#endif
+namespace stk {
+
+/***************************************************/
+/*! \class Socket
+ \brief STK internet socket abstract base class.
+
+ This class provides common functionality for TCP and UDP internet
+ socket server and client subclasses. This class also provides a
+ number of static functions for use with external socket
+ descriptors.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
+*/
+/***************************************************/
+
class Socket : public Stk
{
public:
@@ -52,13 +54,13 @@ class Socket : public Stk
static void close( int socket );
//! Return the socket descriptor.
- int id( void ) const;
+ int id( void ) const { return soket_; };
//! Return the socket port number.
- int port( void ) const;
+ int port( void ) const { return port_; };
//! Returns true if the socket descriptor is valid.
- static bool isValid( int socket );
+ static bool isValid( int socket ) { return socket != -1; };
//! If enable = false, the socket is set to non-blocking mode. When first created, sockets are by default in blocking mode.
static void setBlocking( int socket, bool enable );
@@ -82,4 +84,6 @@ class Socket : public Stk
};
-#endif // defined(STK_SOCKET_H)
+} // stk namespace
+
+#endif
diff --git a/include/Sphere.h b/include/Sphere.h
index d399165..246a145 100644
--- a/include/Sphere.h
+++ b/include/Sphere.h
@@ -1,3 +1,11 @@
+#ifndef STK_SPHERE_H
+#define STK_SPHERE_H
+
+#include "Stk.h"
+#include "Vector3D.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Sphere
\brief STK sphere class.
@@ -5,60 +13,51 @@
This class implements a spherical ball with
radius, mass, position, and velocity parameters.
- by Perry R. Cook, 1995 - 2004.
+ by Perry R. Cook, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_SPHERE_H
-#define STK_SPHERE_H
-
-#include "Stk.h"
-#include "Vector3D.h"
-
class Sphere : public Stk
{
public:
//! Constructor taking an initial radius value.
- Sphere(StkFloat radius = 1.0 );
-
- //! Class destructor.
- ~Sphere();
+ Sphere( StkFloat radius = 1.0 ) { radius_ = radius; mass_ = 1.0; };
//! Set the 3D center position of the sphere.
- void setPosition(StkFloat x, StkFloat y, StkFloat z);
+ void setPosition( StkFloat x, StkFloat y, StkFloat z ) { position_.setXYZ(x, y, z); };
//! Set the 3D velocity of the sphere.
- void setVelocity(StkFloat x, StkFloat y, StkFloat z);
+ void setVelocity( StkFloat x, StkFloat y, StkFloat z ) { velocity_.setXYZ(x, y, z); };
//! Set the radius of the sphere.
- void setRadius(StkFloat radius);
+ void setRadius( StkFloat radius ) { radius_ = radius; };
//! Set the mass of the sphere.
- void setMass(StkFloat mass);
+ void setMass( StkFloat mass ) { mass_ = mass; };
//! Get the current position of the sphere as a 3D vector.
- Vector3D* getPosition();
+ Vector3D* getPosition( void ) { return &position_; };
//! Get the relative position of the given point to the sphere as a 3D vector.
- Vector3D* getRelativePosition(Vector3D *position);
+ Vector3D* getRelativePosition( Vector3D *position );
//! Set the velcoity of the sphere as a 3D vector.
- StkFloat getVelocity(Vector3D* velocity);
+ StkFloat getVelocity( Vector3D* velocity );
//! Returns the distance from the sphere boundary to the given position (< 0 if inside).
- StkFloat isInside(Vector3D *position);
+ StkFloat isInside( Vector3D *position );
//! Get the current sphere radius.
- StkFloat getRadius();
+ StkFloat getRadius( void ) { return radius_; };
//! Get the current sphere mass.
- StkFloat getMass();
+ StkFloat getMass( void ) { return mass_; };
//! Increase the current sphere velocity by the given 3D components.
- void addVelocity(StkFloat x, StkFloat y, StkFloat z);
+ void addVelocity( StkFloat x, StkFloat y, StkFloat z );
//! Move the sphere for the given time increment.
- void tick(StkFloat timeIncrement);
+ void tick( StkFloat timeIncrement );
private:
Vector3D position_;
@@ -68,4 +67,13 @@ private:
StkFloat mass_;
};
+inline void Sphere::tick( StkFloat timeIncrement )
+{
+ position_.setX(position_.getX() + (timeIncrement * velocity_.getX()));
+ position_.setY(position_.getY() + (timeIncrement * velocity_.getY()));
+ position_.setZ(position_.getZ() + (timeIncrement * velocity_.getZ()));
+};
+
+} // stk namespace
+
#endif
diff --git a/include/StifKarp.h b/include/StifKarp.h
index 6f106b9..a0621d2 100644
--- a/include/StifKarp.h
+++ b/include/StifKarp.h
@@ -1,3 +1,15 @@
+#ifndef STK_STIFKARP_H
+#define STK_STIFKARP_H
+
+#include "Instrmnt.h"
+#include "DelayL.h"
+#include "DelayA.h"
+#include "OneZero.h"
+#include "Noise.h"
+#include "BiQuad.h"
+
+namespace stk {
+
/***************************************************/
/*! \class StifKarp
\brief STK plucked stiff string instrument.
@@ -17,40 +29,30 @@
- String Sustain = 11
- String Stretch = 1
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_STIFKARP_H
-#define STK_STIFKARP_H
-
-#include "Instrmnt.h"
-#include "DelayL.h"
-#include "DelayA.h"
-#include "OneZero.h"
-#include "Noise.h"
-#include "BiQuad.h"
-
class StifKarp : public Instrmnt
{
public:
//! Class constructor, taking the lowest desired playing frequency.
- StifKarp(StkFloat lowestFrequency);
+ StifKarp( StkFloat lowestFrequency );
//! Class destructor.
- ~StifKarp();
+ ~StifKarp( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set instrument parameters for a particular frequency.
- void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Set the stretch "factor" of the string (0.0 - 1.0).
- void setStretch(StkFloat stretch);
+ void setStretch( StkFloat stretch );
//! Set the pluck or "excitation" position along the string (0.0 - 1.0).
- void setPickupPosition(StkFloat position);
+ void setPickupPosition( StkFloat position );
//! Set the base loop gain.
/*!
@@ -58,24 +60,25 @@ class StifKarp : public Instrmnt
Because of high-frequency loop filter roll-off, higher
frequency settings have greater loop gains.
*/
- void setBaseLoopGain(StkFloat aGain);
+ void setBaseLoopGain( StkFloat aGain );
//! Pluck the string with the given amplitude using the current frequency.
- void pluck(StkFloat amplitude);
+ void pluck( StkFloat amplitude );
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
DelayA delayLine_;
DelayL combDelay_;
OneZero filter_;
@@ -93,4 +96,22 @@ class StifKarp : public Instrmnt
};
+inline StkFloat StifKarp :: tick( unsigned int )
+{
+ StkFloat temp = delayLine_.lastOut() * loopGain_;
+
+ // Calculate allpass stretching.
+ for (int i=0; i<4; i++)
+ temp = biquad_[i].tick(temp);
+
+ // Moving average filter.
+ temp = filter_.tick(temp);
+
+ lastFrame_[0] = delayLine_.tick(temp);
+ lastFrame_[0] = lastFrame_[0] - combDelay_.tick( lastFrame_[0] );
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Stk.h b/include/Stk.h
index 0f0fadd..3f2aa6e 100644
--- a/include/Stk.h
+++ b/include/Stk.h
@@ -1,3 +1,20 @@
+#ifndef STK_STK_H
+#define STK_STK_H
+
+#include
+#include
+#include
+#include
+#include
+
+/*! \namespace stk
+ \brief The STK namespace.
+
+ Most Stk classes are defined within the STK namespace. Exceptions
+ to this include the classes RtAudio, RtMidi, and RtError.
+*/
+namespace stk {
+
/***************************************************/
/*! \class Stk
\brief STK base class
@@ -22,7 +39,7 @@
STK WWW site: http://ccrma.stanford.edu/software/stk/
The Synthesis ToolKit in C++ (STK)
- Copyright (c) 1995-2007 Perry R. Cook and Gary P. Scavone
+ Copyright (c) 1995-2009 Perry R. Cook and Gary P. Scavone
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
@@ -50,13 +67,7 @@
*/
/***************************************************/
-#ifndef STK_STK_H
-#define STK_STK_H
-
-#include
-#include
-#include
-#include
+//#define _STK_DEBUG_
// Most data in STK is passed and calculated with the
// following user-definable floating-point type. You
@@ -129,15 +140,15 @@ public:
static const StkFormat STK_FLOAT32; /*!< Normalized between plus/minus 1.0. */
static const StkFormat STK_FLOAT64; /*!< Normalized between plus/minus 1.0. */
- //! Static method which returns the current STK sample rate.
+ //! Static method that returns the current STK sample rate.
static StkFloat sampleRate( void ) { return srate_; }
//! Static method that sets the STK sample rate.
/*!
The sample rate set using this method is queried by all STK
- classes which depend on its value. It is initialized to the
+ classes that depend on its value. It is initialized to the
default SRATE set in Stk.h. Many STK classes use the sample rate
- during instantiation. Therefore, if you wish to use a rate which
+ during instantiation. Therefore, if you wish to use a rate that
is different from the default rate, it is imperative that it be
set \e BEFORE STK objects are instantiated. A few classes that
make use of the global STK sample rate are automatically notified
@@ -160,19 +171,19 @@ public:
*/
void ignoreSampleRateChange( bool ignore = true ) { ignoreSampleRateChange_ = ignore; };
- //! Static method which returns the current rawwave path.
+ //! Static method that returns the current rawwave path.
static std::string rawwavePath(void) { return rawwavepath_; }
- //! Static method which sets the STK rawwave path.
+ //! Static method that sets the STK rawwave path.
static void setRawwavePath( std::string path );
- //! Static method which byte-swaps a 16-bit data type.
+ //! Static method that byte-swaps a 16-bit data type.
static void swap16( unsigned char *ptr );
- //! Static method which byte-swaps a 32-bit data type.
+ //! Static method that byte-swaps a 32-bit data type.
static void swap32( unsigned char *ptr );
- //! Static method which byte-swaps a 64-bit data type.
+ //! Static method that byte-swaps a 64-bit data type.
static void swap64( unsigned char *ptr );
//! Static cross-platform method to sleep for a number of milliseconds.
@@ -217,7 +228,7 @@ protected:
//! Remove class pointer from list for sample rate change notification.
void removeSampleRateAlert( Stk *ptr );
- //! Internal function for error reporting which assumes message in \c errorString_ variable.
+ //! Internal function for error reporting that assumes message in \c errorString_ variable.
void handleError( StkError::Type type );
};
@@ -226,16 +237,24 @@ protected:
/*! \class StkFrames
\brief An STK class to handle vectorized audio data.
- This class can hold single- or multi-channel audio data in either
- interleaved or non-interleaved formats. The data type is always
- StkFloat. In an effort to maintain efficiency, no out-of-bounds
- checks are performed in this class.
+ This class can hold single- or multi-channel audio data. The data
+ type is always StkFloat and the channel format is always
+ interleaved. In an effort to maintain efficiency, no
+ out-of-bounds checks are performed in this class unless
+ _STK_DEBUG_ is defined.
+
+ Internally, the data is stored in a one-dimensional C array. An
+ indexing operator is available to set and retrieve data values.
+ Alternately, one can use pointers to access the data, using the
+ index operator to get an address for a particular location in the
+ data:
+
+ StkFloat* ptr = &myStkFrames[0];
Possible future improvements in this class could include functions
- to inter- or de-interleave the data and to convert to and return
- other data types.
+ to convert to and return other data types.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
@@ -244,17 +263,23 @@ class StkFrames
public:
//! The default constructor initializes the frame data structure to size zero.
- StkFrames( unsigned int nFrames = 0, unsigned int nChannels = 0, bool interleaved = true );
+ StkFrames( unsigned int nFrames = 0, unsigned int nChannels = 0 );
//! Overloaded constructor that initializes the frame data to the specified size with \c value.
- StkFrames( const StkFloat& value, unsigned int nFrames, unsigned int nChannels, bool interleaved = true );
+ StkFrames( const StkFloat& value, unsigned int nFrames, unsigned int nChannels );
//! The destructor.
~StkFrames();
- //! Subscript operator which returns a reference to element \c n of self.
+ // A copy constructor.
+ StkFrames( const StkFrames& f );
+
+ // Assignment operator that returns a reference to self.
+ StkFrames& operator= ( const StkFrames& f );
+
+ //! Subscript operator that returns a reference to element \c n of self.
/*!
- The result can be used as an lvalue . This reference is valid
+ The result can be used as an lvalue. This reference is valid
until the resize function is called or the array is destroyed. The
index \c n must be between 0 and size less one. No range checking
is performed unless _STK_DEBUG_ is defined.
@@ -268,6 +293,22 @@ public:
*/
StkFloat operator[] ( size_t n ) const;
+ //! Assignment by sum operator into self.
+ /*!
+ The dimensions of the argument are expected to be the same as
+ self. No range checking is performed unless _STK_DEBUG_ is
+ defined.
+ */
+ void operator+= ( StkFrames& f );
+
+ //! Assignment by product operator into self.
+ /*!
+ The dimensions of the argument are expected to be the same as
+ self. No range checking is performed unless _STK_DEBUG_ is
+ defined.
+ */
+ void operator*= ( StkFrames& f );
+
//! Channel / frame subscript operator that returns a reference.
/*!
The result can be used as an lvalue. This reference is valid
@@ -341,17 +382,6 @@ public:
*/
StkFloat dataRate( void ) const { return dataRate_; };
- //! Returns \c true if the data is in interleaved format, \c false if the data is non-interleaved.
- bool interleaved( void ) const { return interleaved_; };
-
- //! Set the flag to indicate whether the internal data is in interleaved (\c true) or non-interleaved (\c false) format.
- /*!
- Note that this function does not modify the internal data order
- with respect to the argument value. It simply changes the
- indicator flag value.
- */
- void setInterleaved( bool isInterleaved ) { interleaved_ = isInterleaved; };
-
private:
StkFloat *data_;
@@ -360,10 +390,98 @@ private:
unsigned int nChannels_;
size_t size_;
size_t bufferSize_;
- bool interleaved_;
};
+inline bool StkFrames :: empty() const
+{
+ if ( size_ > 0 ) return false;
+ else return true;
+}
+
+inline StkFloat& StkFrames :: operator[] ( size_t n )
+{
+#if defined(_STK_DEBUG_)
+ if ( n >= size_ ) {
+ std::ostringstream error;
+ error << "StkFrames::operator[]: invalid index (" << n << ") value!";
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
+ }
+#endif
+
+ return data_[n];
+}
+
+inline StkFloat StkFrames :: operator[] ( size_t n ) const
+{
+#if defined(_STK_DEBUG_)
+ if ( n >= size_ ) {
+ std::ostringstream error;
+ error << "StkFrames::operator[]: invalid index (" << n << ") value!";
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
+ }
+#endif
+
+ return data_[n];
+}
+
+inline StkFloat& StkFrames :: operator() ( size_t frame, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( frame >= nFrames_ || channel >= nChannels_ ) {
+ std::ostringstream error;
+ error << "StkFrames::operator(): invalid frame (" << frame << ") or channel (" << channel << ") value!";
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
+ }
+#endif
+
+ return data_[ frame * nChannels_ + channel ];
+}
+
+inline StkFloat StkFrames :: operator() ( size_t frame, unsigned int channel ) const
+{
+#if defined(_STK_DEBUG_)
+ if ( frame >= nFrames_ || channel >= nChannels_ ) {
+ std::ostringstream error;
+ error << "StkFrames::operator(): invalid frame (" << frame << ") or channel (" << channel << ") value!";
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
+ }
+#endif
+
+ return data_[ frame * nChannels_ + channel ];
+}
+
+inline void StkFrames :: operator+= ( StkFrames& f )
+{
+#if defined(_STK_DEBUG_)
+ if ( f.frames() != nFrames_ || f.channels() != nChannels_ ) {
+ std::ostringstream error;
+ error << "StkFrames::operator+=: frames argument must be of equal dimensions!";
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
+ }
+#endif
+
+ StkFloat *fptr = &f[0];
+ StkFloat *dptr = data_;
+ for ( unsigned int i=0; i taps = std::vector( 1, 0 ), unsigned long maxDelay = 4095 );
+
+ //! Class destructor.
+ ~TapDelay();
+
+ //! Set the maximum delay-line length.
+ /*!
+ This method should generally only be used during initial setup
+ of the delay line. If it is used between calls to the tick()
+ function, without a call to clear(), a signal discontinuity will
+ likely occur. If the current maximum length is greater than the
+ new length, no change will be made.
+ */
+ void setMaximumDelay( unsigned long delay );
+
+ //! Set the delay-line tap lengths.
+ /*!
+ The valid range for each tap length is from 0 to the maximum delay-line length.
+ */
+ void setTapDelays( std::vector taps );
+
+ //! Return the current delay-line length.
+ std::vector getTapDelays( void ) const { return delays_; };
+
+ //! Return the specified tap value of the last computed frame.
+ /*!
+ Use the lastFrame() function to get all tap values from the
+ last computed frame. The \c tap argument must be less than the
+ number of delayline taps (the first tap 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.
+ */
+ StkFloat lastOut( unsigned int tap = 0 ) const;
+
+ //! Input one sample to the delayline and return outputs at all tap positions.
+ /*!
+ The StkFrames argument reference is returned. The output
+ values are ordered according to the tap positions set using the
+ setTapDelays() function (no sorting is performed). The StkFrames
+ argument must contain at least as many channels as the number of
+ taps. 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.
+ */
+ StkFrames& tick( StkFloat input, StkFrames& outputs );
+
+ //! Take a channel of the StkFrames object as inputs to the filter and write outputs back to the same object.
+ /*!
+ The StkFrames argument reference is returned. The output
+ values are ordered according to the tap positions set using the
+ setTapDelays() function (no sorting is performed). The StkFrames
+ argument must contain at least as many channels as the number of
+ taps. 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.
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+ //! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
+ /*!
+ The \c iFrames object reference is returned. The output values
+ are ordered according to the tap positions set using the
+ setTapDelays() function (no sorting is performed). The \c
+ iChannel argument must be less than the number of channels in
+ the \c iFrames argument (the first channel is specified by 0).
+ The \c oFrames argument must contain at least as many channels as
+ the number of taps. 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.
+ */
+ StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0 );
+
+ protected:
+
+ unsigned long inPoint_;
+ std::vector outPoint_;
+ std::vector delays_;
+
+};
+
+inline StkFloat TapDelay :: lastOut( unsigned int tap ) const
+{
+#if defined(_STK_DEBUG_)
+ if ( tap >= lastFrame_.size() ) ) {
+ errorString_ << "TapDelay::lastOut(): tap argument and number of taps are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ return lastFrame_[tap];
+}
+
+inline StkFrames& TapDelay :: tick( StkFloat input, StkFrames& outputs )
+{
+#if defined(_STK_DEBUG_)
+ if ( outputs.channels() < outPoint_.size() ) {
+ errorString_ << "TapDelay::tick(): number of taps > channels in StkFrames argument!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ inputs_[inPoint_++] = input * gain_;
+
+ // Check for end condition
+ if ( inPoint_ == inputs_.size() )
+ inPoint_ = 0;
+
+ // Read out next values
+ StkFloat *outs = &outputs[0];
+ for ( unsigned int i=0; i= frames.channels() ) {
+ errorString_ << "TapDelay::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+ if ( frames.channels() < outPoint_.size() ) {
+ errorString_ << "TapDelay::tick(): number of taps > channels in StkFrames argument!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &frames[channel];
+ StkFloat *oSamples = &frames[0];
+ unsigned int j, iHop = frames.channels(), oHop = frames.channels() - outPoint_.size();
+ for ( unsigned int i=0; i= iFrames.channels() ) {
+ errorString_ << "TapDelay::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+ if ( oFrames.channels() < outPoint_.size() ) {
+ errorString_ << "TapDelay::tick(): number of taps > channels in output StkFrames argument!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[0];
+ unsigned int j, iHop = iFrames.channels(), oHop = oFrames.channels() - outPoint_.size();
+ for ( unsigned int i=0; itick() * waves_[1]->tick();
+ temp = temp * control1_;
+
+ waves_[0]->addPhaseOffset( temp );
+ waves_[3]->addPhaseOffset( twozero_.lastOut() );
+ temp = gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
+ twozero_.tick( temp );
+
+ waves_[2]->addPhaseOffset( temp );
+ temp = ( 1.0 - (control2_ * 0.5)) * gains_[0] * adsr_[0]->tick() * waves_[0]->tick();
+ temp += control2_ * 0.5 * gains_[2] * adsr_[2]->tick() * waves_[2]->tick();
+
+ // Calculate amplitude modulation and apply it to output.
+ temp2 = vibrato_.tick() * modDepth_;
+ temp = temp * (1.0 + temp2);
+
+ lastFrame_[0] = temp * 0.5;
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/TwoPole.h b/include/TwoPole.h
index b8060ea..f5ab03d 100644
--- a/include/TwoPole.h
+++ b/include/TwoPole.h
@@ -1,28 +1,28 @@
-/***************************************************/
-/*! \class TwoPole
- \brief STK two-pole filter class.
-
- This protected Filter subclass implements
- a two-pole digital filter. A method is
- provided for creating a resonance in the
- frequency response while maintaining a nearly
- constant filter gain.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
#ifndef STK_TWOPOLE_H
#define STK_TWOPOLE_H
#include "Filter.h"
-class TwoPole : protected Filter
+namespace stk {
+
+/***************************************************/
+/*! \class TwoPole
+ \brief STK two-pole filter class.
+
+ This class implements a two-pole digital filter. A method is
+ provided for creating a resonance in the frequency response while
+ maintaining a nearly constant filter gain.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
+*/
+/***************************************************/
+
+class TwoPole : public Filter
{
public:
//! Default constructor creates a second-order pass-through filter.
- TwoPole();
+ TwoPole( void );
//! Class destructor.
~TwoPole();
@@ -30,17 +30,17 @@ class TwoPole : protected Filter
//! A function to enable/disable the automatic updating of class data when the STK sample rate changes.
void ignoreSampleRateChange( bool ignore = true ) { ignoreSampleRateChange_ = ignore; };
- //! Clears the internal states of the filter.
- void clear(void);
-
//! Set the b[0] coefficient value.
- void setB0(StkFloat b0);
+ void setB0( StkFloat b0 ) { b_[0] = b0; };
//! Set the a[1] coefficient value.
- void setA1(StkFloat a1);
+ void setA1( StkFloat a1 ) { a_[1] = a1; };
//! Set the a[2] coefficient value.
- void setA2(StkFloat a2);
+ void setA2( StkFloat a2 ) { a_[2] = a2; };
+
+ //! Set all filter coefficients.
+ void setCoefficients( StkFloat b0, StkFloat a1, StkFloat a2, bool clearState = false );
//! Sets the filter coefficients for a resonance at \e frequency (in Hz).
/*!
@@ -58,34 +58,94 @@ class TwoPole : protected Filter
*/
void setResonance(StkFloat frequency, StkFloat radius, bool normalize = false);
- //! Set the filter gain.
- /*!
- The gain is applied at the filter input and does not affect the
- coefficient values. The default gain value is 1.0.
- */
- void setGain(StkFloat gain);
-
- //! Return the current filter gain.
- StkFloat getGain(void) const;
-
//! Return the last computed output value.
- StkFloat lastOut(void) const;
+ StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Input one sample to the filter and return one output.
- StkFloat tick(StkFloat sample);
+ StkFloat tick( StkFloat input );
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
- The \c channel argument should be zero or greater (the first
- channel is specified by 0). An StkError will be thrown if the \c
- channel argument is equal to or greater than the number of
- channels in the StkFrames object.
+ The StkFrames argument reference is returned. The \c 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.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+ //! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
+ /*!
+ The \c 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.
+ */
+ StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
+
protected:
virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
};
+inline StkFloat TwoPole :: tick( StkFloat input )
+{
+ inputs_[0] = gain_ * input;
+ lastFrame_[0] = b_[0] * inputs_[0] - a_[1] * outputs_[1] - a_[2] * outputs_[2];
+ outputs_[2] = outputs_[1];
+ outputs_[1] = lastFrame_[0];
+
+ return lastFrame_[0];
+}
+
+inline StkFrames& TwoPole :: tick( StkFrames& frames, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= frames.channels() ) {
+ errorString_ << "TwoPole::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "TwoPole::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i= frames.channels() ) {
+ errorString_ << "TwoZero::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int hop = frames.channels();
+ for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() ) {
+ errorString_ << "TwoZero::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *iSamples = &iFrames[iChannel];
+ StkFloat *oSamples = &oFrames[oChannel];
+ unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
+ for ( unsigned int i=0; i
+
+namespace stk {
+
/***************************************************/
/*! \class Vector3D
\brief STK 3D vector class.
This class implements a three-dimensional vector.
- by Perry R. Cook, 1995 - 2004.
+ by Perry R. Cook, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_VECTOR3D_H
-#define STK_VECTOR3D_H
-
-#include "Stk.h"
-
class Vector3D : public Stk
{
public:
//! Default constructor taking optional initial X, Y, and Z values.
- Vector3D(StkFloat initX=0.0, StkFloat initY=0.0, StkFloat initZ=0.0);
-
- //! Class destructor.
- ~Vector3D();
+ Vector3D( StkFloat x = 0.0, StkFloat y = 0.0, StkFloat z = 0.0 ) { setXYZ( x, y, z ); };
//! Get the current X value.
- StkFloat getX();
+ StkFloat getX( void ) { return X_; };
//! Get the current Y value.
- StkFloat getY();
+ StkFloat getY( void ) { return Y_; };
//! Get the current Z value.
- StkFloat getZ();
+ StkFloat getZ( void ) { return Z_; };
//! Calculate the vector length.
- StkFloat getLength();
+ StkFloat getLength( void );
//! Set the X, Y, and Z values simultaniously.
- void setXYZ(StkFloat x, StkFloat y, StkFloat z);
+ void setXYZ( StkFloat x, StkFloat y, StkFloat z ) { X_ = x; Y_ = y; Z_ = z; };
//! Set the X value.
- void setX(StkFloat x);
+ void setX( StkFloat x ) { X_ = x; };
//! Set the Y value.
- void setY(StkFloat y);
+ void setY( StkFloat y ) { Y_ = y; };
//! Set the Z value.
- void setZ(StkFloat z);
+ void setZ( StkFloat z ) { Z_ = z; };
protected:
- StkFloat myX_;
- StkFloat myY_;
- StkFloat myZ_;
+ StkFloat X_;
+ StkFloat Y_;
+ StkFloat Z_;
};
+inline StkFloat Vector3D :: getLength( void )
+{
+ StkFloat temp;
+ temp = X_ * X_;
+ temp += Y_ * Y_;
+ temp += Z_ * Z_;
+ temp = sqrt( temp );
+ return temp;
+}
+
+} // stk namespace
+
#endif
diff --git a/include/VoicForm.h b/include/VoicForm.h
index 41f47b0..5653589 100644
--- a/include/VoicForm.h
+++ b/include/VoicForm.h
@@ -1,3 +1,16 @@
+#ifndef STK_VOICFORM_H
+#define STK_VOICFORM_H
+
+#include "Instrmnt.h"
+#include "Envelope.h"
+#include "Noise.h"
+#include "SingWave.h"
+#include "FormSwep.h"
+#include "OnePole.h"
+#include "OneZero.h"
+
+namespace stk {
+
/***************************************************/
/*! \class VoicForm
\brief Four formant synthesis instrument.
@@ -21,21 +34,10 @@
- Vibrato Gain = 1
- Loudness (Spectral Tilt) = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_VOICFORM_H
-#define STK_VOICFORM_H
-
-#include "Instrmnt.h"
-#include "Envelope.h"
-#include "Noise.h"
-#include "SingWave.h"
-#include "FormSwep.h"
-#include "OnePole.h"
-#include "OneZero.h"
-
class VoicForm : public Instrmnt
{
public:
@@ -43,51 +45,52 @@ class VoicForm : public Instrmnt
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
- VoicForm();
+ VoicForm( void );
//! Class destructor.
- ~VoicForm();
+ ~VoicForm( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set instrument parameters for a particular frequency.
- void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Set instrument parameters for the given phoneme. Returns false if phoneme not found.
- bool setPhoneme(const char* phoneme);
+ bool setPhoneme( const char* phoneme );
//! Set the voiced component gain.
- void setVoiced(StkFloat vGain);
+ void setVoiced( StkFloat vGain ) { voiced_->setGainTarget(vGain); };
//! Set the unvoiced component gain.
- void setUnVoiced(StkFloat nGain);
+ void setUnVoiced( StkFloat nGain ) { noiseEnv_.setTarget(nGain); };
//! Set the sweep rate for a particular formant filter (0-3).
- void setFilterSweepRate(unsigned int whichOne, StkFloat rate);
+ void setFilterSweepRate( unsigned int whichOne, StkFloat rate );
//! Set voiced component pitch sweep rate.
- void setPitchSweepRate(StkFloat rate);
+ void setPitchSweepRate( StkFloat rate ) { voiced_->setSweepRate(rate); };
//! Start the voice.
- void speak();
+ void speak( void ) { voiced_->noteOn(); };
//! Stop the voice.
- void quiet();
+ void quiet( void );
//! Start a note with the given frequency and amplitude.
- void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude ) { this->quiet(); };
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
- void controlChange(int number, StkFloat value);
+ void controlChange( int number, StkFloat value );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
SingWave *voiced_;
Noise noise_;
Envelope noiseEnv_;
@@ -97,4 +100,25 @@ protected:
};
+inline StkFloat VoicForm :: tick( unsigned int )
+{
+ StkFloat temp;
+ temp = onepole_.tick( onezero_.tick( voiced_->tick() ) );
+ temp += noiseEnv_.tick() * noise_.tick();
+ lastFrame_[0] = filters_[0].tick(temp);
+ lastFrame_[0] += filters_[1].tick(temp);
+ lastFrame_[0] += filters_[2].tick(temp);
+ lastFrame_[0] += filters_[3].tick(temp);
+ /*
+ temp += noiseEnv_.tick() * noise_.tick();
+ lastFrame_[0] = filters_[0].tick(temp);
+ lastFrame_[0] = filters_[1].tick(lastFrame_[0]);
+ lastFrame_[0] = filters_[2].tick(lastFrame_[0]);
+ lastFrame_[0] = filters_[3].tick(lastFrame_[0]);
+ */
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/Voicer.h b/include/Voicer.h
index ba404a4..5a4fd2a 100644
--- a/include/Voicer.h
+++ b/include/Voicer.h
@@ -1,80 +1,73 @@
-/***************************************************/
-/*! \class Voicer
- \brief STK voice manager class.
-
- This class can be used to manage a group of
- STK instrument classes. Individual voices can
- be controlled via unique note tags.
- Instrument groups can be controlled by channel
- number.
-
- A previously constructed STK instrument class
- is linked with a voice manager using the
- addInstrument() function. An optional channel
- number argument can be specified to the
- addInstrument() function as well (default
- channel = 0). The voice manager does not
- delete any instrument instances ... it is the
- responsibility of the user to allocate and
- deallocate all instruments.
-
- The tick() function returns the mix of all
- sounding voices. Each noteOn returns a unique
- tag (credits to the NeXT MusicKit), so you can
- send control changes to specific voices within
- an ensemble. Alternately, control changes can
- be sent to all voices on a given channel.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
#ifndef STK_VOICER_H
#define STK_VOICER_H
#include "Instrmnt.h"
#include
+namespace stk {
+
+/***************************************************/
+/*! \class Voicer
+ \brief STK voice manager class.
+
+ This class can be used to manage a group of STK instrument
+ classes. Individual voices can be controlled via unique note
+ tags. Instrument groups can be controlled by group number.
+
+ A previously constructed STK instrument class is linked with a
+ voice manager using the addInstrument() function. An optional
+ group number argument can be specified to the addInstrument()
+ function as well (default group = 0). The voice manager does not
+ delete any instrument instances ... it is the responsibility of
+ the user to allocate and deallocate all instruments.
+
+ The tick() function returns the mix of all sounding voices. Each
+ noteOn returns a unique tag (credits to the NeXT MusicKit), so you
+ can send control changes to specific voices within an ensemble.
+ Alternately, control changes can be sent to all voices in a given
+ group.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
+*/
+/***************************************************/
+
class Voicer : public Stk
{
-public:
+ public:
//! Class constructor taking an optional note decay time (in seconds).
- Voicer( StkFloat decayTime=0.2 );
+ Voicer( StkFloat decayTime = 0.2 );
- //! Class destructor.
- ~Voicer();
-
- //! Add an instrument with an optional channel number to the voice manager.
+ //! Add an instrument with an optional group number to the voice manager.
/*!
- A set of instruments can be grouped by channel number and
- controlled via the functions which take a channel number argument.
+ A set of instruments can be grouped by group number and
+ controlled via the functions that take a group number argument.
*/
- void addInstrument( Instrmnt *instrument, int channel=0 );
+ void addInstrument( Instrmnt *instrument, int group=0 );
//! Remove the given instrument pointer from the voice manager's control.
/*!
It is important that any instruments which are to be deleted by
the user while the voice manager is running be first removed from
the manager's control via this function!!
- */
+ */
void removeInstrument( Instrmnt *instrument );
//! Initiate a noteOn event with the given note number and amplitude and return a unique note tag.
/*!
Send the noteOn message to the first available unused voice.
If all voices are sounding, the oldest voice is interrupted and
- sent the noteOn message. If the optional channel argument is
- non-zero, only voices on that channel are used. If no voices are
- found for a specified non-zero channel value, the function returns
+ sent the noteOn message. If the optional group argument is
+ non-zero, only voices in that group are used. If no voices are
+ found for a specified non-zero group value, the function returns
-1. The amplitude value should be in the range 0.0 - 128.0.
*/
- long noteOn( StkFloat noteNumber, StkFloat amplitude, int channel=0 );
+ long noteOn( StkFloat noteNumber, StkFloat amplitude, int group=0 );
- //! Send a noteOff to all voices having the given noteNumber and optional channel (default channel = 0).
+ //! Send a noteOff to all voices having the given noteNumber and optional group (default group = 0).
/*!
The amplitude value should be in the range 0.0 - 128.0.
*/
- void noteOff( StkFloat noteNumber, StkFloat amplitude, int channel=0 );
+ void noteOff( StkFloat noteNumber, StkFloat amplitude, int group=0 );
//! Send a noteOff to the voice with the given note tag.
/*!
@@ -82,26 +75,26 @@ public:
*/
void noteOff( long tag, StkFloat amplitude );
- //! Send a frequency update message to all voices assigned to the optional channel argument (default channel = 0).
+ //! Send a frequency update message to all voices assigned to the optional group argument (default group = 0).
/*!
The \e noteNumber argument corresponds to a MIDI note number, though it is a floating-point value and can range beyond the normal 0-127 range.
- */
- void setFrequency( StkFloat noteNumber, int channel=0 );
+ */
+ void setFrequency( StkFloat noteNumber, int group=0 );
//! Send a frequency update message to the voice with the given note tag.
/*!
The \e noteNumber argument corresponds to a MIDI note number, though it is a floating-point value and can range beyond the normal 0-127 range.
- */
+ */
void setFrequency( long tag, StkFloat noteNumber );
- //! Send a pitchBend message to all voices assigned to the optional channel argument (default channel = 0).
- void pitchBend( StkFloat value, int channel=0 );
+ //! Send a pitchBend message to all voices assigned to the optional group argument (default group = 0).
+ void pitchBend( StkFloat value, int group=0 );
//! Send a pitchBend message to the voice with the given note tag.
void pitchBend( long tag, StkFloat value );
- //! Send a controlChange to all instruments assigned to the optional channel argument (default channel = 0).
- void controlChange( int number, StkFloat value, int channel=0 );
+ //! Send a controlChange to all instruments assigned to the optional group argument (default group = 0).
+ void controlChange( int number, StkFloat value, int group=0 );
//! Send a controlChange to the voice with the given note tag.
void controlChange( long tag, int number, StkFloat value );
@@ -109,31 +102,46 @@ public:
//! Send a noteOff message to all existing voices.
void silence( void );
- //! Mix the output for all sounding voices.
- StkFloat tick();
+ //! Return the current number of output channels.
+ unsigned int channelsOut( void ) const { return lastFrame_.channels(); };
- //! Compute \e vectorSize output mixes and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
+ //! Return an StkFrames reference to the last output sample frame.
+ const StkFrames& lastFrame( void ) const { return lastFrame_; };
- //! Fill a channel of the StkFrames object with computed outputs.
+ //! Return the specified channel value of the last computed frame.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
+ The \c channel argument must be less than the number of output
+ channels, which can be determined with the channelsOut() function
+ (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. \sa lastFrame()
*/
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFloat lastOut( unsigned int channel = 0 );
- //! Return the last output value.
- StkFloat lastOut() const;
+ //! Mix one sample frame of all sounding voices and return the specified \c channel value.
+ /*!
+ The \c channel argument must be less than the number of output
+ channels, which can be determined with the channelsOut() function
+ (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.
+ */
+ StkFloat tick( unsigned int channel = 0 );
- //! Return the last left output value.
- StkFloat lastOutLeft() const;
+ //! Fill the StkFrames argument with computed frames and return the same reference.
+ /*!
+ The number of channels in the StkFrames argument must equal
+ the number of channels in the file data. However, this is only
+ checked if _STK_DEBUG_ is defined during compilation, in which
+ case an incompatibility will trigger an StkError exception. If no
+ file data is loaded, the function does nothing (a warning will be
+ issued if _STK_DEBUG_ is defined during compilation).
+ */
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
- //! Return the last right output value.
- StkFloat lastOutRight() const;
-
-protected:
+ protected:
struct Voice {
Instrmnt *instrument;
@@ -141,20 +149,72 @@ protected:
StkFloat noteNumber;
StkFloat frequency;
int sounding;
- int channel;
+ int group;
// Default constructor.
Voice()
- :instrument(0), tag(0), noteNumber(-1.0), frequency(0.0),
- sounding(0), channel(0) {}
+ :instrument(0), tag(0), noteNumber(-1.0), frequency(0.0), sounding(0), group(0) {}
};
std::vector voices_;
long tags_;
int muteTime_;
- StkFloat lastOutput_;
- StkFloat lastOutputLeft_;
- StkFloat lastOutputRight_;
+ StkFrames lastFrame_;
};
+inline StkFloat Voicer :: lastOut( unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( channel >= lastFrame_.channels() ) {
+ errorString_ << "Voicer::lastOut(): channel argument is invalid!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ return lastFrame_[channel];
+}
+
+
+inline StkFloat Voicer :: tick( unsigned int channel )
+{
+ unsigned int j;
+ for ( j=0; jtick();
+ for ( j=0; jchannelsOut(); j++ ) lastFrame_[j] += voices_[i].instrument->lastOut( j );
+ }
+ if ( voices_[i].sounding < 0 ) {
+ voices_[i].sounding++;
+ if ( voices_[i].sounding == 0 )
+ voices_[i].noteNumber = -1;
+ }
+ }
+
+ return lastFrame_[channel];
+}
+
+inline StkFrames& Voicer :: tick( StkFrames& frames, unsigned int channel )
+{
+ unsigned int nChannels = lastFrame_.channels();
+#if defined(_STK_DEBUG_)
+ if ( channel > frames.channels() - nChannels ) {
+ errorString_ << "Voicer::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
+ StkFloat *samples = &frames[channel];
+ unsigned int j, hop = frames.channels() - nChannels;
+ for ( unsigned int i=0; itick() * waves_[1]->tick();
+ temp = temp * control1_;
+
+ waves_[0]->addPhaseOffset( temp );
+ waves_[3]->addPhaseOffset( twozero_.lastOut() );
+ temp = gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
+ twozero_.tick(temp);
+
+ waves_[2]->addPhaseOffset( temp );
+ temp = ( 1.0 - (control2_ * 0.5)) * gains_[0] * adsr_[0]->tick() * waves_[0]->tick();
+ temp += control2_ * 0.5 * gains_[2] * adsr_[2]->tick() * waves_[2]->tick();
+
+ // Calculate amplitude modulation and apply it to output.
+ temp2 = vibrato_.tick() * modDepth_;
+ temp = temp * (1.0 + temp2);
+
+ lastFrame_[0] = temp * 0.5;
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/include/WvIn.h b/include/WvIn.h
index 7722b80..651bbc2 100644
--- a/include/WvIn.h
+++ b/include/WvIn.h
@@ -1,3 +1,10 @@
+#ifndef STK_WVIN_H
+#define STK_WVIN_H
+
+#include "Stk.h"
+
+namespace stk {
+
/***************************************************/
/*! \class WvIn
\brief STK audio input abstract base class.
@@ -5,83 +12,32 @@
This class provides common functionality for a variety of audio
data input subclasses.
- WvIn supports multi-channel data. It is important to distinguish
- the tick() methods, which return samples produced by averaging
- across sample frames, from the tickFrame() methods, which return
- references or pointers to multi-channel sample frames.
-
- Both interleaved and non-interleaved data is supported via the use
- of StkFrames objects.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_WVIN_H
-#define STK_WVIN_H
-
-#include "Stk.h"
-#include
-
class WvIn : public Stk
{
public:
- //! Default constructor.
- WvIn();
+ //! Return the number of audio channels in the data or stream.
+ unsigned int channelsOut( void ) const { return data_.channels(); };
- //! Class destructor.
- virtual ~WvIn();
-
- //! Return the number of audio channels in the data.
- unsigned int getChannels( void ) const { return data_.channels(); };
-
- //! Return the average across the last output sample frame.
- /*!
- If no file data is loaded, the returned value is 0.0.
- */
- StkFloat lastOut( void ) const;
-
- //! Return an StkFrames reference to the last output sample frame.
+ //! Return an StkFrames reference to the last computed sample frame.
/*!
If no file data is loaded, an empty container is returned.
*/
- const StkFrames& lastFrame( void ) const { return lastOutputs_; };
+ const StkFrames& lastFrame( void ) const { return lastFrame_; };
- //! Read out the average across one sample frame of data.
- /*!
- If no file data is loaded, the returned value is 0.0.
- */
- StkFloat tick( void );
-
- //! Fill a channel of the StkFrames object with averaged sample frames.
- /*!
- The \c channel argument should be zero or greater (the first
- channel is specified by 0). An StkError will be thrown if the \c
- channel argument is greater than or equal to the number of
- channels in the StkFrames object. If no file data is loaded, the
- container is filled with zeroes.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
-
- //! Fill the StkFrames argument with data and return the same reference.
- /*!
- An StkError will be thrown if there is an incompatability
- between the number of channels in the loaded data and that in the
- StkFrames argument. If no file data is loaded, the container is
- filled with zeroes.
- */
- StkFrames& tickFrame( StkFrames& frames );
+ //! Compute one sample frame and return the specified \c channel value.
+ virtual StkFloat tick( unsigned int channel = 0 ) = 0;
protected:
- // This abstract function must be implemented in all subclasses.
- // It is used to get around a C++ problem with overloaded virtual
- // functions.
- virtual void computeFrame( void ) = 0;
-
StkFrames data_;
- StkFrames lastOutputs_;
+ StkFrames lastFrame_;
};
+} // stk namespace
+
#endif
diff --git a/include/WvOut.h b/include/WvOut.h
index d2b4820..1339319 100644
--- a/include/WvOut.h
+++ b/include/WvOut.h
@@ -1,3 +1,10 @@
+#ifndef STK_WVOUT_H
+#define STK_WVOUT_H
+
+#include "Stk.h"
+
+namespace stk {
+
/***************************************************/
/*! \class WvOut
\brief STK audio output abstract base class.
@@ -5,42 +12,25 @@
This class provides common functionality for a variety of audio
data output subclasses.
- WvOut supports multi-channel data. It is important to distinguish
- the tick() methods, which output single samples to all channels in
- a sample frame, from the tickFrame() methods, which take a pointer
- or reference to multi-channel sample frame data.
-
- Both interleaved and non-interleaved data is supported via the use
- of StkFrames objects.
-
Currently, WvOut is non-interpolating and the output rate is
always Stk::sampleRate().
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_WVOUT_H
-#define STK_WVOUT_H
-
-#include "Stk.h"
-#include
-
class WvOut : public Stk
{
public:
//! Default constructor.
- WvOut();
-
- //! Class destructor.
- virtual ~WvOut();
+ WvOut( void ) : frameCounter_(0), clipping_(false) {};
//! Return the number of sample frames output.
- unsigned long getFrameCount( void ) const;
+ unsigned long getFrameCount( void ) const { return frameCounter_; };
//! Return the number of seconds of data output.
- StkFloat getTime( void ) const;
+ StkFloat getTime( void ) const { return (StkFloat) frameCounter_ / Stk::sampleRate(); };
//! Returns \c true if clipping has been detected during output since instantiation or the last reset.
bool clipStatus( void ) { return clipping_; };
@@ -52,34 +42,10 @@ class WvOut : public Stk
/*!
An StkError is thrown if an output error occurs.
*/
- void tick( const StkFloat sample );
-
- //! Output a channel of the StkFrames object to all channels of the WvOut object.
- /*!
- The \c channel argument should be 0 or greater (the first
- channel is specified by 0). An StkError will be thrown if an
- output error occurs or if the \c channel argument is equal to or
- greater than the number of channels in the StkFrames object.
- */
- void tick( const StkFrames& frames, unsigned int channel = 0 );
-
- //! Output the StkFrames data.
- /*!
- An StkError will be thrown if an output error occurs or if
- there is an incompatability between the number of channels in the
- WvOut object and that in the StkFrames object.
- */
- void tickFrame( const StkFrames& frames );
+ virtual void tick( const StkFloat sample ) = 0;
protected:
- // These abstract functions must be implemented in all subclasses.
- // They are used to get around a C++ problem with overloaded virtual
- // functions.
- virtual void computeSample( const StkFloat sample ) = 0;
-
- virtual void computeFrames( const StkFrames& frames ) = 0;
-
// Check for sample clipping and clamp.
StkFloat& clipTest( StkFloat& sample );
@@ -89,4 +55,28 @@ class WvOut : public Stk
};
+inline StkFloat& WvOut :: clipTest( StkFloat& sample )
+{
+ bool clip = false;
+ if ( sample > 1.0 ) {
+ sample = 1.0;
+ clip = true;
+ }
+ else if ( sample < -1.0 ) {
+ sample = -1.0;
+ clip = true;
+ }
+
+ if ( clip == true && clipping_ == false ) {
+ // First occurrence of clipping since instantiation or reset.
+ clipping_ = true;
+ errorString_ << "WvOut: data value(s) outside +-1.0 detected ... clamping at outer bound!";
+ handleError( StkError::WARNING );
+ }
+
+ return sample;
+}
+
+} // stk namespace
+
#endif
diff --git a/projects/demo/Makefile.in b/projects/demo/Makefile.in
index 31af87a..ffb8448 100644
--- a/projects/demo/Makefile.in
+++ b/projects/demo/Makefile.in
@@ -7,16 +7,16 @@ SRC_PATH = ../../src
OBJECT_PATH = @object_path@
vpath %.o $(OBJECT_PATH)
-OBJECTS = Stk.o Generator.o Noise.o SubNoise.o Envelope.o ADSR.o \
+OBJECTS = Stk.o Noise.o Envelope.o ADSR.o \
Modulate.o SingWave.o SineWave.o FileRead.o FileWrite.o \
- WvIn.o FileWvIn.o WaveLoop.o WvOut.o FileWvOut.o \
- Filter.o OneZero.o OnePole.o PoleZero.o TwoZero.o \
+ FileWvIn.o FileLoop.o FileWvOut.o \
+ OneZero.o OnePole.o PoleZero.o TwoZero.o \
BiQuad.o FormSwep.o Delay.o DelayL.o DelayA.o \
- Function.o ReedTable.o JetTable.o BowTable.o \
- Effect.o PRCRev.o \
+ ReedTable.o JetTable.o BowTable.o \
+ PRCRev.o \
Voicer.o Vector3D.o Sphere.o \
\
- Instrmnt.o Clarinet.o BlowHole.o Saxofony.o Flute.o Brass.o BlowBotl.o \
+ Clarinet.o BlowHole.o Saxofony.o Flute.o Brass.o BlowBotl.o \
Bowed.o Plucked.o StifKarp.o Sitar.o PluckTwo.o Mandolin.o Mesh2D.o \
FM.o Rhodey.o Wurley.o TubeBell.o HevyMetl.o PercFlut.o BeeThree.o FMVoices.o \
Sampler.o Moog.o Simple.o Drummer.o Shakers.o \
@@ -31,18 +31,16 @@ endif
vpath %.h $(INCLUDE)
CC = @CXX@
-DEFS = @byte_order@
-DEFS += @debug@
-CFLAGS = @cflags@
-CFLAGS += @warn@ -I$(INCLUDE) -I../../src/include
+DEFS = @CPPFLAGS@
+DEFS += @byte_order@
+CFLAGS = @CXXFLAGS@
+CFLAGS += -I$(INCLUDE) -I$(INCLUDE)/../src/include
LIBRARY = @LIBS@
-LIBRARY += @frameworks@
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
PROGRAMS += demo
OBJECTS += RtMidi.o RtAudio.o Thread.o Mutex.o Socket.o TcpServer.o @objects@
- DEFS += @audio_apis@
endif
RAWWAVES = @rawwaves@
@@ -76,6 +74,7 @@ $(OBJECTS) : Stk.h
clean :
-rm $(OBJECT_PATH)/*.o
-rm $(PROGRAMS) *.exe
+ -rm -fR *~ *.dSYM
strip :
strip $(PROGRAMS)
diff --git a/projects/demo/Md2Skini.cpp b/projects/demo/Md2Skini.cpp
index 41c4f14..5062685 100644
--- a/projects/demo/Md2Skini.cpp
+++ b/projects/demo/Md2Skini.cpp
@@ -12,9 +12,8 @@
#include "RtMidi.h"
#include "SKINI.msg"
-#include
#include
-#include
+#include
void usage(void) {
std::cout << "\nuseage: Md2Skini \n\n";
@@ -161,6 +160,8 @@ void midiCallback( double deltatime, std::vector< unsigned char > *bytes, void *
if ( file != NULL )
fprintf( file, "%s %.3f %d %.1f %.1f\n", typeName.c_str(), deltatime, channel, (float)databyte1, (float)databyte2 );
}
+
+ fflush( stdout );
}
int main( int argc,char *argv[] )
diff --git a/projects/demo/demo.cpp b/projects/demo/demo.cpp
index b048dee..f7bcd63 100644
--- a/projects/demo/demo.cpp
+++ b/projects/demo/demo.cpp
@@ -28,13 +28,15 @@ using std::min;
bool done;
static void finish(int ignore){ done = true; }
+using namespace stk;
+
// The TickData structure holds all the class instances and data that
// are shared by the various processing functions.
struct TickData {
WvOut **wvout;
Instrmnt **instrument;
Voicer *voicer;
- Effect *reverb;
+ PRCRev reverb;
Messager messager;
Skini::Message message;
StkFloat volume;
@@ -51,7 +53,7 @@ struct TickData {
// Default constructor.
TickData()
- : wvout(0), instrument(0), voicer(0), reverb(0), volume(1.0), t60(1.0),
+ : wvout(0), instrument(0), voicer(0), volume(1.0), t60(1.0),
nWvOuts(0), nVoices(1), currentVoice(0), channels(2), counter(0),
realtime( false ), settling( false ), haveMessage( false ) {}
};
@@ -90,7 +92,7 @@ void processMessage( TickData* data )
case __SK_ControlChange_:
if (value1 == 44.0)
- data->reverb->setEffectMix(value2 * ONE_OVER_128);
+ data->reverb.setEffectMix(value2 * ONE_OVER_128);
else if (value1 == 7.0)
data->volume = value2 * ONE_OVER_128;
else if (value1 == 49.0)
@@ -183,7 +185,7 @@ int tick( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
counter = min( nTicks, data->counter );
data->counter -= counter;
for ( int i=0; ivolume * data->reverb->tick( data->voicer->tick() );
+ sample = data->volume * data->reverb.tick( data->voicer->tick() );
for ( unsigned int j=0; jnWvOuts; j++ ) data->wvout[j]->tick(sample);
if ( data->realtime )
for ( int k=0; kchannels; k++ ) *samples++ = sample;
@@ -212,6 +214,10 @@ int main( int argc, char *argv[] )
// specified in the command line, it will override this setting.
Stk::setSampleRate( 44100.0 );
+ // Depending on how you compile STK, you may need to explicitly set
+ // the path to the rawwave directory.
+ Stk::setRawwavePath( "../../rawwaves/" );
+
// By default, warning messages are not printed. If we want to see
// them, we need to specify that here.
Stk::showWarnings( true );
@@ -267,8 +273,8 @@ int main( int argc, char *argv[] )
#endif
// Set the reverb parameters.
- data.reverb = new PRCRev( data.t60 );
- data.reverb->setEffectMix(0.2);
+ data.reverb.setT60( data.t60 );
+ data.reverb.setEffectMix(0.2);
// Install an interrupt handler function.
(void) signal(SIGINT, finish);
@@ -315,7 +321,6 @@ int main( int argc, char *argv[] )
for ( i=0; i<(int)data.nWvOuts; i++ ) delete data.wvout[i];
free( data.wvout );
- delete data.reverb;
delete data.voicer;
for ( i=0; i {
-bind . {
- noteOn $pitch $press
-}
-
# Bind an X windows "close" event with the Exit routine
bind . +myExit
diff --git a/projects/demo/utilities.cpp b/projects/demo/utilities.cpp
index 853c25c..65b6a0b 100644
--- a/projects/demo/utilities.cpp
+++ b/projects/demo/utilities.cpp
@@ -36,6 +36,8 @@
#include "Resonate.h"
#include "Whistle.h"
+using namespace stk;
+
#define NUM_INSTS 28
// The order of the following list is important. The location of a particular
diff --git a/projects/demo/utilities.h b/projects/demo/utilities.h
index e80ddb2..1885687 100644
--- a/projects/demo/utilities.h
+++ b/projects/demo/utilities.h
@@ -6,9 +6,9 @@
#include "FileWvOut.h"
#include "Messager.h"
-int voiceByNumber(int number, Instrmnt **instrument);
+int voiceByNumber(int number, stk::Instrmnt **instrument);
-int voiceByName(char *name, Instrmnt **instrument);
+int voiceByName(char *name, stk::Instrmnt **instrument);
void usage(char *function);
@@ -16,4 +16,4 @@ int checkArgs(int numArgs, char *args[]);
int countVoices(int nArgs, char *args[]);
-bool parseArgs(int numArgs, char *args[], WvOut **output, Messager& messager);
+bool parseArgs(int numArgs, char *args[], stk::WvOut **output, stk::Messager& messager);
diff --git a/projects/effects/Makefile.in b/projects/effects/Makefile.in
index 39d60f5..8cc7bb5 100644
--- a/projects/effects/Makefile.in
+++ b/projects/effects/Makefile.in
@@ -20,18 +20,16 @@ endif
vpath %.h $(INCLUDE)
CC = @CXX@
-DEFS = @byte_order@
-DEFS += @debug@
-CFLAGS = @cflags@
-CFLAGS += @warn@ -I$(INCLUDE) -I../../src/include
+DEFS = @CPPFLAGS@
+DEFS += @byte_order@
+CFLAGS = @CXXFLAGS@
+CFLAGS += -I$(INCLUDE) -I$(INCLUDE)/../src/include
LIBRARY = @LIBS@
-LIBRARY += @frameworks@
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
PROGRAMS += effects
OBJECTS += RtMidi.o RtAudio.o Thread.o Mutex.o Socket.o TcpServer.o @objects@
- DEFS += @audio_apis@
endif
RAWWAVES = @rawwaves@
@@ -59,6 +57,7 @@ $(OBJECTS) : Stk.h
clean :
-rm $(OBJECT_PATH)/*.o
-rm $(PROGRAMS) *.exe
+ -rm -fR *.dSYM
strip :
strip $(PROGRAMS)
diff --git a/projects/effects/README-effects.txt b/projects/effects/README-effects.txt
index 6fa532a..d4d7e62 100644
--- a/projects/effects/README-effects.txt
+++ b/projects/effects/README-effects.txt
@@ -1,6 +1,6 @@
The Synthesis ToolKit in C++ (STK)
-By Perry R. Cook and Gary P. Scavone, 1995-2007.
+By Perry R. Cook and Gary P. Scavone, 1995-2009.
EFFECTS PROJECT:
diff --git a/projects/effects/effects.cpp b/projects/effects/effects.cpp
index 985dcf3..9553fa4 100644
--- a/projects/effects/effects.cpp
+++ b/projects/effects/effects.cpp
@@ -13,10 +13,13 @@
#include "RtAudio.h"
#include
+#include
#include
#include
using std::min;
+using namespace stk;
+
void usage(void) {
// Error function in case of incorrect command-line argument specifications
std::cout << "\nuseage: effects flags \n";
@@ -33,7 +36,7 @@ static void finish(int ignore){ done = true; }
// The TickData structure holds all the class instances and data that
// are shared by the various processing functions.
struct TickData {
- Effect *effect;
+ unsigned int effectId;
PRCRev prcrev;
JCRev jcrev;
NRev nrev;
@@ -51,7 +54,7 @@ struct TickData {
// Default constructor.
TickData()
- : effect(0), t60(1.0), counter(0),
+ : effectId(0), t60(1.0), counter(0),
settling( false ), haveMessage( false ) {}
};
@@ -90,18 +93,7 @@ void processMessage( TickData* data )
case 20: { // effect type change
int type = data->message.intValues[1];
- if ( type == 0 )
- data->effect = &(data->echo);
- else if ( type == 1 )
- data->effect = &(data->shifter);
- else if ( type == 2 )
- data->effect = &(data->chorus);
- else if ( type == 3 )
- data->effect = &(data->prcrev);
- else if ( type == 4 )
- data->effect = &(data->jcrev);
- else if ( type == 5 )
- data->effect = &(data->nrev);
+ data->effectId = (unsigned int) type;
break;
}
@@ -153,6 +145,7 @@ int tick( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
TickData *data = (TickData *) dataPointer;
register StkFloat *oSamples = (StkFloat *) outputBuffer, *iSamples = (StkFloat *) inputBuffer;
register StkFloat sample;
+ Effect *effect;
int i, counter, nTicks = (int) nBufferFrames;
while ( nTicks > 0 && !done ) {
@@ -170,9 +163,35 @@ int tick( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
counter = min( nTicks, data->counter );
data->counter -= counter;
for ( i=0; ienvelope.tick() * data->effect->tick( *iSamples++ );
- *oSamples++ = sample; // two channels interleaved
- *oSamples++ = sample;
+ if ( data->effectId < 2 ) { // Echo and PitShift ... mono output
+ if ( data->effectId == 0 )
+ sample = data->envelope.tick() * data->echo.tick( *iSamples++ );
+ else
+ sample = data->envelope.tick() * data->shifter.tick( *iSamples++ );
+ *oSamples++ = sample; // two channels interleaved
+ *oSamples++ = sample;
+ }
+ else { // Chorus or a reverb ... stereo output
+ if ( data->effectId == 2 ) {
+ data->chorus.tick( *iSamples++ );
+ effect = (Effect *) &(data->chorus);
+ }
+ else if ( data->effectId == 3 ) {
+ data->prcrev.tick( *iSamples++ );
+ effect = (Effect *) &(data->prcrev);
+ }
+ else if ( data->effectId == 4 ) {
+ data->jcrev.tick( *iSamples++ );
+ effect = (Effect *) &(data->jcrev);
+ }
+ else {
+ data->nrev.tick( *iSamples++ );
+ effect = (Effect *) &(data->nrev);
+ }
+ const StkFrames& samples = effect->lastFrame();
+ *oSamples++ = data->envelope.tick() * samples[0];
+ *oSamples++ = data->envelope.lastOut() * samples[1];
+ }
nTicks--;
}
if ( nTicks == 0 ) break;
@@ -184,7 +203,6 @@ int tick( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
return 0;
}
-
int main( int argc, char *argv[] )
{
TickData data;
@@ -230,7 +248,6 @@ int main( int argc, char *argv[] )
}
data.envelope.setRate( 0.001 );
- data.effect = &( data.echo );
// Install an interrupt handler function.
(void) signal( SIGINT, finish );
diff --git a/projects/effects/effects.dsp b/projects/effects/effects.dsp
index abb9228..1183e1f 100644
--- a/projects/effects/effects.dsp
+++ b/projects/effects/effects.dsp
@@ -118,10 +118,6 @@ SOURCE=..\..\include\Echo.h
# End Source File
# Begin Source File
-SOURCE=..\..\src\Effect.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\Effect.h
# End Source File
# Begin Source File
@@ -154,18 +150,10 @@ SOURCE=..\..\include\FileWvIn.h
# End Source File
# Begin Source File
-SOURCE=..\..\src\Filter.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\Filter.h
# End Source File
# Begin Source File
-SOURCE=..\..\src\Generator.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\Generator.h
# End Source File
# Begin Source File
@@ -282,15 +270,11 @@ SOURCE=..\..\include\Thread.h
# End Source File
# Begin Source File
-SOURCE=..\..\src\WaveLoop.cpp
+SOURCE=..\..\src\FileLoop.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\include\WaveLoop.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvIn.cpp
+SOURCE=..\..\include\FileLoop.h
# End Source File
# Begin Source File
diff --git a/projects/examples/Makefile.in b/projects/examples/Makefile.in
index 17b360c..3c522b4 100644
--- a/projects/examples/Makefile.in
+++ b/projects/examples/Makefile.in
@@ -14,17 +14,15 @@ endif
vpath %.h $(INCLUDE)
CC = @CXX@
-DEFS = @byte_order@
-DEFS += @debug@
-CFLAGS = @cflags@
-CFLAGS += @warn@ -I$(INCLUDE) -I../../src/include
+DEFS = @CPPFLAGS@
+DEFS += @byte_order@
+CFLAGS = @CXXFLAGS@
+CFLAGS += -I$(INCLUDE) -I$(INCLUDE)/../src/include
LIBRARY = @LIBS@
-LIBRARY += @frameworks@
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
PROGRAMS += play record audioprobe midiprobe duplex inetIn inetOut rtsine crtsine bethree controlbee threebees playsmf grains
- DEFS += @audio_apis@
endif
RAWWAVES = @rawwaves@
@@ -46,6 +44,7 @@ $(OBJECTS) : Stk.h
clean :
-rm $(OBJECT_PATH)/*.o
-rm $(PROGRAMS) *.exe
+ -rm -fR *~ *.dSYM
strip :
strip $(PROGRAMS)
@@ -56,47 +55,47 @@ audioprobe: RtAudio.o @objects@
midiprobe: RtMidi.o
$(CC) $(CFLAGS) $(DEFS) -o midiprobe midiprobe.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY)
-play: play.cpp Stk.o FileRead.o WvIn.o FileWvIn.o RtAudio.o
- $(CC) $(CFLAGS) $(DEFS) -o play play.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/FileWvIn.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
+play: play.cpp Stk.o FileRead.o FileWvIn.o RtAudio.o
+ $(CC) $(CFLAGS) $(DEFS) -o play play.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/FileWvIn.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
-record: record.cpp Stk.o WvIn.o FileWrite.o WvOut.o FileWvOut.o RtWvIn.o RtAudio.o
- $(CC) $(CFLAGS) $(DEFS) -o record record.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/FileWrite.o $(OBJECT_PATH)/FileWvOut.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/RtWvIn.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
+record: record.cpp Stk.o FileWrite.o FileWvOut.o RtWvIn.o RtAudio.o Mutex.o
+ $(CC) $(CFLAGS) $(DEFS) -o record record.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/FileWrite.o $(OBJECT_PATH)/FileWvOut.o $(OBJECT_PATH)/RtWvIn.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
-sine: sine.cpp Stk.o Generator.o SineWave.o FileWrite.o WvOut.o FileWvOut.o
- $(CC) $(CFLAGS) $(DEFS) -o sine sine.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/Generator.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/FileWrite.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/FileWvOut.o $(LIBRARY)
+sine: sine.cpp Stk.o SineWave.o FileWrite.o FileWvOut.o
+ $(CC) $(CFLAGS) $(DEFS) -o sine sine.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/FileWrite.o $(OBJECT_PATH)/FileWvOut.o $(LIBRARY)
duplex: duplex.cpp RtAudio.o
$(CC) $(CFLAGS) $(DEFS) -o duplex duplex.cpp $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
-inetIn: inetIn.cpp Stk.o WvIn.o InetWvIn.o WvOut.o RtWvOut.o RtAudio.o Socket.o TcpServer.o UdpSocket.o Thread.o Mutex.o
- $(CC) $(CFLAGS) $(DEFS) -o inetIn inetIn.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/InetWvIn.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/TcpServer.o $(OBJECT_PATH)/UdpSocket.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/RtWvOut.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
+inetIn: inetIn.cpp Stk.o InetWvIn.o RtWvOut.o RtAudio.o Socket.o TcpServer.o UdpSocket.o Thread.o Mutex.o
+ $(CC) $(CFLAGS) $(DEFS) -o inetIn inetIn.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/InetWvIn.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/TcpServer.o $(OBJECT_PATH)/UdpSocket.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/RtWvOut.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
-inetOut: inetOut.cpp Stk.o FileRead.o WvIn.o FileWvIn.o WvOut.o InetWvOut.o Socket.o TcpClient.o UdpSocket.o Thread.o Mutex.o
- $(CC) $(CFLAGS) $(DEFS) -o inetOut inetOut.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/FileWvIn.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/TcpClient.o $(OBJECT_PATH)/UdpSocket.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/InetWvOut.o $(LIBRARY)
+inetOut: inetOut.cpp Stk.o FileRead.o FileWvIn.o InetWvOut.o Socket.o TcpClient.o UdpSocket.o Thread.o Mutex.o
+ $(CC) $(CFLAGS) $(DEFS) -o inetOut inetOut.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/FileWvIn.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/TcpClient.o $(OBJECT_PATH)/UdpSocket.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/InetWvOut.o $(LIBRARY)
-sineosc: sineosc.cpp Stk.o FileRead.o WvIn.o FileWvIn.o WaveLoop.o FileWrite.o WvOut.o FileWvOut.o
- $(CC) $(CFLAGS) $(DEFS) -o sineosc sineosc.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/FileWrite.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/FileWvIn.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/FileWvOut.o $(OBJECT_PATH)/WaveLoop.o $(LIBRARY)
+sineosc: sineosc.cpp Stk.o FileRead.o FileWvIn.o FileLoop.o FileWrite.o FileWvOut.o
+ $(CC) $(CFLAGS) $(DEFS) -o sineosc sineosc.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/FileWrite.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/FileWvIn.o $(OBJECT_PATH)/FileWvOut.o $(OBJECT_PATH)/FileLoop.o $(LIBRARY)
-rtsine: rtsine.cpp Stk.o Generator.o SineWave.o WvOut.o RtWvOut.o RtAudio.o
- $(CC) $(CFLAGS) $(DEFS) -o rtsine rtsine.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/Generator.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/RtWvOut.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
+rtsine: rtsine.cpp Stk.o SineWave.o RtWvOut.o RtAudio.o Mutex.o
+ $(CC) $(CFLAGS) $(DEFS) -o rtsine rtsine.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/RtWvOut.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/Mutex.o $(LIBRARY)
-crtsine: crtsine.cpp Stk.o Generator.o SineWave.o RtAudio.o
- $(CC) $(CFLAGS) $(DEFS) -o crtsine crtsine.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/Generator.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
+crtsine: crtsine.cpp Stk.o SineWave.o RtAudio.o
+ $(CC) $(CFLAGS) $(DEFS) -o crtsine crtsine.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
-bethree: bethree.cpp Stk.o WvIn.o FileRead.o FileWvIn.o WaveLoop.o FM.o RtAudio.o Instrmnt.o Filter.o TwoZero.o Generator.o SineWave.o Envelope.o ADSR.o BeeThree.o
- $(CC) $(CFLAGS) $(DEFS) -o bethree bethree.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/FileWvIn.o $(OBJECT_PATH)/WaveLoop.o $(OBJECT_PATH)/FM.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/Instrmnt.o $(OBJECT_PATH)/Filter.o $(OBJECT_PATH)/TwoZero.o $(OBJECT_PATH)/Generator.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/Envelope.o $(OBJECT_PATH)/ADSR.o $(OBJECT_PATH)/BeeThree.o $(LIBRARY)
+bethree: bethree.cpp Stk.o FileRead.o FileWvIn.o FileLoop.o FM.o RtAudio.o TwoZero.o SineWave.o ADSR.o BeeThree.o
+ $(CC) $(CFLAGS) $(DEFS) -o bethree bethree.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/FileWvIn.o $(OBJECT_PATH)/FileLoop.o $(OBJECT_PATH)/FM.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/TwoZero.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/ADSR.o $(OBJECT_PATH)/BeeThree.o $(LIBRARY)
-controlbee: controlbee.cpp Stk.o WvIn.o FileRead.o FileWvIn.o WaveLoop.o FM.o RtAudio.o Instrmnt.o Filter.o TwoZero.o Generator.o SineWave.o Envelope.o ADSR.o BeeThree.o Messager.o RtMidi.o Socket.o TcpServer.o Thread.o Mutex.o Skini.o
- $(CC) $(CFLAGS) $(DEFS) -o controlbee controlbee.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/FileWvIn.o $(OBJECT_PATH)/WaveLoop.o $(OBJECT_PATH)/FM.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/Instrmnt.o $(OBJECT_PATH)/Filter.o $(OBJECT_PATH)/TwoZero.o $(OBJECT_PATH)/Generator.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/Envelope.o $(OBJECT_PATH)/ADSR.o $(OBJECT_PATH)/BeeThree.o $(OBJECT_PATH)/Messager.o $(OBJECT_PATH)/RtMidi.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/TcpServer.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/Skini.o $(LIBRARY)
+controlbee: controlbee.cpp Stk.o FileRead.o FileWvIn.o FileLoop.o FM.o RtAudio.o TwoZero.o SineWave.o ADSR.o BeeThree.o Messager.o RtMidi.o Socket.o TcpServer.o Thread.o Mutex.o Skini.o
+ $(CC) $(CFLAGS) $(DEFS) -o controlbee controlbee.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/FileWvIn.o $(OBJECT_PATH)/FileLoop.o $(OBJECT_PATH)/FM.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/TwoZero.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/ADSR.o $(OBJECT_PATH)/BeeThree.o $(OBJECT_PATH)/Messager.o $(OBJECT_PATH)/RtMidi.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/TcpServer.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/Skini.o $(LIBRARY)
-foursine: foursine.cpp Stk.o Generator.o SineWave.o FileWrite.o WvOut.o FileWvOut.o
- $(CC) $(CFLAGS) $(DEFS) -o foursine foursine.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/Generator.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/FileWrite.o $(OBJECT_PATH)/WvOut.o $(OBJECT_PATH)/FileWvOut.o $(LIBRARY)
+foursine: foursine.cpp Stk.o SineWave.o FileWrite.o FileWvOut.o
+ $(CC) $(CFLAGS) $(DEFS) -o foursine foursine.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/FileWrite.o $(OBJECT_PATH)/FileWvOut.o $(LIBRARY)
-threebees: threebees.cpp Stk.o FileRead.o WvIn.o FileWvIn.o WaveLoop.o FM.o RtAudio.o Instrmnt.o Filter.o TwoZero.o Generator.o SineWave.o Envelope.o ADSR.o BeeThree.o Messager.o RtMidi.o Socket.o TcpServer.o Thread.o Mutex.o Skini.o Voicer.o
- $(CC) $(CFLAGS) $(DEFS) -o threebees threebees.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/WvIn.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/FileWvIn.o $(OBJECT_PATH)/WaveLoop.o $(OBJECT_PATH)/FM.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/Instrmnt.o $(OBJECT_PATH)/Filter.o $(OBJECT_PATH)/TwoZero.o $(OBJECT_PATH)/Generator.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/Envelope.o $(OBJECT_PATH)/ADSR.o $(OBJECT_PATH)/BeeThree.o $(OBJECT_PATH)/Messager.o $(OBJECT_PATH)/RtMidi.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/TcpServer.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/Skini.o $(OBJECT_PATH)/Voicer.o $(LIBRARY)
+threebees: threebees.cpp Stk.o FileRead.o FileWvIn.o FileLoop.o FM.o RtAudio.o TwoZero.o SineWave.o ADSR.o BeeThree.o Messager.o RtMidi.o Socket.o TcpServer.o Thread.o Mutex.o Skini.o Voicer.o
+ $(CC) $(CFLAGS) $(DEFS) -o threebees threebees.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/FileWvIn.o $(OBJECT_PATH)/FileLoop.o $(OBJECT_PATH)/FM.o $(OBJECT_PATH)/RtAudio.o $(OBJECT_PATH)/TwoZero.o $(OBJECT_PATH)/SineWave.o $(OBJECT_PATH)/ADSR.o $(OBJECT_PATH)/BeeThree.o $(OBJECT_PATH)/Messager.o $(OBJECT_PATH)/RtMidi.o $(OBJECT_PATH)/Socket.o $(OBJECT_PATH)/TcpServer.o $(OBJECT_PATH)/Thread.o $(OBJECT_PATH)/Mutex.o $(OBJECT_PATH)/Skini.o $(OBJECT_PATH)/Voicer.o $(LIBRARY)
playsmf: playsmf.cpp Stk.o MidiFileIn.o RtMidi.o
$(CC) $(CFLAGS) $(DEFS) -o playsmf playsmf.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/MidiFileIn.o $(OBJECT_PATH)/RtMidi.o $(LIBRARY)
-grains: grains.cpp Stk.o Generator.o Granulate.o Noise.o FileRead.o RtAudio.o
- $(CC) $(CFLAGS) $(DEFS) -o grains grains.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/Generator.o $(OBJECT_PATH)/Granulate.o $(OBJECT_PATH)/Noise.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
+grains: grains.cpp Stk.o Granulate.o Noise.o FileRead.o RtAudio.o
+ $(CC) $(CFLAGS) $(DEFS) -o grains grains.cpp $(OBJECT_PATH)/Stk.o $(OBJECT_PATH)/Granulate.o $(OBJECT_PATH)/Noise.o $(OBJECT_PATH)/FileRead.o $(OBJECT_PATH)/RtAudio.o $(LIBRARY)
diff --git a/projects/examples/audioprobe.dsp b/projects/examples/audioprobe.dsp
index bdb557c..b6a43dc 100755
--- a/projects/examples/audioprobe.dsp
+++ b/projects/examples/audioprobe.dsp
@@ -160,3 +160,4 @@ SOURCE=..\..\include\RtError.h
# End Group
# End Target
# End Project
+
diff --git a/projects/examples/bethree.cpp b/projects/examples/bethree.cpp
index 0767c03..5869bc6 100644
--- a/projects/examples/bethree.cpp
+++ b/projects/examples/bethree.cpp
@@ -2,6 +2,7 @@
#include "BeeThree.h"
#include "RtAudio.h"
+using namespace stk;
// The TickData structure holds all the class instances and data that
// are shared by the various processing functions.
diff --git a/projects/examples/bethree.dsp b/projects/examples/bethree.dsp
index c5f4401..56d55dc 100755
--- a/projects/examples/bethree.dsp
+++ b/projects/examples/bethree.dsp
@@ -111,19 +111,11 @@ SOURCE=..\..\src\FileWvIn.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\Filter.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\src\FM.cpp
# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\Generator.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\Instrmnt.cpp
+# Begin Source File
+
+SOURCE=..\..\src\Mutex.cpp
# End Source File
# Begin Source File
@@ -147,15 +139,7 @@ SOURCE=..\..\src\TwoZero.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\WaveLoop.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvIn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvOut.cpp
+SOURCE=..\..\src\FileLoop.cpp
# End Source File
# End Group
# Begin Group "Header Files"
@@ -197,6 +181,10 @@ SOURCE=..\..\include\Generator.h
SOURCE=..\..\include\Instrmnt.h
# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\Mutex.h
+# End Source File
# Begin Source File
SOURCE=..\..\include\RtAudio.h
@@ -215,7 +203,7 @@ SOURCE=..\..\include\TwoZero.h
# End Source File
# Begin Source File
-SOURCE=..\..\include\WaveLoop.h
+SOURCE=..\..\include\FileLoop.h
# End Source File
# Begin Source File
diff --git a/projects/examples/controlbee.cpp b/projects/examples/controlbee.cpp
index 8902172..f2ba4b1 100644
--- a/projects/examples/controlbee.cpp
+++ b/projects/examples/controlbee.cpp
@@ -8,6 +8,8 @@
#include
using std::min;
+using namespace stk;
+
void usage(void) {
// Error function in case of incorrect command-line
// argument specifications.
diff --git a/projects/examples/controlbee.dsp b/projects/examples/controlbee.dsp
index 557262b..6b41d03 100755
--- a/projects/examples/controlbee.dsp
+++ b/projects/examples/controlbee.dsp
@@ -112,22 +112,10 @@ SOURCE=..\..\src\FileWvIn.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\Filter.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\src\FM.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\Generator.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\Instrmnt.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\src\Messager.cpp
# End Source File
# Begin Source File
@@ -176,15 +164,7 @@ SOURCE=..\..\src\TwoZero.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\WaveLoop.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvIn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvOut.cpp
+SOURCE=..\..\src\FileLoop.cpp
# End Source File
# End Group
# Begin Group "Header Files"
@@ -252,7 +232,7 @@ SOURCE=..\..\include\TwoZero.h
# End Source File
# Begin Source File
-SOURCE=..\..\include\WaveLoop.h
+SOURCE=..\..\include\FileLoop.h
# End Source File
# Begin Source File
diff --git a/projects/examples/crtsine.cpp b/projects/examples/crtsine.cpp
index b959c08..26087b9 100644
--- a/projects/examples/crtsine.cpp
+++ b/projects/examples/crtsine.cpp
@@ -2,6 +2,7 @@
#include "SineWave.h"
#include "RtAudio.h"
+using namespace stk;
// This tick() function handles sample computation only. It will be
// called automatically when the system needs a new buffer of audio
diff --git a/projects/examples/crtsine.dsp b/projects/examples/crtsine.dsp
index 004e7c7..f56b8ae 100755
--- a/projects/examples/crtsine.dsp
+++ b/projects/examples/crtsine.dsp
@@ -91,18 +91,6 @@ SOURCE=.\crtsine.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\FileRead.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\FileWvIn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\Generator.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\src\RtAudio.cpp
# End Source File
# Begin Source File
@@ -113,14 +101,6 @@ SOURCE=..\..\src\SineWave.cpp
SOURCE=..\..\src\Stk.cpp
# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WaveLoop.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvIn.cpp
-# End Source File
# End Group
# Begin Group "Header Files"
@@ -133,13 +113,9 @@ SOURCE=..\..\include\RtAudio.h
SOURCE=..\..\include\Stk.h
# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\WaveLoop.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\WvIn.h
+# Begin Source File
+
+SOURCE=..\..\include\Generator.h
# End Source File
# End Group
# Begin Group "Resource Files"
diff --git a/projects/examples/duplex.cpp b/projects/examples/duplex.cpp
index 77cf961..5edceae 100644
--- a/projects/examples/duplex.cpp
+++ b/projects/examples/duplex.cpp
@@ -10,6 +10,8 @@
#include "RtAudio.h"
#include
+#include
+#include
/*
typedef signed long MY_TYPE;
@@ -86,10 +88,16 @@ int main(int argc, char *argv[])
// Set the same number of channels for both input and output.
unsigned int bufferFrames = 512;
RtAudio::StreamParameters iParams, oParams;
- iParams.deviceId = iDevice;
+ if ( iDevice == 0 )
+ iParams.deviceId = adac.getDefaultInputDevice();
+ else
+ iParams.deviceId = iDevice - 1;
iParams.nChannels = channels;
iParams.firstChannel = iOffset;
- oParams.deviceId = oDevice;
+ if ( oDevice == 0 )
+ oParams.deviceId = adac.getDefaultOutputDevice();
+ else
+ oParams.deviceId = oDevice - 1;
oParams.nChannels = channels;
oParams.firstChannel = oOffset;
diff --git a/projects/examples/foursine.cpp b/projects/examples/foursine.cpp
index 7e64c88..d0f8e61 100644
--- a/projects/examples/foursine.cpp
+++ b/projects/examples/foursine.cpp
@@ -2,6 +2,7 @@
#include "SineWave.h"
#include "FileWvOut.h"
+using namespace stk;
int main()
{
@@ -29,7 +30,7 @@ int main()
for ( i=0; i<4; i++ )
inputs[i].tick( frames, i );
- output.tickFrame( frames );
+ output.tick( frames );
// Now write the first sine to all four channels for two seconds
for ( i=0; i<88200; i++ ) {
diff --git a/projects/examples/foursine.dsp b/projects/examples/foursine.dsp
index 220fd1b..9fcd11a 100755
--- a/projects/examples/foursine.dsp
+++ b/projects/examples/foursine.dsp
@@ -85,18 +85,10 @@ LINK32=link.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
-SOURCE=..\..\src\FileRead.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\src\FileWrite.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\FileWvIn.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\src\FileWvOut.cpp
# End Source File
# Begin Source File
@@ -105,28 +97,12 @@ SOURCE=.\foursine.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\Generator.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\src\SineWave.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Stk.cpp
# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WaveLoop.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvIn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvOut.cpp
-# End Source File
# End Group
# Begin Group "Header Files"
@@ -145,14 +121,6 @@ SOURCE=..\..\include\Stk.h
# End Source File
# Begin Source File
-SOURCE=..\..\include\WaveLoop.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\WvIn.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\WvOut.h
# End Source File
# End Group
diff --git a/projects/examples/grains.cpp b/projects/examples/grains.cpp
index 71f2f45..801e112 100644
--- a/projects/examples/grains.cpp
+++ b/projects/examples/grains.cpp
@@ -5,6 +5,8 @@
#include "Granulate.h"
#include "RtAudio.h"
+using namespace stk;
+
// This tick() function handles sample computation only. It will be
// called automatically when the system needs a new buffer of audio
// samples.
@@ -13,9 +15,15 @@ int tick( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
{
Granulate *grani = (Granulate *) dataPointer;
register StkFloat *samples = (StkFloat *) outputBuffer;
+ const StkFrames& lastframe = grani->lastFrame();
+ unsigned int nChannels = lastframe.channels();
- for ( unsigned int i=0; itick();
+ unsigned int j;
+ for ( unsigned int i=0; itick();
+ for ( j=0; jtickFrame( input.tickFrame( frame ) );
+ output->tick( input.tick( frame ) );
cleanup:
delete output;
diff --git a/projects/examples/inetIn.dsp b/projects/examples/inetIn.dsp
index 5e4f4e6..8ce3ebb 100755
--- a/projects/examples/inetIn.dsp
+++ b/projects/examples/inetIn.dsp
@@ -125,14 +125,6 @@ SOURCE=..\..\src\Thread.cpp
SOURCE=..\..\src\UdpSocket.cpp
# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvIn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvOut.cpp
-# End Source File
# End Group
# Begin Group "Header Files"
diff --git a/projects/examples/inetOut.cpp b/projects/examples/inetOut.cpp
index 211fd1c..1de041e 100644
--- a/projects/examples/inetOut.cpp
+++ b/projects/examples/inetOut.cpp
@@ -20,6 +20,8 @@
#include "FileWvIn.h"
#include "InetWvOut.h"
+using namespace stk;
+
void usage(void) {
// Error function in case of incorrect command-line
// argument specifications.
@@ -57,7 +59,7 @@ int main( int argc, char *argv[] )
input.setRate( rate );
// Find out how many channels we have.
- int channels = input.getChannels();
+ int channels = input.channelsOut();
StkFrames frames( 4096, channels );
// Attempt to connect to the socket server.
@@ -71,7 +73,7 @@ int main( int argc, char *argv[] )
// Here's the runtime loop
while ( !input.isFinished() )
- output.tickFrame( input.tickFrame( frames ) );
+ output.tick( input.tick( frames ) );
return 0;
}
diff --git a/projects/examples/inetOut.dsp b/projects/examples/inetOut.dsp
index 6ecf774..bdd3e8e 100755
--- a/projects/examples/inetOut.dsp
+++ b/projects/examples/inetOut.dsp
@@ -117,14 +117,6 @@ SOURCE=..\..\src\TcpClient.cpp
SOURCE=..\..\src\UdpSocket.cpp
# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvIn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvOut.cpp
-# End Source File
# End Group
# Begin Group "Header Files"
diff --git a/projects/examples/libMakefile.in b/projects/examples/libMakefile.in
index d6e995d..6dab44b 100644
--- a/projects/examples/libMakefile.in
+++ b/projects/examples/libMakefile.in
@@ -10,17 +10,15 @@ endif
vpath %.h $(INCLUDE)
CC = @CXX@
-DEFS = @byte_order@
-DEFS += @debug@
-CFLAGS = @cflags@
-CFLAGS += @warn@ -I$(INCLUDE) -I../../src/include
+DEFS = @CPPFLAGS@
+DEFS += @byte_order@
+CFLAGS = @CXXFLAGS@
+CFLAGS += -I$(INCLUDE) -Iinclude
LIBRARY = @LIBS@
-LIBRARY += @frameworks@
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
PROGRAMS += audioprobe midiprobe duplex play record inetIn inetOut rtsine crtsine bethree controlbee threebees playsmf grains
- DEFS += @audio_apis@
endif
RAWWAVES = @rawwaves@
diff --git a/projects/examples/midiprobe.cpp b/projects/examples/midiprobe.cpp
index 7b4dc8c..9fdb242 100644
--- a/projects/examples/midiprobe.cpp
+++ b/projects/examples/midiprobe.cpp
@@ -5,6 +5,7 @@
// by Gary Scavone, 2003-2004.
#include
+#include
#include "RtMidi.h"
int main()
diff --git a/projects/examples/play.cpp b/projects/examples/play.cpp
index c0cd29b..fef3e63 100644
--- a/projects/examples/play.cpp
+++ b/projects/examples/play.cpp
@@ -19,6 +19,8 @@
#include
#include
+using namespace stk;
+
// Eewww ... global variables! :-)
bool done;
StkFrames frames;
@@ -44,7 +46,7 @@ int tick( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
FileWvIn *input = (FileWvIn *) userData;
register StkFloat *samples = (StkFloat *) outputBuffer;
- input->tickFrame( frames );
+ input->tick( frames );
for ( unsigned int i=0; i
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=probe - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "probe.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "probe.mak" CFG="probe - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "probe - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "probe - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "probe - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "probe___Win32_Release"
-# PROP BASE Intermediate_Dir "probe___Win32_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir ""
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__WINDOWS_ASIO__" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-
-!ELSEIF "$(CFG)" == "probe - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "probe___Win32_Debug"
-# PROP BASE Intermediate_Dir "probe___Win32_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir ""
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__WINDOWS_ASIO__" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# SUBTRACT LINK32 /pdb:none
-
-!ENDIF
-
-# Begin Target
-
-# Name "probe - Win32 Release"
-# Name "probe - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\..\src\asio\asio.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\asio\asiodrivers.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\asio\asiolist.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\asio\iasiothiscallresolver.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\probe.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\RtAudio.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=..\..\src\asio\asio.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\asio\asiodrivers.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\asio\asiodrvr.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\asio\asiolist.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\asio\asiosys.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\asio\ginclude.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\asio\iasiodrv.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\asio\iasiothiscallresolver.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\RtAudio.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/projects/examples/record.cpp b/projects/examples/record.cpp
index d7b49cc..d3b6a7e 100644
--- a/projects/examples/record.cpp
+++ b/projects/examples/record.cpp
@@ -25,6 +25,8 @@
#include "RtWvIn.h"
#include "FileWvOut.h"
+using namespace stk;
+
void usage( void ) {
// Error function in case of incorrect command-line
// argument specifications.
@@ -75,7 +77,7 @@ int main( int argc, char *argv[] )
// Here's the runtime loop
samples = (long) ( time * Stk::sampleRate() );
for ( i=0; itickFrame( input->tickFrame( frame ) );
+ output->tick( input->tick( frame ) );
}
cleanup:
diff --git a/projects/examples/record.dsp b/projects/examples/record.dsp
index fe537e7..ebca7eb 100755
--- a/projects/examples/record.dsp
+++ b/projects/examples/record.dsp
@@ -101,7 +101,11 @@ SOURCE=.\record.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\RtAudio.cpp
+SOURCE=..\..\src\Mutex.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\RtAudio.cpp
# End Source File
# Begin Source File
@@ -111,14 +115,6 @@ SOURCE=..\..\src\RtWvIn.cpp
SOURCE=..\..\src\Stk.cpp
# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvIn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvOut.cpp
-# End Source File
# End Group
# Begin Group "Header Files"
@@ -131,6 +127,10 @@ SOURCE=..\..\include\RtAudio.h
SOURCE=..\..\include\RtWvIn.h
# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\Mutex.h
+# End Source File
# Begin Source File
SOURCE=..\..\include\Stk.h
diff --git a/projects/examples/rtsine.cpp b/projects/examples/rtsine.cpp
index 96a9773..bb42403 100644
--- a/projects/examples/rtsine.cpp
+++ b/projects/examples/rtsine.cpp
@@ -2,6 +2,7 @@
#include "SineWave.h"
#include "RtWvOut.h"
+using namespace stk;
int main()
{
@@ -9,6 +10,7 @@ int main()
Stk::setSampleRate( 44100.0 );
Stk::showWarnings( true );
+ int nFrames = 100000;
SineWave sine;
RtWvOut *dac = 0;
@@ -22,8 +24,19 @@ int main()
sine.setFrequency( 441.0 );
- // Play the oscillator for 40000 samples
- for ( int i=0; i<40000; i++ ) {
+ // Option 1: Use StkFrames
+ /*
+ StkFrames frames( nFrames, 1 );
+ try {
+ dac->tick( sine.tick( frames ) );
+ }
+ catch ( StkError & ) {
+ goto cleanup;
+ }
+ */
+
+ // Option 2: Single-sample computations
+ for ( int i=0; itick( sine.tick() );
}
diff --git a/projects/examples/rtsine.dsp b/projects/examples/rtsine.dsp
index cab3ae3..50f0c0f 100755
--- a/projects/examples/rtsine.dsp
+++ b/projects/examples/rtsine.dsp
@@ -87,18 +87,6 @@ LINK32=link.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
-SOURCE=..\..\src\FileRead.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\FileWvIn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\Generator.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\src\RtAudio.cpp
# End Source File
# Begin Source File
@@ -107,7 +95,11 @@ SOURCE=.\rtsine.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\RtWvOut.cpp
+SOURCE=..\..\src\Mutex.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\RtWvOut.cpp
# End Source File
# Begin Source File
@@ -117,32 +109,12 @@ SOURCE=..\..\src\SineWave.cpp
SOURCE=..\..\src\Stk.cpp
# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WaveLoop.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvIn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvOut.cpp
-# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
-SOURCE=..\..\include\FileRead.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\FileWvIn.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\RtAudio.h
# End Source File
# Begin Source File
@@ -153,13 +125,9 @@ SOURCE=..\..\include\RtWvOut.h
SOURCE=..\..\include\Stk.h
# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\WaveLoop.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\WvIn.h
+# Begin Source File
+
+SOURCE=..\..\include\Mutex.h
# End Source File
# Begin Source File
diff --git a/projects/examples/sine.cpp b/projects/examples/sine.cpp
index 84fb59d..84ca398 100644
--- a/projects/examples/sine.cpp
+++ b/projects/examples/sine.cpp
@@ -14,6 +14,7 @@
#include "SineWave.h"
#include "FileWvOut.h"
+using namespace stk;
void usage(void) {
// Error function in case of incorrect command-line
@@ -73,7 +74,7 @@ int main( int argc, char *argv[] )
for ( i=0; itick( frames, i );
- output.tickFrame( frames );
+ output.tick( frames );
cleanup:
for ( i=0; i
using std::min;
+using namespace stk;
+
// The TickData structure holds all the class instances and data that
// are shared by the various processing functions.
struct TickData {
diff --git a/projects/examples/threebees.dsp b/projects/examples/threebees.dsp
index f8c9a24..54e98f2 100755
--- a/projects/examples/threebees.dsp
+++ b/projects/examples/threebees.dsp
@@ -107,22 +107,10 @@ SOURCE=..\..\src\FileWvIn.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\Filter.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\src\FM.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\Generator.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\Instrmnt.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\src\Messager.cpp
# End Source File
# Begin Source File
@@ -179,15 +167,7 @@ SOURCE=..\..\src\Voicer.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\src\WaveLoop.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvIn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvOut.cpp
+SOURCE=..\..\src\FileLoop.cpp
# End Source File
# End Group
# Begin Group "Header Files"
@@ -259,7 +239,7 @@ SOURCE=..\..\include\Voicer.h
# End Source File
# Begin Source File
-SOURCE=..\..\include\WaveLoop.h
+SOURCE=..\..\include\FileLoop.h
# End Source File
# Begin Source File
diff --git a/projects/ragamatic/Drone.cpp b/projects/ragamatic/Drone.cpp
index 61e411f..bcf903e 100644
--- a/projects/ragamatic/Drone.cpp
+++ b/projects/ragamatic/Drone.cpp
@@ -13,15 +13,17 @@
Stanford, bearing the names of Karplus and/or
Strong.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "Drone.h"
+namespace stk {
+
Drone :: Drone( StkFloat lowestFrequency )
{
- length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
+ length_ = (unsigned long) ( Stk::sampleRate() / lowestFrequency + 1 );
loopGain_ = 0.999;
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( 0.5 * length_ );
@@ -29,11 +31,11 @@ Drone :: Drone( StkFloat lowestFrequency )
this->clear();
}
-Drone :: ~Drone()
+Drone :: ~Drone( void )
{
}
-void Drone :: clear()
+void Drone :: clear( void )
{
delayLine_.clear();
loopFilter_.clear();
@@ -95,11 +97,4 @@ void Drone :: noteOff( StkFloat amplitude )
#endif
}
-StkFloat Drone :: computeSample()
-{
- // Here's the whole inner loop of the instrument!!
- lastOutput_ = delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ )
- + (0.005 * envelope_.tick() * noise_.tick()));
- return lastOutput_;
-}
-
+} // stk namespace
diff --git a/projects/ragamatic/Drone.h b/projects/ragamatic/Drone.h
index 6563cd8..9d1cd6e 100644
--- a/projects/ragamatic/Drone.h
+++ b/projects/ragamatic/Drone.h
@@ -1,3 +1,14 @@
+#ifndef STK_DRONE_H
+#define STK_DRONE_H
+
+#include "Instrmnt.h"
+#include "DelayA.h"
+#include "OneZero.h"
+#include "ADSR.h"
+#include "Noise.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Drone
\brief STK "drone" plucked string model.
@@ -13,19 +24,10 @@
Stanford, bearing the names of Karplus and/or
Strong.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_DRONE_H
-#define STK_DRONE_H
-
-#include "Instrmnt.h"
-#include "DelayA.h"
-#include "OneZero.h"
-#include "ADSR.h"
-#include "Noise.h"
-
class Drone : public Instrmnt
{
public:
@@ -33,27 +35,28 @@ class Drone : public Instrmnt
Drone( StkFloat lowestFrequency = 20 );
//! Class destructor.
- ~Drone();
+ ~Drone( void );
//! Reset and clear all internal state.
- void clear();
+ void clear( void );
//! Set instrument parameters for a particular frequency.
- virtual void setFrequency(StkFloat frequency);
+ void setFrequency( StkFloat frequency );
//! Pluck the string with the given amplitude using the current frequency.
- void pluck(StkFloat amplitude);
+ void pluck( StkFloat amplitude );
//! Start a note with the given frequency and amplitude.
- virtual void noteOn(StkFloat frequency, StkFloat amplitude);
+ void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- virtual void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
DelayA delayLine_;
OneZero loopFilter_;
ADSR envelope_;
@@ -63,5 +66,15 @@ class Drone : public Instrmnt
};
+inline StkFloat Drone :: tick( unsigned int )
+{
+ // Here's the whole inner loop of the instrument!!
+ lastFrame_[0] = delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ )
+ + ( 0.005 * envelope_.tick() * noise_.tick() ) );
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/projects/ragamatic/Makefile.in b/projects/ragamatic/Makefile.in
index cc65a20..22a5308 100644
--- a/projects/ragamatic/Makefile.in
+++ b/projects/ragamatic/Makefile.in
@@ -7,12 +7,12 @@ SRC_PATH = ../../src
OBJECT_PATH = @object_path@
vpath %.o $(OBJECT_PATH)
-OBJECTS = Stk.o Generator.o Noise.o Envelope.o ADSR.o \
- Filter.o DelayA.o Delay.o \
+OBJECTS = Stk.o Noise.o ADSR.o \
+ DelayA.o Delay.o \
OnePole.o OneZero.o Skini.o \
- Tabla.o Instrmnt.o Sitar.o \
- Drone.o VoicDrum.o FileRead.o WvOut.o WvIn.o FileWvIn.o \
- Effect.o JCRev.o Messager.o
+ Tabla.o Sitar.o \
+ Drone.o VoicDrum.o FileRead.o FileWvIn.o \
+ JCRev.o Messager.o
INCLUDE = @include@
ifeq ($(strip $(INCLUDE)), )
@@ -21,18 +21,16 @@ endif
vpath %.h $(INCLUDE)
CC = @CXX@
-DEFS = @byte_order@
-DEFS += @debug@
-CFLAGS = @cflags@
-CFLAGS += @warn@ -I$(INCLUDE) -I../../src/include
+DEFS = @CPPFLAGS@
+DEFS += @byte_order@
+CFLAGS = @CXXFLAGS@
+CFLAGS += -I$(INCLUDE) -I$(INCLUDE)/../src/include
LIBRARY = @LIBS@
-LIBRARY += @frameworks@
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
PROGRAMS = ragamat
OBJECTS += RtMidi.o RtAudio.o RtWvOut.o Thread.o Mutex.o Socket.o TcpServer.o @objects@
- DEFS += @audio_apis@
endif
RAWWAVES = @rawwaves@
@@ -60,6 +58,7 @@ $(OBJECTS) : Stk.h
clean :
-rm $(OBJECT_PATH)/*.o
-rm $(PROGRAMS) *.exe
+ -rm -fR *.dSYM
strip :
strip $(PROGRAMS)
diff --git a/projects/ragamatic/Tabla.cpp b/projects/ragamatic/Tabla.cpp
index a9998b0..32320c5 100644
--- a/projects/ragamatic/Tabla.cpp
+++ b/projects/ragamatic/Tabla.cpp
@@ -8,14 +8,16 @@
sample rates. You can specify the maximum polyphony (maximum
number of simultaneous voices) in Tabla.h.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "Tabla.h"
#include
-Tabla :: Tabla() : Instrmnt()
+namespace stk {
+
+Tabla :: Tabla( void ) : Instrmnt()
{
// This counts the number of sounding voices.
nSounding_ = 0;
@@ -23,7 +25,7 @@ Tabla :: Tabla() : Instrmnt()
soundNumber_ = std::vector (TABLA_POLYPHONY, -1);
}
-Tabla :: ~Tabla()
+Tabla :: ~Tabla( void )
{
}
@@ -45,7 +47,7 @@ static char tablaWaves[TABLA_NUMWAVES][16] =
"DrTak2.raw"
};
-void Tabla :: noteOn(StkFloat instrument, StkFloat amplitude)
+void Tabla :: noteOn( StkFloat instrument, StkFloat amplitude )
{
#if defined(_STK_DEBUG_)
errorString_ << "Tabla::noteOn: instrument = " << instrument << ", amplitude = " << amplitude << '.';
@@ -117,34 +119,11 @@ void Tabla :: noteOn(StkFloat instrument, StkFloat amplitude)
#endif
}
-void Tabla :: noteOff(StkFloat amplitude)
+void Tabla :: noteOff( StkFloat amplitude )
{
// Set all sounding wave filter gains low.
int i = 0;
while ( i < nSounding_ ) filters_[i++].setGain( amplitude * 0.01 );
}
-StkFloat Tabla :: computeSample()
-{
- lastOutput_ = 0.0;
- if ( nSounding_ == 0 ) return lastOutput_;
-
- for ( int i=0; i= 0 ) {
- if ( waves_[i].isFinished() ) {
- // Re-order the list.
- for ( int j=0; j soundOrder_[i] )
- soundOrder_[j] -= 1;
- }
- soundOrder_[i] = -1;
- nSounding_--;
- }
- else
- lastOutput_ += filters_[i].tick( waves_[i].tick() );
- }
- }
-
- return lastOutput_;
-}
-
+} // stk namespace
diff --git a/projects/ragamatic/Tabla.h b/projects/ragamatic/Tabla.h
index b4c6e6e..ea8a910 100644
--- a/projects/ragamatic/Tabla.h
+++ b/projects/ragamatic/Tabla.h
@@ -1,3 +1,12 @@
+#ifndef STK_TABLA_H
+#define STK_TABLA_H
+
+#include "Instrmnt.h"
+#include "FileWvIn.h"
+#include "OnePole.h"
+
+namespace stk {
+
/***************************************************/
/*! \class Tabla
\brief STK tabla drum class.
@@ -8,17 +17,10 @@
sample rates. You can specify the maximum polyphony (maximum
number of simultaneous voices) in Tabla.h.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_TABLA_H
-#define STK_TABLA_H
-
-#include "Instrmnt.h"
-#include "FileWvIn.h"
-#include "OnePole.h"
-
const int TABLA_NUMWAVES = 15;
const int TABLA_POLYPHONY = 4;
@@ -26,27 +28,54 @@ class Tabla : public Instrmnt
{
public:
//! Class constructor.
- Tabla();
+ Tabla( void );
//! Class destructor.
- ~Tabla();
+ ~Tabla( void );
//! Start a note with the given drum type and amplitude.
- void noteOn(StkFloat instrument, StkFloat amplitude);
+ void noteOn( StkFloat instrument, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
FileWvIn waves_[TABLA_POLYPHONY];
OnePole filters_[TABLA_POLYPHONY];
std::vector soundOrder_;
std::vector soundNumber_;
- int nSounding_;
+ int nSounding_;
};
+inline StkFloat Tabla :: tick( unsigned int )
+{
+ lastFrame_[0] = 0.0;
+ if ( nSounding_ == 0 ) return lastFrame_[0];
+
+ for ( int i=0; i= 0 ) {
+ if ( waves_[i].isFinished() ) {
+ // Re-order the list.
+ for ( int j=0; j soundOrder_[i] )
+ soundOrder_[j] -= 1;
+ }
+ soundOrder_[i] = -1;
+ nSounding_--;
+ }
+ else
+ lastFrame_[0] += filters_[i].tick( waves_[i].tick() );
+ }
+ }
+
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/projects/ragamatic/VoicDrum.cpp b/projects/ragamatic/VoicDrum.cpp
index b959308..ce8c4c7 100644
--- a/projects/ragamatic/VoicDrum.cpp
+++ b/projects/ragamatic/VoicDrum.cpp
@@ -8,14 +8,16 @@
sample rates. You can specify the maximum polyphony (maximum
number of simultaneous voices) in VoicDrum.h.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "VoicDrum.h"
#include
-VoicDrum :: VoicDrum() : Instrmnt()
+namespace stk {
+
+VoicDrum :: VoicDrum( void ) : Instrmnt()
{
// This counts the number of sounding voices.
nSounding_ = 0;
@@ -23,7 +25,7 @@ VoicDrum :: VoicDrum() : Instrmnt()
soundNumber_ = std::vector (VOICE_POLYPHONY, -1);
}
-VoicDrum :: ~VoicDrum()
+VoicDrum :: ~VoicDrum( void )
{
}
@@ -114,33 +116,11 @@ void VoicDrum :: noteOn( StkFloat instrument, StkFloat amplitude )
#endif
}
-void VoicDrum :: noteOff(StkFloat amplitude)
+void VoicDrum :: noteOff( StkFloat amplitude )
{
// Set all sounding wave filter gains low.
int i = 0;
while ( i < nSounding_ ) filters_[i++].setGain( amplitude * 0.01 );
}
-StkFloat VoicDrum :: computeSample()
-{
- lastOutput_ = 0.0;
- if ( nSounding_ == 0 ) return lastOutput_;
-
- for ( int i=0; i= 0 ) {
- if ( waves_[i].isFinished() ) {
- // Re-order the list.
- for ( int j=0; j soundOrder_[i] )
- soundOrder_[j] -= 1;
- }
- soundOrder_[i] = -1;
- nSounding_--;
- }
- else
- lastOutput_ += filters_[i].tick( waves_[i].tick() );
- }
- }
-
- return lastOutput_;
-}
+} // stk namespace
diff --git a/projects/ragamatic/VoicDrum.h b/projects/ragamatic/VoicDrum.h
index 14168ba..7c1451e 100644
--- a/projects/ragamatic/VoicDrum.h
+++ b/projects/ragamatic/VoicDrum.h
@@ -1,3 +1,12 @@
+#ifndef STK_VOICDRUM_H
+#define STK_VOICDRUM_H
+
+#include "Instrmnt.h"
+#include "FileWvIn.h"
+#include "OnePole.h"
+
+namespace stk {
+
/***************************************************/
/*! \class VoicDrum
\brief STK vocal drum sample player class.
@@ -8,17 +17,10 @@
sample rates. You can specify the maximum polyphony (maximum
number of simultaneous voices) in VoicDrum.h.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#ifndef STK_VOICDRUM_H
-#define STK_VOICDRUM_H
-
-#include "Instrmnt.h"
-#include "FileWvIn.h"
-#include "OnePole.h"
-
const int VOICE_NUMWAVES = 11;
const int VOICE_POLYPHONY = 4;
@@ -26,21 +28,22 @@ class VoicDrum : public Instrmnt
{
public:
//! Class constructor.
- VoicDrum();
+ VoicDrum( void );
//! Class destructor.
- ~VoicDrum();
+ ~VoicDrum( void );
//! Start a note with the given drum type and amplitude.
- void noteOn(StkFloat instrument, StkFloat amplitude);
+ void noteOn( StkFloat instrument, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
- void noteOff(StkFloat amplitude);
+ void noteOff( StkFloat amplitude );
+
+ //! Compute and return one output sample.
+ StkFloat tick( unsigned int channel = 0 );
protected:
- StkFloat computeSample( void );
-
FileWvIn waves_[VOICE_POLYPHONY];
OnePole filters_[VOICE_POLYPHONY];
std::vector soundOrder_;
@@ -49,4 +52,30 @@ class VoicDrum : public Instrmnt
};
+inline StkFloat VoicDrum :: tick( unsigned int )
+{
+ lastFrame_[0] = 0.0;
+ if ( nSounding_ == 0 ) return lastFrame_[0];
+
+ for ( int i=0; i= 0 ) {
+ if ( waves_[i].isFinished() ) {
+ // Re-order the list.
+ for ( int j=0; j soundOrder_[i] )
+ soundOrder_[j] -= 1;
+ }
+ soundOrder_[i] = -1;
+ nSounding_--;
+ }
+ else
+ lastFrame_[0] += filters_[i].tick( waves_[i].tick() );
+ }
+ }
+
+ return lastFrame_[0];
+}
+
+} // stk namespace
+
#endif
diff --git a/projects/ragamatic/ragamat.cpp b/projects/ragamatic/ragamat.cpp
index fbab62b..b0ac11d 100644
--- a/projects/ragamatic/ragamat.cpp
+++ b/projects/ragamatic/ragamat.cpp
@@ -11,9 +11,11 @@
#include "RtAudio.h"
#include
+#include
#include
#include
using std::min;
+using namespace stk;
StkFloat float_random(StkFloat max) // Return random float between 0.0 and max
{
diff --git a/projects/ragamatic/ragamat.dsp b/projects/ragamatic/ragamat.dsp
index 4d5868b..f0a7506 100644
--- a/projects/ragamatic/ragamat.dsp
+++ b/projects/ragamatic/ragamat.dsp
@@ -124,10 +124,6 @@ SOURCE=.\Drone.h
# End Source File
# Begin Source File
-SOURCE=..\..\src\Effect.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\Effect.h
# End Source File
# Begin Source File
@@ -156,26 +152,14 @@ SOURCE=..\..\include\FileWvIn.h
# End Source File
# Begin Source File
-SOURCE=..\..\src\Filter.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\Filter.h
# End Source File
# Begin Source File
-SOURCE=..\..\src\Generator.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\Generator.h
# End Source File
# Begin Source File
-SOURCE=..\..\src\Instrmnt.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\Instrmnt.h
# End Source File
# Begin Source File
@@ -312,15 +296,11 @@ SOURCE=.\VoicDrum.h
# End Source File
# Begin Source File
-SOURCE=..\..\src\WaveLoop.cpp
+SOURCE=..\..\src\FileLoop.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\include\WaveLoop.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvIn.cpp
+SOURCE=..\..\include\FileLoop.h
# End Source File
# Begin Source File
@@ -328,10 +308,6 @@ SOURCE=..\..\include\WvIn.h
# End Source File
# Begin Source File
-SOURCE=..\..\src\WvOut.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\WvOut.h
# End Source File
# End Target
diff --git a/src/ADSR.cpp b/src/ADSR.cpp
index 34178e9..e609b72 100644
--- a/src/ADSR.cpp
+++ b/src/ADSR.cpp
@@ -2,33 +2,32 @@
/*! \class ADSR
\brief STK ADSR envelope class.
- This Envelope subclass implements a
- traditional ADSR (Attack, Decay,
- Sustain, Release) envelope. It
- responds to simple keyOn and keyOff
- messages, keeping track of its state.
- The \e state = ADSR::DONE after the
- envelope value reaches 0.0 in the
- ADSR::RELEASE state.
+ This class implements a traditional ADSR (Attack, Decay, Sustain,
+ Release) envelope. It responds to simple keyOn and keyOff
+ messages, keeping track of its state. The \e state = ADSR::DONE
+ after the envelope value reaches 0.0 in the ADSR::RELEASE state.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "ADSR.h"
-ADSR :: ADSR() : Envelope()
+namespace stk {
+
+ADSR :: ADSR( void )
{
target_ = 0.0;
value_ = 0.0;
attackRate_ = 0.001;
decayRate_ = 0.001;
+ releaseRate_ = 0.005;
sustainLevel_ = 0.5;
- releaseRate_ = 0.01;
state_ = ATTACK;
+ Stk::addSampleRateAlert( this );
}
-ADSR :: ~ADSR()
+ADSR :: ~ADSR( void )
{
}
@@ -44,20 +43,18 @@ void ADSR :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
void ADSR :: keyOn()
{
target_ = 1.0;
- rate_ = attackRate_;
state_ = ATTACK;
}
void ADSR :: keyOff()
{
target_ = 0.0;
- rate_ = releaseRate_;
state_ = RELEASE;
}
-void ADSR :: setAttackRate(StkFloat rate)
+void ADSR :: setAttackRate( StkFloat rate )
{
- if (rate < 0.0) {
+ if ( rate < 0.0 ) {
errorString_ << "ADSR::setAttackRate: negative rates not allowed ... correcting!";
handleError( StkError::WARNING );
attackRate_ = -rate;
@@ -65,9 +62,9 @@ void ADSR :: setAttackRate(StkFloat rate)
else attackRate_ = rate;
}
-void ADSR :: setDecayRate(StkFloat rate)
+void ADSR :: setDecayRate( StkFloat rate )
{
- if (rate < 0.0) {
+ if ( rate < 0.0 ) {
errorString_ << "ADSR::setDecayRate: negative rates not allowed ... correcting!";
handleError( StkError::WARNING );
decayRate_ = -rate;
@@ -75,9 +72,9 @@ void ADSR :: setDecayRate(StkFloat rate)
else decayRate_ = rate;
}
-void ADSR :: setSustainLevel(StkFloat level)
+void ADSR :: setSustainLevel( StkFloat level )
{
- if (level < 0.0 ) {
+ if ( level < 0.0 ) {
errorString_ << "ADSR::setSustainLevel: level out of range ... correcting!";
handleError( StkError::WARNING );
sustainLevel_ = 0.0;
@@ -85,9 +82,9 @@ void ADSR :: setSustainLevel(StkFloat level)
else sustainLevel_ = level;
}
-void ADSR :: setReleaseRate(StkFloat rate)
+void ADSR :: setReleaseRate( StkFloat rate )
{
- if (rate < 0.0) {
+ if ( rate < 0.0 ) {
errorString_ << "ADSR::setReleaseRate: negative rates not allowed ... correcting!";
handleError( StkError::WARNING );
releaseRate_ = -rate;
@@ -95,9 +92,9 @@ void ADSR :: setReleaseRate(StkFloat rate)
else releaseRate_ = rate;
}
-void ADSR :: setAttackTime(StkFloat time)
+void ADSR :: setAttackTime( StkFloat time )
{
- if (time < 0.0) {
+ if ( time < 0.0 ) {
errorString_ << "ADSR::setAttackTime: negative times not allowed ... correcting!";
handleError( StkError::WARNING );
attackRate_ = 1.0 / ( -time * Stk::sampleRate() );
@@ -105,9 +102,9 @@ void ADSR :: setAttackTime(StkFloat time)
else attackRate_ = 1.0 / ( time * Stk::sampleRate() );
}
-void ADSR :: setDecayTime(StkFloat time)
+void ADSR :: setDecayTime( StkFloat time )
{
- if (time < 0.0) {
+ if ( time < 0.0 ) {
errorString_ << "ADSR::setDecayTime: negative times not allowed ... correcting!";
handleError( StkError::WARNING );
decayRate_ = 1.0 / ( -time * Stk::sampleRate() );
@@ -115,9 +112,9 @@ void ADSR :: setDecayTime(StkFloat time)
else decayRate_ = 1.0 / ( time * Stk::sampleRate() );
}
-void ADSR :: setReleaseTime(StkFloat time)
+void ADSR :: setReleaseTime( StkFloat time )
{
- if (time < 0.0) {
+ if ( time < 0.0 ) {
errorString_ << "ADSR::setReleaseTime: negative times not allowed ... correcting!";
handleError( StkError::WARNING );
releaseRate_ = sustainLevel_ / ( -time * Stk::sampleRate() );
@@ -125,74 +122,34 @@ void ADSR :: setReleaseTime(StkFloat time)
else releaseRate_ = sustainLevel_ / ( time * Stk::sampleRate() );
}
-void ADSR :: setAllTimes(StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime)
+void ADSR :: setAllTimes( StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime )
{
- this->setAttackTime(aTime);
- this->setDecayTime(dTime);
- this->setSustainLevel(sLevel);
- this->setReleaseTime(rTime);
+ this->setAttackTime( aTime );
+ this->setDecayTime( dTime );
+ this->setSustainLevel( sLevel );
+ this->setReleaseTime( rTime );
}
-void ADSR :: setTarget(StkFloat target)
+void ADSR :: setTarget( StkFloat target )
{
target_ = target;
- if (value_ < target_) {
+ if ( value_ < target_ ) {
state_ = ATTACK;
- this->setSustainLevel(target_);
- rate_ = attackRate_;
+ this->setSustainLevel( target_ );
}
- if (value_ > target_) {
- this->setSustainLevel(target_);
+ if ( value_ > target_ ) {
+ this->setSustainLevel( target_ );
state_ = DECAY;
- rate_ = decayRate_;
}
}
-void ADSR :: setValue(StkFloat value)
+void ADSR :: setValue( StkFloat value )
{
state_ = SUSTAIN;
target_ = value;
value_ = value;
- this->setSustainLevel(value);
- rate_ = (StkFloat) 0.0;
+ this->setSustainLevel( value );
+ lastFrame_[0] = value;
}
-int ADSR :: getState(void) const
-{
- return state_;
-}
-
-StkFloat ADSR :: computeSample()
-{
- switch (state_) {
-
- case ATTACK:
- value_ += rate_;
- if (value_ >= target_) {
- value_ = target_;
- rate_ = decayRate_;
- target_ = sustainLevel_;
- state_ = DECAY;
- }
- break;
-
- case DECAY:
- value_ -= decayRate_;
- if (value_ <= sustainLevel_) {
- value_ = sustainLevel_;
- rate_ = (StkFloat) 0.0;
- state_ = SUSTAIN;
- }
- break;
-
- case RELEASE:
- value_ -= releaseRate_;
- if (value_ <= 0.0) {
- value_ = (StkFloat) 0.0;
- state_ = DONE;
- }
- }
-
- lastOutput_ = value_;
- return value_;
-}
+} // stk namespace
diff --git a/src/Asymp.cpp b/src/Asymp.cpp
index 854c2c7..3a0c25f 100644
--- a/src/Asymp.cpp
+++ b/src/Asymp.cpp
@@ -6,7 +6,7 @@
which asymptotically approaches a target value.
The algorithm used is of the form:
- x[n] = a x[n-1] + (1-a) target,
+ y[n] = a y[n-1] + (1-a) target,
where a = exp(-T/tau), T is the sample period, and
tau is a time constant. The user can set the time
@@ -19,20 +19,26 @@
to \e keyOn and \e keyOff messages by ramping to
1.0 on keyOn and to 0.0 on keyOff.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "Asymp.h"
#include
-Asymp :: Asymp(void) : Envelope()
+namespace stk {
+
+Asymp :: Asymp( void )
{
+ value_ = 0.0;
+ target_ = 0.0;
+ state_ = 0;
factor_ = exp( -1.0 / ( 0.3 * Stk::sampleRate() ) );
constant_ = 0.0;
+ Stk::addSampleRateAlert( this );
}
-Asymp :: ~Asymp(void)
+Asymp :: ~Asymp( void )
{
}
@@ -44,33 +50,31 @@ void Asymp :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
}
}
-void Asymp :: keyOn(void)
+void Asymp :: keyOn( void )
{
- Envelope::keyOn();
- constant_ = ( 1.0 - factor_ ) * target_;
+ this->setTarget( 1.0 );
}
-void Asymp :: keyOff(void)
+void Asymp :: keyOff( void )
{
- Envelope::keyOff();
- constant_ = ( 1.0 - factor_ ) * target_;
+ this->setTarget( 0.0 );
}
-void Asymp :: setTau(StkFloat tau)
+void Asymp :: setTau( StkFloat tau )
{
- if (tau <= 0.0) {
+ if ( tau <= 0.0 ) {
errorString_ << "Asymp::setTau: negative or zero tau not allowed ... ignoring!";
handleError( StkError::WARNING );
return;
}
- factor_ = std::exp( -1.0 / ( tau * Stk::sampleRate() ) );
+ factor_ = std::exp( -1.0 / ( tau * Stk::sampleRate() ) );
constant_ = ( 1.0 - factor_ ) * target_;
}
-void Asymp :: setTime(StkFloat time)
+void Asymp :: setTime( StkFloat time )
{
- if (time <= 0.0) {
+ if ( time <= 0.0 ) {
errorString_ << "Asymp::setTime: negative or zero times not allowed ... ignoring!";
handleError( StkError::WARNING );
return;
@@ -81,34 +85,19 @@ void Asymp :: setTime(StkFloat time)
constant_ = ( 1.0 - factor_ ) * target_;
}
-void Asymp :: setTarget(StkFloat target)
+void Asymp :: setTarget( StkFloat target )
{
- Envelope::setTarget( target );
+ target_ = target;
+ if ( value_ != target_ ) state_ = 1;
constant_ = ( 1.0 - factor_ ) * target_;
}
-StkFloat Asymp :: computeSample(void)
+void Asymp :: setValue( StkFloat value )
{
- if (state_) {
-
- value_ = factor_ * value_ + constant_;
-
- // Check threshold.
- if ( target_ > value_ ) {
- if ( target_ - value_ <= TARGET_THRESHOLD ) {
- value_ = target_;
- state_ = 0;
- }
- }
- else {
- if ( value_ - target_ <= TARGET_THRESHOLD ) {
- value_ = target_;
- state_ = 0;
- }
- }
- }
-
- lastOutput_ = value_;
- return value_;
+ state_ = 0;
+ target_ = value;
+ value_ = value;
}
+} // stk namespace
+
diff --git a/src/BandedWG.cpp b/src/BandedWG.cpp
index f25f52c..84e9079 100644
--- a/src/BandedWG.cpp
+++ b/src/BandedWG.cpp
@@ -25,7 +25,7 @@
- Tibetan Bowl = 3
by Georg Essl, 1999 - 2004.
- Modified for Stk 4.0 by Gary Scavone.
+ Modified for STK 4.0 by Gary Scavone.
*/
/***************************************************/
@@ -33,7 +33,9 @@
#include "SKINI.msg"
#include
-BandedWG :: BandedWG()
+namespace stk {
+
+BandedWG :: BandedWG( void )
{
doPluck_ = true;
@@ -55,22 +57,22 @@ BandedWG :: BandedWG()
strikeAmp_ = 0.0;
}
-BandedWG :: ~BandedWG()
+BandedWG :: ~BandedWG( void )
{
}
-void BandedWG :: clear()
+void BandedWG :: clear( void )
{
- for (int i=0; isetFrequency(frequency);
@@ -252,7 +254,7 @@ void BandedWG :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-void BandedWG :: noteOff(StkFloat amplitude)
+void BandedWG :: noteOff( StkFloat amplitude )
{
if ( !doPluck_ )
this->stopBowing((1.0 - amplitude) * 0.005);
@@ -263,7 +265,7 @@ void BandedWG :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat BandedWG :: computeSample()
+StkFloat BandedWG :: tick( unsigned int )
{
int k;
@@ -274,12 +276,12 @@ StkFloat BandedWG :: computeSample()
// strikeAmp_ = 0.0;
}
else {
- if (integrationConstant_ == 0.0)
+ if ( integrationConstant_ == 0.0 )
velocityInput_ = 0.0;
else
velocityInput_ = integrationConstant_ * velocityInput_;
- for (k=0; ksetRatio(0, 0.999);
- this->setRatio(1, 1.997);
- this->setRatio(2, 3.006);
- this->setRatio(3, 6.009);
+ this->setRatio( 0, 0.999 );
+ this->setRatio( 1, 1.997 );
+ this->setRatio( 2, 3.006 );
+ this->setRatio( 3, 6.009 );
gains_[0] = fmGains_[95];
gains_[1] = fmGains_[95];
gains_[2] = fmGains_[99];
gains_[3] = fmGains_[95];
- adsr_[0]->setAllTimes( 0.005, 0.003, 1.0, 0.01);
- adsr_[1]->setAllTimes( 0.005, 0.003, 1.0, 0.01);
- adsr_[2]->setAllTimes( 0.005, 0.003, 1.0, 0.01);
- adsr_[3]->setAllTimes( 0.005, 0.001, 0.4, 0.03);
+ adsr_[0]->setAllTimes( 0.005, 0.003, 1.0, 0.01 );
+ adsr_[1]->setAllTimes( 0.005, 0.003, 1.0, 0.01 );
+ adsr_[2]->setAllTimes( 0.005, 0.003, 1.0, 0.01 );
+ adsr_[3]->setAllTimes( 0.005, 0.001, 0.4, 0.03 );
twozero_.setGain( 0.1 );
}
-BeeThree :: ~BeeThree()
+BeeThree :: ~BeeThree( void )
{
}
-void BeeThree :: noteOn(StkFloat frequency, StkFloat amplitude)
+void BeeThree :: noteOn( StkFloat frequency, StkFloat amplitude )
{
gains_[0] = amplitude * fmGains_[95];
gains_[1] = amplitude * fmGains_[95];
@@ -79,28 +81,4 @@ void BeeThree :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-StkFloat BeeThree :: computeSample()
-{
- register StkFloat temp;
-
- if (modDepth_ > 0.0) {
- temp = 1.0 + (modDepth_ * vibrato_.tick() * 0.1);
- waves_[0]->setFrequency(baseFrequency_ * temp * ratios_[0]);
- waves_[1]->setFrequency(baseFrequency_ * temp * ratios_[1]);
- waves_[2]->setFrequency(baseFrequency_ * temp * ratios_[2]);
- waves_[3]->setFrequency(baseFrequency_ * temp * ratios_[3]);
- }
-
- waves_[3]->addPhaseOffset( twozero_.lastOut() );
- temp = control1_ * 2.0 * gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
- twozero_.tick(temp);
-
- temp += control2_ * 2.0 * gains_[2] * adsr_[2]->tick() * waves_[2]->tick();
- temp += gains_[1] * adsr_[1]->tick() * waves_[1]->tick();
- temp += gains_[0] * adsr_[0]->tick() * waves_[0]->tick();
-
- lastOutput_ = temp * 0.125;
- return lastOutput_;
-}
-
-
+} // stk namespace
diff --git a/src/BiQuad.cpp b/src/BiQuad.cpp
index bb6de29..e091296 100644
--- a/src/BiQuad.cpp
+++ b/src/BiQuad.cpp
@@ -2,26 +2,28 @@
/*! \class BiQuad
\brief STK biquad (two-pole, two-zero) filter class.
- This protected Filter subclass implements a
- two-pole, two-zero digital filter. A method
- is provided for creating a resonance in the
- frequency response while maintaining a constant
- filter gain.
+ This class implements a two-pole, two-zero digital filter.
+ Methods are provided for creating a resonance or notch in the
+ frequency response while maintaining a constant filter gain.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "BiQuad.h"
#include
+namespace stk {
+
BiQuad :: BiQuad() : Filter()
{
- std::vector b(3, 0.0);
- std::vector a(3, 0.0);
- b[0] = 1.0;
- a[0] = 1.0;
- Filter::setCoefficients( b, a );
+ b_.resize( 3, 0.0 );
+ a_.resize( 3, 0.0 );
+ b_[0] = 1.0;
+ a_[0] = 1.0;
+ inputs_.resize( 3, 1, 0.0 );
+ outputs_.resize( 3, 1, 0.0 );
+
Stk::addSampleRateAlert( this );
}
@@ -30,6 +32,17 @@ BiQuad :: ~BiQuad()
Stk::removeSampleRateAlert( this );
}
+void BiQuad :: setCoefficients( StkFloat b0, StkFloat b1, StkFloat b2, StkFloat a1, StkFloat a2, bool clearState )
+{
+ b_[0] = b0;
+ b_[1] = b1;
+ b_[2] = b2;
+ a_[1] = a1;
+ a_[2] = a2;
+
+ if ( clearState ) this->clear();
+}
+
void BiQuad :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
{
if ( !ignoreSampleRateChange_ ) {
@@ -38,40 +51,10 @@ void BiQuad :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
}
}
-void BiQuad :: clear(void)
-{
- Filter::clear();
-}
-
-void BiQuad :: setB0(StkFloat b0)
-{
- b_[0] = b0;
-}
-
-void BiQuad :: setB1(StkFloat b1)
-{
- b_[1] = b1;
-}
-
-void BiQuad :: setB2(StkFloat b2)
-{
- b_[2] = b2;
-}
-
-void BiQuad :: setA1(StkFloat a1)
-{
- a_[1] = a1;
-}
-
-void BiQuad :: setA2(StkFloat a2)
-{
- a_[2] = a2;
-}
-
void BiQuad :: setResonance(StkFloat frequency, StkFloat radius, bool normalize)
{
a_[2] = radius * radius;
- a_[1] = -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate());
+ a_[1] = -2.0 * radius * cos( TWO_PI * frequency / Stk::sampleRate() );
if ( normalize ) {
// Use zeros at +- 1 and normalize the filter peak gain.
@@ -85,7 +68,7 @@ void BiQuad :: setNotch(StkFloat frequency, StkFloat radius)
{
// This method does not attempt to normalize the filter gain.
b_[2] = radius * radius;
- b_[1] = (StkFloat) -2.0 * radius * cos(TWO_PI * (double) frequency / Stk::sampleRate());
+ b_[1] = (StkFloat) -2.0 * radius * cos( TWO_PI * (double) frequency / Stk::sampleRate() );
}
void BiQuad :: setEqualGainZeroes()
@@ -95,17 +78,4 @@ void BiQuad :: setEqualGainZeroes()
b_[2] = -1.0;
}
-void BiQuad :: setGain(StkFloat gain)
-{
- Filter::setGain(gain);
-}
-
-StkFloat BiQuad :: getGain(void) const
-{
- return Filter::getGain();
-}
-
-StkFloat BiQuad :: lastOut(void) const
-{
- return Filter::lastOut();
-}
+} // stk namespace
diff --git a/src/Blit.cpp b/src/Blit.cpp
index 0755a04..f6a5cad 100644
--- a/src/Blit.cpp
+++ b/src/Blit.cpp
@@ -22,8 +22,8 @@
/***************************************************/
#include "Blit.h"
-#include
-#include
+
+namespace stk {
Blit:: Blit( StkFloat frequency )
{
@@ -39,7 +39,7 @@ Blit :: ~Blit()
void Blit :: reset()
{
phase_ = 0.0;
- lastOutput_ = 0;
+ lastFrame_[0] = 0.0;
}
void Blit :: setFrequency( StkFloat frequency )
@@ -75,31 +75,4 @@ void Blit :: updateHarmonics( void )
#endif
}
-StkFloat Blit :: computeSample( void )
-{
- // The code below implements the SincM algorithm of Stilson and
- // Smith with an additional scale factor of P / M applied to
- // normalize the output.
-
- // A fully optimized version of this code would replace the two sin
- // calls with a pair of fast sin oscillators, for which stable fast
- // two-multiply algorithms are well known. In the spirit of STK,
- // which favors clarity over performance, the optimization has not
- // been made here.
-
- // Avoid a divide by zero at the sinc peak, which has a limiting
- // value of 1.0.
- StkFloat denominator = sin( phase_ );
- if ( denominator <= std::numeric_limits::epsilon() ) {
- lastOutput_ = 1.0;
- } else {
- lastOutput_ = sin( m_ * phase_ );
- lastOutput_ /= m_ * denominator;
- }
-
- phase_ += rate_;
- if ( phase_ >= PI ) phase_ -= PI;
-
- return lastOutput_;
-}
-
+} // stk namespace
diff --git a/src/BlitSaw.cpp b/src/BlitSaw.cpp
index 42908e3..abde294 100644
--- a/src/BlitSaw.cpp
+++ b/src/BlitSaw.cpp
@@ -20,8 +20,8 @@
/***************************************************/
#include "BlitSaw.h"
-#include
-#include
+
+namespace stk {
BlitSaw:: BlitSaw( StkFloat frequency )
{
@@ -38,7 +38,7 @@ void BlitSaw :: reset()
{
phase_ = 0.0f;
state_ = 0.0;
- lastOutput_ = 0;
+ lastFrame_[0] = 0.0;
}
void BlitSaw :: setFrequency( StkFloat frequency )
@@ -88,38 +88,4 @@ void BlitSaw :: updateHarmonics( void )
#endif
}
-StkFloat BlitSaw :: computeSample( void )
-{
- // The code below implements the BLIT algorithm of Stilson and
- // Smith, followed by a summation and filtering operation to produce
- // a sawtooth waveform. After experimenting with various approaches
- // to calculate the average value of the BLIT over one period, I
- // found that an estimate of C2_ = 1.0 / period (in samples) worked
- // most consistently. A "leaky integrator" is then applied to the
- // difference of the BLIT output and C2_. (GPS - 1 October 2005)
-
- // A fully optimized version of this code would replace the two sin
- // calls with a pair of fast sin oscillators, for which stable fast
- // two-multiply algorithms are well known. In the spirit of STK,
- // which favors clarity over performance, the optimization has
- // not been made here.
-
- // Avoid a divide by zero, or use of a denormalized divisor
- // at the sinc peak, which has a limiting value of m_ / p_.
- StkFloat denominator = sin( phase_ );
- if ( fabs(denominator) <= std::numeric_limits::epsilon() )
- lastOutput_ = a_;
- else {
- lastOutput_ = sin( m_ * phase_ );
- lastOutput_ /= p_ * denominator;
- }
-
- lastOutput_ += state_ - C2_;
- state_ = lastOutput_ * 0.995;
-
- phase_ += rate_;
- if ( phase_ >= PI ) phase_ -= PI;
-
- return lastOutput_;
-}
-
+} // stk namespace
diff --git a/src/BlitSquare.cpp b/src/BlitSquare.cpp
index d26cc18..330756a 100644
--- a/src/BlitSquare.cpp
+++ b/src/BlitSquare.cpp
@@ -25,14 +25,14 @@
Blit waveforms. This class is not guaranteed to be well behaved
in the presence of significant aliasing.
- Based on initial code of Robin Davies, 2005.
- Modified algorithm code by Gary Scavone, 2005 - 2006.
+ Based on initial code of Robin Davies, 2005
+ Modified algorithm code by Gary Scavone, 2005 - 2009.
*/
/***************************************************/
#include "BlitSquare.h"
-#include
-#include
+
+namespace stk {
BlitSquare:: BlitSquare( StkFloat frequency )
{
@@ -48,7 +48,7 @@ BlitSquare :: ~BlitSquare()
void BlitSquare :: reset()
{
phase_ = 0.0;
- lastOutput_ = 0;
+ lastFrame_[0] = 0.0;
dcbState_ = 0.0;
lastBlitOutput_ = 0;
}
@@ -92,40 +92,4 @@ void BlitSquare :: updateHarmonics( void )
#endif
}
-StkFloat BlitSquare :: computeSample( void )
-{
- StkFloat temp = lastBlitOutput_;
-
- // A fully optimized version of this would replace the two sin calls
- // with a pair of fast sin oscillators, for which stable fast
- // two-multiply algorithms are well known. In the spirit of STK,
- // which favors clarity over performance, the optimization has
- // not been made here.
-
- // Avoid a divide by zero, or use of a denomralized divisor
- // at the sinc peak, which has a limiting value of 1.0.
- StkFloat denominator = sin( phase_ );
- if ( fabs( denominator ) < std::numeric_limits::epsilon() ) {
- // Inexact comparison safely distinguishes betwen *close to zero*, and *close to PI*.
- if ( phase_ < 0.1f || phase_ > TWO_PI - 0.1f )
- lastBlitOutput_ = a_;
- else
- lastBlitOutput_ = -a_;
- }
- else {
- lastBlitOutput_ = sin( m_ * phase_ );
- lastBlitOutput_ /= p_ * denominator;
- }
-
- lastBlitOutput_ += temp;
-
- // Now apply DC blocker.
- lastOutput_ = lastBlitOutput_ - dcbState_ + 0.999 * lastOutput_;
- dcbState_ = lastBlitOutput_;
-
- phase_ += rate_;
- if ( phase_ >= TWO_PI ) phase_ -= TWO_PI;
-
- return lastOutput_;
-}
-
+} // stk namespace
diff --git a/src/BlowBotl.cpp b/src/BlowBotl.cpp
index 63abf41..25ba8bb 100644
--- a/src/BlowBotl.cpp
+++ b/src/BlowBotl.cpp
@@ -12,16 +12,18 @@
- Vibrato Gain = 1
- Volume = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "BlowBotl.h"
#include "SKINI.msg"
+namespace stk {
+
#define __BOTTLE_RADIUS_ 0.999
-BlowBotl :: BlowBotl()
+BlowBotl :: BlowBotl( void )
{
dcBlock_.setBlockZero();
@@ -35,16 +37,16 @@ BlowBotl :: BlowBotl()
maxPressure_ = (StkFloat) 0.0;
}
-BlowBotl :: ~BlowBotl()
+BlowBotl :: ~BlowBotl( void )
{
}
-void BlowBotl :: clear()
+void BlowBotl :: clear( void )
{
resonator_.clear();
}
-void BlowBotl :: setFrequency(StkFloat frequency)
+void BlowBotl :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
@@ -56,20 +58,20 @@ void BlowBotl :: setFrequency(StkFloat frequency)
resonator_.setResonance( freakency, __BOTTLE_RADIUS_, true );
}
-void BlowBotl :: startBlowing(StkFloat amplitude, StkFloat rate)
+void BlowBotl :: startBlowing( StkFloat amplitude, StkFloat rate )
{
adsr_.setAttackRate(rate);
maxPressure_ = amplitude;
adsr_.keyOn();
}
-void BlowBotl :: stopBlowing(StkFloat rate)
+void BlowBotl :: stopBlowing( StkFloat rate )
{
adsr_.setReleaseRate(rate);
adsr_.keyOff();
}
-void BlowBotl :: noteOn(StkFloat frequency, StkFloat amplitude)
+void BlowBotl :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency(frequency);
startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02);
@@ -81,7 +83,7 @@ void BlowBotl :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-void BlowBotl :: noteOff(StkFloat amplitude)
+void BlowBotl :: noteOff( StkFloat amplitude )
{
this->stopBlowing(amplitude * 0.02);
@@ -91,29 +93,7 @@ void BlowBotl :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat BlowBotl :: computeSample()
-{
- StkFloat breathPressure;
- StkFloat randPressure;
- StkFloat pressureDiff;
-
- // Calculate the breath pressure (envelope + vibrato)
- breathPressure = maxPressure_ * adsr_.tick();
- breathPressure += vibratoGain_ * vibrato_.tick();
-
- pressureDiff = breathPressure - resonator_.lastOut();
-
- randPressure = noiseGain_ * noise_.tick();
- randPressure *= breathPressure;
- randPressure *= (1.0 + pressureDiff);
-
- resonator_.tick( breathPressure + randPressure - ( jetTable_.tick( pressureDiff ) * pressureDiff ) );
- lastOutput_ = 0.2 * outputGain_ * dcBlock_.tick( pressureDiff );
-
- return lastOutput_;
-}
-
-void BlowBotl :: controlChange(int number, StkFloat value)
+void BlowBotl :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
@@ -145,3 +125,5 @@ void BlowBotl :: controlChange(int number, StkFloat value)
handleError( StkError::DEBUG_WARNING );
#endif
}
+
+} // stk namespace
diff --git a/src/BlowHole.cpp b/src/BlowHole.cpp
index 8bf8116..ec271f1 100644
--- a/src/BlowHole.cpp
+++ b/src/BlowHole.cpp
@@ -29,17 +29,19 @@
- Register State = 1
- Breath Pressure = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "BlowHole.h"
#include "SKINI.msg"
-#include
+#include
-BlowHole :: BlowHole(StkFloat lowestFrequency)
+namespace stk {
+
+BlowHole :: BlowHole( StkFloat lowestFrequency )
{
- length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
+ length_ = (unsigned long) ( Stk::sampleRate() / lowestFrequency + 1 );
// delays[0] is the delay line between the reed and the register vent.
delays_[0].setDelay( 5.0 * Stk::sampleRate() / 22050.0 );
// delays[1] is the delay line between the register vent and the tonehole.
@@ -83,11 +85,11 @@ BlowHole :: BlowHole(StkFloat lowestFrequency)
vibratoGain_ = 0.01;
}
-BlowHole :: ~BlowHole()
+BlowHole :: ~BlowHole( void )
{
}
-void BlowHole :: clear()
+void BlowHole :: clear( void )
{
delays_[0].clear();
delays_[1].clear();
@@ -97,7 +99,7 @@ void BlowHole :: clear()
vent_.tick( 0.0 );
}
-void BlowHole :: setFrequency(StkFloat frequency)
+void BlowHole :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
@@ -114,7 +116,7 @@ void BlowHole :: setFrequency(StkFloat frequency)
delays_[1].setDelay(delay);
}
-void BlowHole :: setVent(StkFloat newValue)
+void BlowHole :: setVent( StkFloat newValue )
{
// This method allows setting of the register vent "open-ness" at
// any point between "Open" (newValue = 1) and "Closed"
@@ -132,7 +134,7 @@ void BlowHole :: setVent(StkFloat newValue)
vent_.setGain( gain );
}
-void BlowHole :: setTonehole(StkFloat newValue)
+void BlowHole :: setTonehole( StkFloat newValue )
{
// This method allows setting of the tonehole "open-ness" at
// any point between "Open" (newValue = 1) and "Closed"
@@ -150,19 +152,19 @@ void BlowHole :: setTonehole(StkFloat newValue)
tonehole_.setB0( new_coeff );
}
-void BlowHole :: startBlowing(StkFloat amplitude, StkFloat rate)
+void BlowHole :: startBlowing( StkFloat amplitude, StkFloat rate )
{
envelope_.setRate( rate );
envelope_.setTarget( amplitude );
}
-void BlowHole :: stopBlowing(StkFloat rate)
+void BlowHole :: stopBlowing( StkFloat rate )
{
envelope_.setRate( rate );
envelope_.setTarget( 0.0 );
}
-void BlowHole :: noteOn(StkFloat frequency, StkFloat amplitude)
+void BlowHole :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency( frequency );
this->startBlowing( 0.55 + (amplitude * 0.30), amplitude * 0.005 );
@@ -174,7 +176,7 @@ void BlowHole :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-void BlowHole :: noteOff(StkFloat amplitude)
+void BlowHole :: noteOff( StkFloat amplitude )
{
this->stopBlowing( amplitude * 0.01 );
@@ -184,42 +186,7 @@ void BlowHole :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat BlowHole :: computeSample()
-{
- StkFloat pressureDiff;
- StkFloat breathPressure;
- StkFloat temp;
-
- // Calculate the breath pressure (envelope + noise + vibrato)
- breathPressure = envelope_.tick();
- breathPressure += breathPressure * noiseGain_ * noise_.tick();
- breathPressure += breathPressure * vibratoGain_ * vibrato_.tick();
-
- // Calculate the differential pressure = reflected - mouthpiece pressures
- pressureDiff = delays_[0].lastOut() - breathPressure;
-
- // Do two-port junction scattering for register vent
- StkFloat pa = breathPressure + pressureDiff * reedTable_.tick( pressureDiff );
- StkFloat pb = delays_[1].lastOut();
- vent_.tick( pa+pb );
-
- lastOutput_ = delays_[0].tick( vent_.lastOut()+pb );
- lastOutput_ *= outputGain_;
-
- // Do three-port junction scattering (under tonehole)
- pa += vent_.lastOut();
- pb = delays_[2].lastOut();
- StkFloat pth = tonehole_.lastOut();
- temp = scatter_ * (pa + pb - 2 * pth);
-
- delays_[2].tick( filter_.tick(pa + temp) * -0.95 );
- delays_[1].tick( pb + temp );
- tonehole_.tick( pa + pb - pth + temp );
-
- return lastOutput_;
-}
-
-void BlowHole :: controlChange(int number, StkFloat value)
+void BlowHole :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
@@ -253,3 +220,5 @@ void BlowHole :: controlChange(int number, StkFloat value)
handleError( StkError::DEBUG_WARNING );
#endif
}
+
+} // stk namespace
diff --git a/src/BowTable.cpp b/src/BowTable.cpp
deleted file mode 100644
index f5b23e7..0000000
--- a/src/BowTable.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/***************************************************/
-/*! \class BowTable
- \brief STK bowed string table class.
-
- This class implements a simple bowed string
- non-linear function, as described by Smith (1986).
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
-#include "BowTable.h"
-#include
-
-BowTable :: BowTable()
-{
- offset_ = (StkFloat) 0.0;
- slope_ = (StkFloat) 0.1;
-}
-
-BowTable :: ~BowTable()
-{
-}
-
-void BowTable :: setOffset(StkFloat offset)
-{
- offset_ = offset;
-}
-
-void BowTable :: setSlope(StkFloat slope)
-{
- slope_ = slope;
-}
-
-StkFloat BowTable :: computeSample(StkFloat input)
-{
- // The input represents differential string vs. bow velocity.
- StkFloat sample;
- sample = input + offset_; // add bias to input
- sample *= slope_; // then scale it
- lastOutput_ = (StkFloat) fabs( (double) sample ) + (StkFloat) 0.75;
- lastOutput_ = (StkFloat) pow( lastOutput_, (StkFloat) -4.0 );
-
- // Set minimum friction to 0.0
- // if (lastOutput < 0.0 ) lastOutput = 0.0;
- // Set maximum friction to 1.0.
- if (lastOutput_ > 1.0 ) lastOutput_ = (StkFloat) 1.0;
-
- return lastOutput_;
-}
-
diff --git a/src/Bowed.cpp b/src/Bowed.cpp
index 586fec3..d314ed6 100644
--- a/src/Bowed.cpp
+++ b/src/Bowed.cpp
@@ -17,14 +17,16 @@
- Vibrato Gain = 1
- Volume = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "Bowed.h"
#include "SKINI.msg"
-Bowed :: Bowed(StkFloat lowestFrequency)
+namespace stk {
+
+Bowed :: Bowed( StkFloat lowestFrequency )
{
unsigned long length;
length = (long) ( Stk::sampleRate() / lowestFrequency + 1 );
@@ -54,17 +56,17 @@ Bowed :: Bowed(StkFloat lowestFrequency)
this->setFrequency( 220.0 );
}
-Bowed :: ~Bowed()
+Bowed :: ~Bowed( void )
{
}
-void Bowed :: clear()
+void Bowed :: clear( void )
{
neckDelay_.clear();
bridgeDelay_.clear();
}
-void Bowed :: setFrequency(StkFloat frequency)
+void Bowed :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
@@ -80,20 +82,20 @@ void Bowed :: setFrequency(StkFloat frequency)
neckDelay_.setDelay( baseDelay_ * (1.0 - betaRatio_) ); // bow to nut (finger) length
}
-void Bowed :: startBowing(StkFloat amplitude, StkFloat rate)
+void Bowed :: startBowing( StkFloat amplitude, StkFloat rate )
{
- adsr_.setRate( rate );
+ adsr_.setAttackRate( rate );
adsr_.keyOn();
maxVelocity_ = 0.03 + ( 0.2 * amplitude );
}
-void Bowed :: stopBowing(StkFloat rate)
+void Bowed :: stopBowing( StkFloat rate )
{
- adsr_.setRate( rate );
+ adsr_.setReleaseRate( rate );
adsr_.keyOff();
}
-void Bowed :: noteOn(StkFloat frequency, StkFloat amplitude)
+void Bowed :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->startBowing( amplitude, amplitude * 0.001 );
this->setFrequency( frequency );
@@ -104,7 +106,7 @@ void Bowed :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-void Bowed :: noteOff(StkFloat amplitude)
+void Bowed :: noteOff( StkFloat amplitude )
{
this->stopBowing( (1.0 - amplitude) * 0.005 );
@@ -114,41 +116,12 @@ void Bowed :: noteOff(StkFloat amplitude)
#endif
}
-void Bowed :: setVibrato(StkFloat gain)
+void Bowed :: setVibrato( StkFloat gain )
{
vibratoGain_ = gain;
}
-StkFloat Bowed :: computeSample()
-{
- StkFloat bowVelocity;
- StkFloat bridgeRefl;
- StkFloat nutRefl;
- StkFloat newVel;
- StkFloat velDiff;
- StkFloat stringVel;
-
- bowVelocity = maxVelocity_ * adsr_.tick();
-
- bridgeRefl = -stringFilter_.tick( bridgeDelay_.lastOut() );
- nutRefl = -neckDelay_.lastOut();
- stringVel = bridgeRefl + nutRefl; // Sum is String Velocity
- velDiff = bowVelocity - stringVel; // Differential Velocity
- newVel = velDiff * bowTable_.tick( velDiff ); // Non-Linear Bow Function
- neckDelay_.tick(bridgeRefl + newVel); // Do string propagations
- bridgeDelay_.tick(nutRefl + newVel);
-
- if ( vibratoGain_ > 0.0 ) {
- neckDelay_.setDelay( (baseDelay_ * (1.0 - betaRatio_) ) +
- (baseDelay_ * vibratoGain_ * vibrato_.tick()) );
- }
-
- lastOutput_ = bodyFilter_.tick( bridgeDelay_.lastOut() );
-
- return lastOutput_;
-}
-
-void Bowed :: controlChange(int number, StkFloat value)
+void Bowed :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
@@ -185,3 +158,5 @@ void Bowed :: controlChange(int number, StkFloat value)
handleError( StkError::DEBUG_WARNING );
#endif
}
+
+} // stk namespace
diff --git a/src/Brass.cpp b/src/Brass.cpp
index edc9cf9..c346ead 100644
--- a/src/Brass.cpp
+++ b/src/Brass.cpp
@@ -16,7 +16,7 @@
- Vibrato Gain = 1
- Volume = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
@@ -24,16 +24,18 @@
#include "SKINI.msg"
#include
-Brass :: Brass(StkFloat lowestFrequency)
+namespace stk {
+
+Brass :: Brass( StkFloat lowestFrequency )
{
- length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
+ length_ = (unsigned long) ( Stk::sampleRate() / lowestFrequency + 1 );
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( 0.5 * length_ );
lipFilter_.setGain( 0.03 );
dcBlock_.setBlockZero();
- adsr_.setAllTimes( 0.005, 0.001, 1.0, 0.010);
+ adsr_.setAllTimes( 0.005, 0.001, 1.0, 0.010 );
vibrato_.setFrequency( 6.137 );
vibratoGain_ = 0.0;
@@ -46,18 +48,18 @@ Brass :: Brass(StkFloat lowestFrequency)
this->setFrequency( 220.0 );
}
-Brass :: ~Brass()
+Brass :: ~Brass( void )
{
}
-void Brass :: clear()
+void Brass :: clear( void )
{
delayLine_.clear();
lipFilter_.clear();
dcBlock_.clear();
}
-void Brass :: setFrequency(StkFloat frequency)
+void Brass :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
@@ -74,7 +76,7 @@ void Brass :: setFrequency(StkFloat frequency)
lipFilter_.setResonance( freakency, 0.997 );
}
-void Brass :: setLip(StkFloat frequency)
+void Brass :: setLip( StkFloat frequency )
{
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
@@ -86,20 +88,20 @@ void Brass :: setLip(StkFloat frequency)
lipFilter_.setResonance( freakency, 0.997 );
}
-void Brass :: startBlowing(StkFloat amplitude, StkFloat rate)
+void Brass :: startBlowing( StkFloat amplitude, StkFloat rate )
{
adsr_.setAttackRate( rate );
maxPressure_ = amplitude;
adsr_.keyOn();
}
-void Brass :: stopBlowing(StkFloat rate)
+void Brass :: stopBlowing( StkFloat rate )
{
adsr_.setReleaseRate( rate );
adsr_.keyOff();
}
-void Brass :: noteOn(StkFloat frequency, StkFloat amplitude)
+void Brass :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency( frequency );
this->startBlowing( amplitude, amplitude * 0.001 );
@@ -110,7 +112,7 @@ void Brass :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-void Brass :: noteOff(StkFloat amplitude)
+void Brass :: noteOff( StkFloat amplitude )
{
this->stopBlowing( amplitude * 0.005 );
@@ -120,26 +122,7 @@ void Brass :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat Brass :: computeSample()
-{
- StkFloat breathPressure = maxPressure_ * adsr_.tick();
- breathPressure += vibratoGain_ * vibrato_.tick();
-
- StkFloat mouthPressure = 0.3 * breathPressure;
- StkFloat borePressure = 0.85 * delayLine_.lastOut();
- StkFloat deltaPressure = mouthPressure - borePressure; // Differential pressure.
- deltaPressure = lipFilter_.tick( deltaPressure ); // Force - > position.
- deltaPressure *= deltaPressure; // Basic position to area mapping.
- if ( deltaPressure > 1.0 ) deltaPressure = 1.0; // Non-linear saturation.
-
- // The following input scattering assumes the mouthPressure = area.
- lastOutput_ = deltaPressure * mouthPressure + ( 1.0 - deltaPressure) * borePressure;
- lastOutput_ = delayLine_.tick( dcBlock_.tick( lastOutput_ ) );
-
- return lastOutput_;
-}
-
-void Brass :: controlChange(int number, StkFloat value)
+void Brass :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
@@ -175,3 +158,5 @@ void Brass :: controlChange(int number, StkFloat value)
handleError( StkError::DEBUG_WARNING );
#endif
}
+
+} // stk namespace
diff --git a/src/Chorus.cpp b/src/Chorus.cpp
index b3ed8a9..d0f58de 100644
--- a/src/Chorus.cpp
+++ b/src/Chorus.cpp
@@ -2,60 +2,45 @@
/*! \class Chorus
\brief STK chorus effect class.
- This class implements a chorus effect.
+ This class implements a chorus effect. It takes a monophonic
+ input signal and produces a stereo output signal.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "Chorus.h"
-#include
-Chorus :: Chorus(StkFloat baseDelay)
+namespace stk {
+
+Chorus :: Chorus( StkFloat baseDelay )
{
+ lastFrame_.resize( 1, 2, 0.0 ); // resize lastFrame_ for stereo output
delayLine_[0].setMaximumDelay( (unsigned long) (baseDelay * 1.414) + 2);
delayLine_[0].setDelay( baseDelay );
delayLine_[1].setMaximumDelay( (unsigned long) (baseDelay * 1.414) + 2);
delayLine_[1].setDelay( baseDelay );
baseLength_ = baseDelay;
- mods_[0].setFrequency(0.2);
- mods_[1].setFrequency(0.222222);
+ mods_[0].setFrequency( 0.2 );
+ mods_[1].setFrequency( 0.222222 );
modDepth_ = 0.05;
effectMix_ = 0.5;
this->clear();
}
-Chorus :: ~Chorus()
-{
-}
-
-void Chorus :: clear()
+void Chorus :: clear( void )
{
delayLine_[0].clear();
delayLine_[1].clear();
- lastOutput_[0] = 0.0;
- lastOutput_[1] = 0.0;
+ lastFrame_[0] = 0.0;
+ lastFrame_[1] = 0.0;
}
-void Chorus :: setModDepth(StkFloat depth)
+void Chorus :: setModFrequency( StkFloat frequency )
{
- modDepth_ = depth;
+ mods_[0].setFrequency( frequency );
+ mods_[1].setFrequency( frequency * 1.1111 );
}
-void Chorus :: setModFrequency(StkFloat frequency)
-{
- mods_[0].setFrequency(frequency);
- mods_[1].setFrequency(frequency * 1.1111);
-}
-
-StkFloat Chorus :: computeSample(StkFloat input)
-{
- delayLine_[0].setDelay( baseLength_ * 0.707 * (1.0 + modDepth_ * mods_[0].tick()) );
- delayLine_[1].setDelay( baseLength_ * 0.5 * (1.0 - modDepth_ * mods_[1].tick()) );
- lastOutput_[0] = input * (1.0 - effectMix_);
- lastOutput_[0] += effectMix_ * delayLine_[0].tick(input);
- lastOutput_[1] = input * (1.0 - effectMix_);
- lastOutput_[1] += effectMix_ * delayLine_[1].tick(input);
- return Effect::lastOut();
-}
+} // stk namespace
diff --git a/src/Clarinet.cpp b/src/Clarinet.cpp
index bd19a52..2c5856d 100644
--- a/src/Clarinet.cpp
+++ b/src/Clarinet.cpp
@@ -18,14 +18,16 @@
- Vibrato Gain = 1
- Breath Pressure = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "Clarinet.h"
#include "SKINI.msg"
-Clarinet :: Clarinet(StkFloat lowestFrequency)
+namespace stk {
+
+Clarinet :: Clarinet( StkFloat lowestFrequency )
{
length_ = (long) (Stk::sampleRate() / lowestFrequency + 1);
delayLine_.setMaximumDelay( length_ );
@@ -39,17 +41,17 @@ Clarinet :: Clarinet(StkFloat lowestFrequency)
vibratoGain_ = (StkFloat) 0.1;
}
-Clarinet :: ~Clarinet()
+Clarinet :: ~Clarinet( void )
{
}
-void Clarinet :: clear()
+void Clarinet :: clear( void )
{
delayLine_.clear();
filter_.tick( 0.0 );
}
-void Clarinet :: setFrequency(StkFloat frequency)
+void Clarinet :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
@@ -65,19 +67,19 @@ void Clarinet :: setFrequency(StkFloat frequency)
delayLine_.setDelay(delay);
}
-void Clarinet :: startBlowing(StkFloat amplitude, StkFloat rate)
+void Clarinet :: startBlowing( StkFloat amplitude, StkFloat rate )
{
envelope_.setRate(rate);
envelope_.setTarget(amplitude);
}
-void Clarinet :: stopBlowing(StkFloat rate)
+void Clarinet :: stopBlowing( StkFloat rate )
{
envelope_.setRate(rate);
envelope_.setTarget((StkFloat) 0.0);
}
-void Clarinet :: noteOn(StkFloat frequency, StkFloat amplitude)
+void Clarinet :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency(frequency);
this->startBlowing((StkFloat) 0.55 + (amplitude * (StkFloat) 0.30), amplitude * (StkFloat) 0.005);
@@ -89,7 +91,7 @@ void Clarinet :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-void Clarinet :: noteOff(StkFloat amplitude)
+void Clarinet :: noteOff( StkFloat amplitude )
{
this->stopBlowing( amplitude * 0.01 );
@@ -99,32 +101,7 @@ void Clarinet :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat Clarinet :: computeSample()
-{
- StkFloat pressureDiff;
- StkFloat breathPressure;
-
- // Calculate the breath pressure (envelope + noise + vibrato)
- breathPressure = envelope_.tick();
- breathPressure += breathPressure * noiseGain_ * noise_.tick();
- breathPressure += breathPressure * vibratoGain_ * vibrato_.tick();
-
- // Perform commuted loss filtering.
- pressureDiff = -0.95 * filter_.tick(delayLine_.lastOut());
-
- // Calculate pressure difference of reflected and mouthpiece pressures.
- pressureDiff = pressureDiff - breathPressure;
-
- // Perform non-linear scattering using pressure difference in reed function.
- lastOutput_ = delayLine_.tick(breathPressure + pressureDiff * reedTable_.tick(pressureDiff));
-
- // Apply output gain.
- lastOutput_ *= outputGain_;
-
- return lastOutput_;
-}
-
-void Clarinet :: controlChange(int number, StkFloat value)
+void Clarinet :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
@@ -158,3 +135,5 @@ void Clarinet :: controlChange(int number, StkFloat value)
handleError( StkError::DEBUG_WARNING );
#endif
}
+
+} // stk namespace
diff --git a/src/Delay.cpp b/src/Delay.cpp
index b14501c..aedec9a 100644
--- a/src/Delay.cpp
+++ b/src/Delay.cpp
@@ -2,36 +2,23 @@
/*! \class Delay
\brief STK non-interpolating delay line class.
- This protected Filter subclass implements
- a non-interpolating digital delay-line.
- A fixed maximum length of 4095 and a delay
- of zero is set using the default constructor.
- Alternatively, the delay and maximum length
- can be set during instantiation with an
- overloaded constructor.
+ This class implements a non-interpolating digital delay-line. If
+ the delay and maximum length are not specified during
+ instantiation, a fixed maximum length of 4095 and a delay of zero
+ is set.
- A non-interpolating delay line is typically
- used in fixed delay-length applications, such
- as for reverberation.
+ A non-interpolating delay line is typically used in fixed
+ delay-length applications, such as for reverberation.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "Delay.h"
-Delay :: Delay() : Filter()
-{
- // Default maximum delay length set to 4095.
- inputs_.resize( 4096 );
- this->clear();
+namespace stk {
- inPoint_ = 0;
- outPoint_ = 0;
- delay_ = 0;
-}
-
-Delay :: Delay(unsigned long delay, unsigned long maxDelay)
+Delay :: Delay( unsigned long delay, unsigned long maxDelay )
{
// Writing before reading allows delays from 0 to length-1.
// If we want to allow a delay of maxDelay, we need a
@@ -46,10 +33,8 @@ Delay :: Delay(unsigned long delay, unsigned long maxDelay)
handleError( StkError::FUNCTION_ARGUMENT );
}
- if ( maxDelay > inputs_.size()-1 ) {
- inputs_.resize( maxDelay+1 );
- this->clear();
- }
+ if ( ( maxDelay + 1 ) > inputs_.size() )
+ inputs_.resize( maxDelay + 1, 1, 0.0 );
inPoint_ = 0;
this->setDelay( delay );
@@ -59,14 +44,7 @@ Delay :: ~Delay()
{
}
-void Delay :: clear(void)
-{
- for (unsigned int i=0; i inputs_.size() - 1 ) { // The value is too big.
errorString_ << "Delay::setDelay: argument (" << delay << ") too big ... setting to maximum!\n";
@@ -109,26 +87,21 @@ void Delay :: setDelay(unsigned long delay)
}
}
-unsigned long Delay :: getDelay(void) const
-{
- return (unsigned long) delay_;
-}
-
-StkFloat Delay :: energy(void) const
+StkFloat Delay :: energy( void ) const
{
unsigned long i;
register StkFloat e = 0;
- if (inPoint_ >= outPoint_) {
- for (i=outPoint_; i= outPoint_ ) {
+ for ( i=outPoint_; i delay_) {
- errorString_ << "Delay::contentsAt: argument (" << tapDelay << ") too big!";
- handleError( StkError::WARNING );
- return 0.0;
- }
-
- long tap = inPoint_ - i;
- if (tap < 0) // Check for wraparound.
+ long tap = inPoint_ - tapDelay - 1;
+ while ( tap < 0 ) // Check for wraparound.
tap += inputs_.size();
return inputs_[tap];
}
-StkFloat Delay :: lastOut(void) const
-{
- return Filter::lastOut();
-}
-
-StkFloat Delay :: nextOut(void)
-{
- return inputs_[outPoint_];
-}
-
-StkFloat Delay :: computeSample( StkFloat input )
-{
- inputs_[inPoint_++] = input;
-
- // Check for end condition
- if (inPoint_ == inputs_.size())
- inPoint_ = 0;
-
- // Read out next value
- outputs_[0] = inputs_[outPoint_++];
-
- if (outPoint_ == inputs_.size())
- outPoint_ = 0;
-
- return outputs_[0];
-}
-
-StkFloat Delay :: tick( StkFloat input )
-{
- return computeSample( input );
-}
-
-StkFrames& Delay :: tick( StkFrames& frames, unsigned int channel )
-{
- return Filter::tick( frames, channel );
-}
+} // stk namespace
diff --git a/src/DelayA.cpp b/src/DelayA.cpp
index 19df1e6..31454da 100644
--- a/src/DelayA.cpp
+++ b/src/DelayA.cpp
@@ -2,11 +2,10 @@
/*! \class DelayA
\brief STK allpass interpolating delay line class.
- This Delay subclass implements a fractional-length digital
- delay-line using a first-order allpass filter. A fixed maximum
- length of 4095 and a delay of 0.5 is set using the default
- constructor. Alternatively, the delay and maximum length can be
- set during instantiation with an overloaded constructor.
+ This class implements a fractional-length digital delay-line using
+ a first-order allpass filter. If the delay and maximum length are
+ not specified during instantiation, a fixed maximum length of 4095
+ and a delay of zero is set.
An allpass filter has unity magnitude gain but variable phase
delay properties, making it useful in achieving fractional delays
@@ -15,23 +14,18 @@
minimum delay possible in this implementation is limited to a
value of 0.5.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "DelayA.h"
-DelayA :: DelayA() : Delay()
-{
- this->setDelay( 0.5 );
- apInput_ = 0.0;
- doNextOut_ = true;
-}
+namespace stk {
-DelayA :: DelayA(StkFloat delay, unsigned long maxDelay)
+DelayA :: DelayA( StkFloat delay, unsigned long maxDelay )
{
- if ( delay < 0.0 || maxDelay < 1 ) {
- errorString_ << "DelayA::DelayA: delay must be >= 0.0, maxDelay must be > 0!";
+ if ( delay < 0.5 || maxDelay < 1 ) {
+ errorString_ << "DelayA::DelayA: delay must be >= 0.5, maxDelay must be > 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -41,13 +35,11 @@ DelayA :: DelayA(StkFloat delay, unsigned long maxDelay)
}
// Writing before reading allows delays from 0 to length-1.
- if ( maxDelay > inputs_.size()-1 ) {
- inputs_.resize( maxDelay+1 );
- this->clear();
- }
+ if ( maxDelay + 1 > inputs_.size() )
+ inputs_.resize( maxDelay + 1, 1, 0.0 );
inPoint_ = 0;
- this->setDelay(delay);
+ this->setDelay( delay );
apInput_ = 0.0;
doNextOut_ = true;
}
@@ -58,16 +50,36 @@ DelayA :: ~DelayA()
void DelayA :: clear()
{
- Delay::clear();
+ for ( unsigned int i=0; i inputs_.size() - 1 ) { // The value is too big.
+ if ( delay + 1 > length ) { // The value is too big.
errorString_ << "DelayA::setDelay: argument (" << delay << ") too big ... setting to maximum!";
handleError( StkError::WARNING );
@@ -75,7 +87,7 @@ void DelayA :: setDelay(StkFloat delay)
outPointer = inPoint_ + 1.0;
delay_ = length - 1;
}
- else if (delay < 0.5) {
+ else if ( delay < 0.5 ) {
errorString_ << "DelayA::setDelay: argument (" << delay << ") less than 0.5 not possible!";
handleError( StkError::WARNING );
@@ -87,14 +99,14 @@ void DelayA :: setDelay(StkFloat delay)
delay_ = delay;
}
- if (outPointer < 0)
+ while ( outPointer < 0 )
outPointer += length; // modulo maximum length
outPoint_ = (long) outPointer; // integer part
if ( outPoint_ == length ) outPoint_ = 0;
alpha_ = 1.0 + outPoint_ - outPointer; // fractional part
- if (alpha_ < 0.5) {
+ if ( alpha_ < 0.5 ) {
// The optimal range for alpha is about 0.5 - 1.5 in order to
// achieve the flattest phase delay response.
outPoint_ += 1;
@@ -106,38 +118,13 @@ void DelayA :: setDelay(StkFloat delay)
((StkFloat) 1.0 + alpha_); // coefficient for all pass
}
-StkFloat DelayA :: getDelay(void) const
+StkFloat DelayA :: contentsAt( unsigned long tapDelay )
{
- return delay_;
+ long tap = inPoint_ - tapDelay - 1;
+ while ( tap < 0 ) // Check for wraparound.
+ tap += inputs_.size();
+
+ return inputs_[tap];
}
-StkFloat DelayA :: nextOut(void)
-{
- if ( doNextOut_ ) {
- // Do allpass interpolation delay.
- nextOutput_ = -coeff_ * outputs_[0];
- nextOutput_ += apInput_ + (coeff_ * inputs_[outPoint_]);
- doNextOut_ = false;
- }
-
- return nextOutput_;
-}
-
-StkFloat DelayA :: computeSample( StkFloat input )
-{
- inputs_[inPoint_++] = input;
-
- // Increment input pointer modulo length.
- if (inPoint_ == inputs_.size())
- inPoint_ = 0;
-
- outputs_[0] = nextOut();
- doNextOut_ = true;
-
- // Save the allpass input and increment modulo length.
- apInput_ = inputs_[outPoint_++];
- if (outPoint_ == inputs_.size())
- outPoint_ = 0;
-
- return outputs_[0];
-}
+} // stk namespace
diff --git a/src/DelayL.cpp b/src/DelayL.cpp
index 1e08139..0003ed1 100644
--- a/src/DelayL.cpp
+++ b/src/DelayL.cpp
@@ -2,34 +2,26 @@
/*! \class DelayL
\brief STK linear interpolating delay line class.
- This Delay subclass implements a fractional-
- length digital delay-line using first-order
- linear interpolation. A fixed maximum length
- of 4095 and a delay of zero is set using the
- default constructor. Alternatively, the
- delay and maximum length can be set during
- instantiation with an overloaded constructor.
+ This class implements a fractional-length digital delay-line using
+ first-order linear interpolation. If the delay and maximum length
+ are not specified during instantiation, a fixed maximum length of
+ 4095 and a delay of zero is set.
- Linear interpolation is an efficient technique
- for achieving fractional delay lengths, though
- it does introduce high-frequency signal
- attenuation to varying degrees depending on the
- fractional delay setting. The use of higher
- order Lagrange interpolators can typically
- improve (minimize) this attenuation characteristic.
+ Linear interpolation is an efficient technique for achieving
+ fractional delay lengths, though it does introduce high-frequency
+ signal attenuation to varying degrees depending on the fractional
+ delay setting. The use of higher order Lagrange interpolators can
+ typically improve (minimize) this attenuation characteristic.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "DelayL.h"
-DelayL :: DelayL() : Delay()
-{
- doNextOut_ = true;
-}
+namespace stk {
-DelayL :: DelayL(StkFloat delay, unsigned long maxDelay)
+DelayL :: DelayL( StkFloat delay, unsigned long maxDelay )
{
if ( delay < 0.0 || maxDelay < 1 ) {
errorString_ << "DelayL::DelayL: delay must be >= 0.0, maxDelay must be > 0!";
@@ -42,13 +34,11 @@ DelayL :: DelayL(StkFloat delay, unsigned long maxDelay)
}
// Writing before reading allows delays from 0 to length-1.
- if ( maxDelay > inputs_.size()-1 ) {
- inputs_.resize( maxDelay+1 );
- this->clear();
- }
+ if ( maxDelay + 1 > inputs_.size() )
+ inputs_.resize( maxDelay + 1, 1, 0.0 );
inPoint_ = 0;
- this->setDelay(delay);
+ this->setDelay( delay );
doNextOut_ = true;
}
@@ -56,11 +46,29 @@ DelayL :: ~DelayL()
{
}
-void DelayL :: setDelay(StkFloat delay)
+void DelayL :: setMaximumDelay( unsigned long delay )
+{
+ if ( delay < inputs_.size() ) return;
+
+ if ( delay < 0 ) {
+ errorString_ << "DelayL::setMaximumDelay: argument (" << delay << ") less than zero!\n";
+ handleError( StkError::WARNING );
+ return;
+ }
+ else if ( delay < delay_ ) {
+ errorString_ << "DelayL::setMaximumDelay: argument (" << delay << ") less than current delay setting (" << delay_ << ")!\n";
+ handleError( StkError::WARNING );
+ return;
+ }
+
+ inputs_.resize( delay + 1 );
+}
+
+void DelayL :: setDelay( StkFloat delay )
{
StkFloat outPointer;
- if ( delay > inputs_.size() - 1 ) { // The value is too big.
+ if ( delay + 1 > inputs_.size() ) { // The value is too big.
errorString_ << "DelayL::setDelay: argument (" << delay << ") too big ... setting to maximum!";
handleError( StkError::WARNING );
@@ -89,42 +97,13 @@ void DelayL :: setDelay(StkFloat delay)
omAlpha_ = (StkFloat) 1.0 - alpha_;
}
-StkFloat DelayL :: getDelay(void) const
+StkFloat DelayL :: contentsAt( unsigned long tapDelay )
{
- return delay_;
-}
-
-StkFloat DelayL :: nextOut(void)
-{
- if ( doNextOut_ ) {
- // First 1/2 of interpolation
- nextOutput_ = inputs_[outPoint_] * omAlpha_;
- // Second 1/2 of interpolation
- if (outPoint_+1 < inputs_.size())
- nextOutput_ += inputs_[outPoint_+1] * alpha_;
- else
- nextOutput_ += inputs_[0] * alpha_;
- doNextOut_ = false;
- }
-
- return nextOutput_;
-}
-
-StkFloat DelayL :: computeSample( StkFloat input )
-{
- inputs_[inPoint_++] = input;
-
- // Increment input pointer modulo length.
- if (inPoint_ == inputs_.size())
- inPoint_ = 0;
-
- outputs_[0] = nextOut();
- doNextOut_ = true;
-
- // Increment output pointer modulo length.
- if (++outPoint_ == inputs_.size())
- outPoint_ = 0;
-
- return outputs_[0];
+ long tap = inPoint_ - tapDelay - 1;
+ while ( tap < 0 ) // Check for wraparound.
+ tap += inputs_.size();
+
+ return inputs_[tap];
}
+} // stk namespace
diff --git a/src/Drummer.cpp b/src/Drummer.cpp
index a258d44..37dddd5 100644
--- a/src/Drummer.cpp
+++ b/src/Drummer.cpp
@@ -11,13 +11,15 @@
of simultaneous voices) via a #define in the
Drummer.h.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "Drummer.h"
#include
+namespace stk {
+
// Not really General MIDI yet.
unsigned char genMIDIMap[128] =
{ 0,0,0,0,0,0,0,0, // 0-7
@@ -53,7 +55,7 @@ char waveNames[DRUM_NUMWAVES][16] =
"tambourn.raw"
};
-Drummer :: Drummer() : Instrmnt()
+Drummer :: Drummer( void ) : Instrmnt()
{
// This counts the number of sounding voices.
nSounding_ = 0;
@@ -61,11 +63,11 @@ Drummer :: Drummer() : Instrmnt()
soundNumber_ = std::vector (DRUM_POLYPHONY, -1);
}
-Drummer :: ~Drummer()
+Drummer :: ~Drummer( void )
{
}
-void Drummer :: noteOn(StkFloat instrument, StkFloat amplitude)
+void Drummer :: noteOn( StkFloat instrument, StkFloat amplitude )
{
#if defined(_STK_DEBUG_)
errorString_ << "Drummer::NoteOn: instrument = " << instrument << ", amplitude = " << amplitude << '.';
@@ -110,7 +112,7 @@ void Drummer :: noteOn(StkFloat instrument, StkFloat amplitude)
if ( soundOrder_[iWave] < 0 ) break;
nSounding_ += 1;
}
- else {
+ else { // interrupt oldest voice
for ( iWave=0; iWave= 0 ) {
- if ( waves_[i].isFinished() ) {
- // Re-order the list.
- for ( int j=0; j soundOrder_[i] )
- soundOrder_[j] -= 1;
- }
- soundOrder_[i] = -1;
- nSounding_--;
- }
- else
- lastOutput_ += filters_[i].tick( waves_[i].tick() );
- }
- }
-
- return lastOutput_;
-}
+} // stk namespace
diff --git a/src/Echo.cpp b/src/Echo.cpp
index a89c312..e911778 100644
--- a/src/Echo.cpp
+++ b/src/Echo.cpp
@@ -4,13 +4,15 @@
This class implements an echo effect.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "Echo.h"
#include
+namespace stk {
+
Echo :: Echo( unsigned long maximumDelay ) : Effect()
{
this->setMaximumDelay( maximumDelay );
@@ -19,15 +21,10 @@ Echo :: Echo( unsigned long maximumDelay ) : Effect()
this->clear();
}
-Echo :: ~Echo()
-{
-}
-
-void Echo :: clear()
+void Echo :: clear( void )
{
delayLine_.clear();
- lastOutput_[0] = 0.0;
- lastOutput_[1] = 0.0;
+ lastFrame_[0] = 0.0;
}
void Echo :: setMaximumDelay( unsigned long delay )
@@ -54,10 +51,4 @@ void Echo :: setDelay( unsigned long delay )
delayLine_.setDelay( size );
}
-StkFloat Echo :: computeSample(StkFloat input)
-{
- lastOutput_[0] = effectMix_ * delayLine_.tick(input);
- lastOutput_[0] += input * (1.0 - effectMix_);
- lastOutput_[1] = lastOutput_[0];
- return lastOutput_[0];
-}
+} // stk namespace
diff --git a/src/Effect.cpp b/src/Effect.cpp
deleted file mode 100644
index 494855e..0000000
--- a/src/Effect.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/***************************************************/
-/*! \class Effect
- \brief STK abstract effects parent class.
-
- This class provides common functionality for
- STK effects subclasses.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
-#include "Effect.h"
-#include
-
-Effect :: Effect()
-{
-}
-
-Effect :: ~Effect()
-{
-}
-
-void Effect :: setEffectMix(StkFloat mix)
-{
- if ( mix < 0.0 ) {
- errorString_ << "Effect::setEffectMix: mix parameter is less than zero ... setting to zero!";
- handleError( StkError::WARNING );
- effectMix_ = 0.0;
- }
- else if ( mix > 1.0 ) {
- errorString_ << "Effect::setEffectMix: mix parameter is greater than 1.0 ... setting to one!";
- handleError( StkError::WARNING );
- effectMix_ = 1.0;
- }
- else
- effectMix_ = mix;
-}
-
-StkFloat Effect :: lastOut() const
-{
- return (lastOutput_[0] + lastOutput_[1]) * 0.5;
-}
-
-StkFloat Effect :: lastOutLeft() const
-{
- return lastOutput_[0];
-}
-
-StkFloat Effect :: lastOutRight() const
-{
- return lastOutput_[1];
-}
-
-StkFloat Effect :: tick( StkFloat input )
-{
- return computeSample( input );
-}
-
-StkFrames& Effect :: tick( StkFrames& frames, unsigned int channel )
-{
- if ( channel >= frames.channels() ) {
- errorString_ << "Effect::tick(): channel and StkFrames arguments are incompatible!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- if ( frames.channels() == 1 ) {
- for ( unsigned int i=0; i value_) {
- value_ += rate_;
- if (value_ >= target_) {
- value_ = target_;
- state_ = 0;
- }
- }
- else {
- value_ -= rate_;
- if (value_ <= target_) {
- value_ = target_;
- state_ = 0;
- }
- }
- }
-
- lastOutput_ = value_;
- return value_;
-}
+} // stk namespace
diff --git a/src/FM.cpp b/src/FM.cpp
index 9751140..c1ca204 100644
--- a/src/FM.cpp
+++ b/src/FM.cpp
@@ -19,13 +19,15 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "FM.h"
#include "SKINI.msg"
+namespace stk {
+
FM :: FM( unsigned int operators )
: nOperators_(operators)
{
@@ -73,7 +75,7 @@ FM :: FM( unsigned int operators )
}
}
-FM :: ~FM()
+FM :: ~FM( void )
{
for (unsigned int i=0; isetFrequency( baseFrequency_ * ratios_[i] );
}
-void FM :: setRatio(unsigned int waveIndex, StkFloat ratio)
+void FM :: setRatio( unsigned int waveIndex, StkFloat ratio )
{
if ( waveIndex < 0 ) {
errorString_ << "FM::setRatio: waveIndex parameter is less than zero!";
@@ -115,7 +117,7 @@ void FM :: setRatio(unsigned int waveIndex, StkFloat ratio)
waves_[waveIndex]->setFrequency( ratio );
}
-void FM :: setGain(unsigned int waveIndex, StkFloat gain)
+void FM :: setGain( unsigned int waveIndex, StkFloat gain )
{
if ( waveIndex < 0 ) {
errorString_ << "FM::setGain: waveIndex parameter is less than zero!";
@@ -131,39 +133,19 @@ void FM :: setGain(unsigned int waveIndex, StkFloat gain)
gains_[waveIndex] = gain;
}
-void FM :: setModulationSpeed(StkFloat mSpeed)
+void FM :: keyOn( void )
{
- vibrato_.setFrequency( mSpeed );
-}
-
-void FM :: setModulationDepth(StkFloat mDepth)
-{
- modDepth_ = mDepth;
-}
-
-void FM :: setControl1(StkFloat cVal)
-{
- control1_ = cVal * 2.0;
-}
-
-void FM :: setControl2(StkFloat cVal)
-{
- control2_ = cVal * 2.0;
-}
-
-void FM :: keyOn()
-{
- for (unsigned int i=0; ikeyOn();
}
-void FM :: keyOff()
+void FM :: keyOff( void )
{
- for (unsigned int i=0; ikeyOff();
}
-void FM :: noteOff(StkFloat amplitude)
+void FM :: noteOff( StkFloat amplitude )
{
this->keyOff();
@@ -173,7 +155,7 @@ void FM :: noteOff(StkFloat amplitude)
#endif
}
-void FM :: controlChange(int number, StkFloat value)
+void FM :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
@@ -212,3 +194,4 @@ void FM :: controlChange(int number, StkFloat value)
#endif
}
+} // stk namespace
diff --git a/src/FMVoices.cpp b/src/FMVoices.cpp
index c324ffd..b9fcea6 100644
--- a/src/FMVoices.cpp
+++ b/src/FMVoices.cpp
@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
@@ -34,13 +34,15 @@
#include "SKINI.msg"
#include "Phonemes.h"
-FMVoices :: FMVoices()
+namespace stk {
+
+FMVoices :: FMVoices( void )
: FM()
{
// Concatenate the STK rawwave path to the rawwave files
for ( unsigned int i=0; i<3; i++ )
- waves_[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
- waves_[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true );
+ waves_[i] = new FileLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
+ waves_[3] = new FileLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true );
this->setRatio(0, 2.00);
this->setRatio(1, 4.00);
@@ -67,11 +69,11 @@ FMVoices :: FMVoices()
this->setFrequency( 110.0 );
}
-FMVoices :: ~FMVoices()
+FMVoices :: ~FMVoices( void )
{
}
-void FMVoices :: setFrequency(StkFloat frequency)
+void FMVoices :: setFrequency( StkFloat frequency )
{
StkFloat temp, temp2 = 0.0;
int tempi = 0;
@@ -109,7 +111,7 @@ void FMVoices :: setFrequency(StkFloat frequency)
gains_[2] = 1.0;
}
-void FMVoices :: noteOn(StkFloat frequency, StkFloat amplitude)
+void FMVoices :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency( frequency );
tilt_[0] = amplitude;
@@ -123,32 +125,7 @@ void FMVoices :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-StkFloat FMVoices :: computeSample()
-{
- register StkFloat temp, temp2;
-
- temp = gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
- temp2 = vibrato_.tick() * modDepth_ * 0.1;
-
- waves_[0]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[0]);
- waves_[1]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[1]);
- waves_[2]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[2]);
- waves_[3]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[3]);
-
- waves_[0]->addPhaseOffset(temp * mods_[0]);
- waves_[1]->addPhaseOffset(temp * mods_[1]);
- waves_[2]->addPhaseOffset(temp * mods_[2]);
- waves_[3]->addPhaseOffset( twozero_.lastOut() );
- twozero_.tick( temp );
- temp = gains_[0] * tilt_[0] * adsr_[0]->tick() * waves_[0]->tick();
- temp += gains_[1] * tilt_[1] * adsr_[1]->tick() * waves_[1]->tick();
- temp += gains_[2] * tilt_[2] * adsr_[2]->tick() * waves_[2]->tick();
-
- lastOutput_ = temp * 0.33;
- return lastOutput_;
-}
-
-void FMVoices :: controlChange(int number, StkFloat value)
+void FMVoices :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
@@ -188,3 +165,5 @@ void FMVoices :: controlChange(int number, StkFloat value)
handleError( StkError::DEBUG_WARNING );
#endif
}
+
+} // stk namespace
diff --git a/src/WaveLoop.cpp b/src/FileLoop.cpp
similarity index 61%
rename from src/WaveLoop.cpp
rename to src/FileLoop.cpp
index 41b7469..56cfdec 100644
--- a/src/WaveLoop.cpp
+++ b/src/FileLoop.cpp
@@ -1,31 +1,33 @@
/***************************************************/
-/*! \class WaveLoop
- \brief STK waveform oscillator class.
+/*! \class FileLoop
+ \brief STK file looping / oscillator class.
- This class inherits from FileWvIn and provides audio file looping
- functionality. Any audio file that can be loaded by FileRead can
- be looped using this class.
+ This class provides audio file looping functionality. Any audio
+ file that can be loaded by FileRead can be looped using this
+ class.
- WaveLoop supports multi-channel data. It is important to
- distinguish the tick() methods, which return samples produced by
- averaging across sample frames, from the tickFrame() methods,
- which return references or pointers to multi-channel sample
- frames.
+ FileLoop supports multi-channel data. It is important to
+ distinguish the tick() method that computes a single frame (and
+ returns only the specified sample of a multi-channel frame) from
+ the overloaded one that takes an StkFrames object for
+ multi-channel and/or multi-frame data.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
-#include "WaveLoop.h"
+#include "FileLoop.h"
#include
-WaveLoop :: WaveLoop( unsigned long chunkThreshold, unsigned long chunkSize )
+namespace stk {
+
+FileLoop :: FileLoop( unsigned long chunkThreshold, unsigned long chunkSize )
: FileWvIn( chunkThreshold, chunkSize ), phaseOffset_(0.0)
{
Stk::addSampleRateAlert( this );
}
-WaveLoop :: WaveLoop( std::string fileName, bool raw, bool doNormalize,
+FileLoop :: FileLoop( std::string fileName, bool raw, bool doNormalize,
unsigned long chunkThreshold, unsigned long chunkSize )
: FileWvIn( chunkThreshold, chunkSize ), phaseOffset_(0.0)
{
@@ -33,18 +35,12 @@ WaveLoop :: WaveLoop( std::string fileName, bool raw, bool doNormalize,
Stk::addSampleRateAlert( this );
}
-WaveLoop :: ~WaveLoop()
+FileLoop :: ~FileLoop( void )
{
Stk::removeSampleRateAlert( this );
}
-void WaveLoop :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
-{
- if ( !ignoreSampleRateChange_ )
- this->setRate( oldRate * rate_ / newRate );
-}
-
-void WaveLoop :: openFile( std::string fileName, bool raw, bool doNormalize )
+void FileLoop :: openFile( std::string fileName, bool raw, bool doNormalize )
{
// Call close() in case another file is already open.
this->closeFile();
@@ -56,7 +52,7 @@ void WaveLoop :: openFile( std::string fileName, bool raw, bool doNormalize )
if ( file_.fileSize() > chunkThreshold_ ) {
chunking_ = true;
chunkPointer_ = 0;
- data_.resize( chunkSize_, file_.channels() );
+ data_.resize( chunkSize_ + 1, file_.channels() );
if ( doNormalize ) normalizing_ = true;
else normalizing_ = false;
}
@@ -79,7 +75,7 @@ void WaveLoop :: openFile( std::string fileName, bool raw, bool doNormalize )
}
// Resize our lastOutputs container.
- lastOutputs_.resize( 1, file_.channels() );
+ lastFrame_.resize( 1, file_.channels() );
// Set default rate based on file sampling rate.
this->setRate( data_.dataRate() / Stk::sampleRate() );
@@ -89,7 +85,7 @@ void WaveLoop :: openFile( std::string fileName, bool raw, bool doNormalize )
this->reset();
}
-void WaveLoop :: setRate( StkFloat rate )
+void FileLoop :: setRate( StkFloat rate )
{
rate_ = rate;
@@ -97,13 +93,7 @@ void WaveLoop :: setRate( StkFloat rate )
else interpolate_ = false;
}
-void WaveLoop :: setFrequency( StkFloat frequency )
-{
- // This is a looping frequency.
- this->setRate( file_.fileSize() * frequency / Stk::sampleRate() );
-}
-
-void WaveLoop :: addTime( StkFloat time )
+void FileLoop :: addTime( StkFloat time )
{
// Add an absolute time in samples.
time_ += time;
@@ -115,7 +105,7 @@ void WaveLoop :: addTime( StkFloat time )
time_ -= fileSize;
}
-void WaveLoop :: addPhase( StkFloat angle )
+void FileLoop :: addPhase( StkFloat angle )
{
// Add a time in cycles (one cycle = fileSize).
StkFloat fileSize = file_.fileSize();
@@ -127,35 +117,40 @@ void WaveLoop :: addPhase( StkFloat angle )
time_ -= fileSize;
}
-void WaveLoop :: addPhaseOffset( StkFloat angle )
+void FileLoop :: addPhaseOffset( StkFloat angle )
{
// Add a phase offset in cycles, where 1.0 = fileSize.
phaseOffset_ = file_.fileSize() * angle;
}
-void WaveLoop :: computeFrame( void )
+StkFloat FileLoop :: tick( unsigned int channel )
{
+#if defined(_STK_DEBUG_)
+ if ( channel >= data_.channels() ) {
+ errorString_ << "FileLoop::tick(): channel argument and soundfile data are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
+
// Check limits of time address ... if necessary, recalculate modulo
// fileSize.
StkFloat fileSize = file_.fileSize();
+
while ( time_ < 0.0 )
time_ += fileSize;
while ( time_ >= fileSize )
time_ -= fileSize;
- StkFloat tyme;
+ StkFloat tyme = time_;
if ( phaseOffset_ ) {
- tyme = time_ + phaseOffset_;
+ tyme += phaseOffset_;
while ( tyme < 0.0 )
tyme += fileSize;
while ( tyme >= fileSize )
tyme -= fileSize;
}
- else {
- tyme = time_;
- }
- if (chunking_) {
+ if ( chunking_ ) {
// Check the time address vs. our current buffer limits.
if ( ( time_ < (StkFloat) chunkPointer_ ) ||
@@ -184,14 +179,46 @@ void WaveLoop :: computeFrame( void )
}
if ( interpolate_ ) {
- for ( unsigned int i=0; itick();
+ for ( j=0; j
#include
+#include
#include
+namespace stk {
+
FileRead :: FileRead()
: fd_(0)
{
@@ -730,3 +733,4 @@ void FileRead :: read( StkFrames& buffer, unsigned long startFrame, bool doNorma
handleError( StkError::FILE_ERROR);
}
+} // stk namespace
diff --git a/src/FileWrite.cpp b/src/FileWrite.cpp
index 1db299a..e2e2e60 100644
--- a/src/FileWrite.cpp
+++ b/src/FileWrite.cpp
@@ -17,13 +17,16 @@
type, the data type will automatically be modified. Compressed
data types are not supported.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "FileWrite.h"
+#include
#include
+namespace stk {
+
const FileWrite::FILE_TYPE FileWrite :: FILE_RAW = 1;
const FileWrite::FILE_TYPE FileWrite :: FILE_WAV = 2;
const FileWrite::FILE_TYPE FileWrite :: FILE_SND = 3;
@@ -699,3 +702,5 @@ void FileWrite :: write( StkFrames& buffer )
errorString_ << "FileWrite::write(): error writing data to file!";
handleError( StkError::FILE_ERROR );
}
+
+} // stk namespace
diff --git a/src/FileWvIn.cpp b/src/FileWvIn.cpp
index e1e3906..557308d 100644
--- a/src/FileWvIn.cpp
+++ b/src/FileWvIn.cpp
@@ -4,14 +4,15 @@
This class inherits from WvIn. It provides a "tick-level"
interface to the FileRead class. It also provides variable-rate
- "playback" functionality. Audio file support is provided by the
- FileRead class. Linear interpolation is used for fractional "read
- rates".
+ playback functionality. Audio file support is provided by the
+ FileRead class. Linear interpolation is used for fractional read
+ rates.
- FileWvIn supports multi-channel data. It is important to distinguish
- the tick() methods, which return samples produced by averaging
- across sample frames, from the tickFrame() methods, which return
- references to multi-channel sample frames.
+ FileWvIn supports multi-channel data. It is important to
+ distinguish the tick() method that computes a single frame (and
+ returns only the specified sample of a multi-channel frame) from
+ the overloaded one that takes an StkFrames object for
+ multi-channel and/or multi-frame data.
FileWvIn will either load the entire content of an audio file into
local memory or incrementally read file data from disk in chunks.
@@ -20,19 +21,21 @@
chunkThreshold (in sample frames) will be read incrementally in
chunks of \e chunkSize each (also in sample frames).
- When the end of a file is reached, subsequent calls to the tick()
- functions return zero-valued data.
+ When the file end is reached, subsequent calls to the tick()
+ functions return zeros and isFinished() returns \e true.
See the FileRead class for a description of the supported audio
file formats.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "FileWvIn.h"
#include
+namespace stk {
+
FileWvIn :: FileWvIn( unsigned long chunkThreshold, unsigned long chunkSize )
: finished_(true), interpolate_(false), time_(0.0),
chunkThreshold_(chunkThreshold), chunkSize_(chunkSize)
@@ -65,6 +68,7 @@ void FileWvIn :: closeFile( void )
{
if ( file_.isOpen() ) file_.close();
finished_ = true;
+ lastFrame_.resize( 0, 0 );
}
void FileWvIn :: openFile( std::string fileName, bool raw, bool doNormalize )
@@ -91,8 +95,8 @@ void FileWvIn :: openFile( std::string fileName, bool raw, bool doNormalize )
// Load all or part of the data.
file_.read( data_, 0, doNormalize );
- // Resize our lastOutputs container.
- lastOutputs_.resize( 1, file_.channels() );
+ // Resize our lastFrame container.
+ lastFrame_.resize( 1, file_.channels() );
// Set default rate based on file sampling rate.
this->setRate( data_.dataRate() / Stk::sampleRate() );
@@ -105,8 +109,7 @@ void FileWvIn :: openFile( std::string fileName, bool raw, bool doNormalize )
void FileWvIn :: reset(void)
{
time_ = (StkFloat) 0.0;
- for ( unsigned int i=0; i 0.0) {
+ if ( max > 0.0 ) {
max = 1.0 / max;
max *= peak;
for ( i=0; i file_.fileSize() - 1.0 ) {
time_ = file_.fileSize() - 1.0;
- for ( unsigned int i=0; i= data_.channels() ) {
+ errorString_ << "FileWvIn::tick(): channel argument and soundfile data are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+#endif
-void FileWvIn :: computeFrame( void )
-{
- if ( finished_ ) return;
+ if ( finished_ ) return 0.0;
if ( time_ < 0.0 || time_ > (StkFloat) ( file_.fileSize() - 1.0 ) ) {
- for ( unsigned int i=0; itick();
+ for ( j=0; jincrementFrame();
}
-void FileWvOut :: computeFrames( const StkFrames& frames )
+void FileWvOut :: tick( const StkFrames& frames )
{
+#if defined(_STK_DEBUG_)
if ( !file_.isOpen() ) {
- errorString_ << "FileWvOut::computeFrames(): no file open!";
+ errorString_ << "FileWvOut::tick(): no file open!";
handleError( StkError::WARNING );
return;
}
if ( data_.channels() != frames.channels() ) {
- errorString_ << "FileWvOut::computeFrames(): incompatible channel value in StkFrames argument!";
+ errorString_ << "FileWvOut::tick(): incompatible channel value in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
+#endif
+ unsigned int iFrames = 0;
unsigned int j, nChannels = data_.channels();
- if ( nChannels == 1 || frames.interleaved() ) {
+ for ( unsigned int i=0; iincrementFrame();
+ for ( j=0; jincrementFrame();
- }
+ this->incrementFrame();
}
}
+} // stk namespace
diff --git a/src/Filter.cpp b/src/Filter.cpp
deleted file mode 100644
index 9f2572d..0000000
--- a/src/Filter.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-/***************************************************/
-/*! \class Filter
- \brief STK filter class.
-
- This class implements a generic structure that
- can be used to create a wide range of filters.
- It can function independently or be subclassed
- to provide more specific controls based on a
- particular filter type.
-
- In particular, this class implements the standard
- difference equation:
-
- a[0]*y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb] -
- a[1]*y[n-1] - ... - a[na]*y[n-na]
-
- If a[0] is not equal to 1, the filter coefficients
- are normalized by a[0].
-
- The \e gain parameter is applied at the filter
- input and does not affect the coefficient values.
- The default gain value is 1.0. This structure
- results in one extra multiply per computed sample,
- but allows easy control of the overall filter gain.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
-#include "Filter.h"
-#include
-
-Filter :: Filter()
-{
- // The default constructor should setup for pass-through.
- gain_ = 1.0;
- b_.push_back( 1.0 );
- a_.push_back( 1.0 );
-
- inputs_.push_back( 0.0 );
- outputs_.push_back( 0.0 );
-}
-
-Filter :: Filter( std::vector &bCoefficients, std::vector &aCoefficients )
-{
- // Check the arguments.
- if ( bCoefficients.size() == 0 || aCoefficients.size() == 0 ) {
- errorString_ << "Filter: a and b coefficient vectors must both have size > 0!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- if ( aCoefficients[0] == 0.0 ) {
- errorString_ << "Filter: a[0] coefficient cannot == 0!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- gain_ = 1.0;
- b_ = bCoefficients;
- a_ = aCoefficients;
-
- inputs_ = std::vector ( b_.size() );
- outputs_ = std::vector ( a_.size() );
- this->clear();
-}
-
-Filter :: ~Filter()
-{
-}
-
-void Filter :: clear(void)
-{
- unsigned int i;
- for (i=0; i &bCoefficients, std::vector &aCoefficients, bool clearState )
-{
- // Check the arguments.
- if ( bCoefficients.size() == 0 || aCoefficients.size() == 0 ) {
- errorString_ << "Filter::setCoefficients: a and b coefficient vectors must both have size > 0!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- if ( aCoefficients[0] == 0.0 ) {
- errorString_ << "Filter::setCoefficients: a[0] coefficient cannot == 0!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- if ( b_.size() != bCoefficients.size() ) {
- b_ = bCoefficients;
- inputs_.clear();
- inputs_ = std::vector ( b_.size() );
- }
- else {
- for ( unsigned int i=0; i ( a_.size() );
- }
- else {
- for ( unsigned int i=0; iclear();
-
- // Scale coefficients by a[0] if necessary
- if ( a_[0] != 1.0 ) {
- unsigned int i;
- for ( i=0; i &bCoefficients, bool clearState )
-{
- // Check the argument.
- if ( bCoefficients.size() == 0 ) {
- errorString_ << "Filter::setNumerator: coefficient vector must have size > 0!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- if ( b_.size() != bCoefficients.size() ) {
- b_ = bCoefficients;
- inputs_.clear();
- inputs_ = std::vector ( b_.size() );
- }
- else {
- for ( unsigned int i=0; iclear();
-}
-
-void Filter :: setDenominator( std::vector &aCoefficients, bool clearState )
-{
- // Check the argument.
- if ( aCoefficients.size() == 0 ) {
- errorString_ << "Filter::setDenominator: coefficient vector must have size > 0!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- if ( aCoefficients[0] == 0.0 ) {
- errorString_ << "Filter::setDenominator: a[0] coefficient cannot == 0!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- if ( a_.size() != aCoefficients.size() ) {
- a_ = aCoefficients;
- outputs_.clear();
- outputs_ = std::vector ( a_.size() );
- }
- else {
- for ( unsigned int i=0; iclear();
-
- // Scale coefficients by a[0] if necessary
- if ( a_[0] != 1.0 ) {
- unsigned int i;
- for ( i=0; i0; i--) {
- outputs_[0] += b_[i] * inputs_[i];
- inputs_[i] = inputs_[i-1];
- }
- outputs_[0] += b_[0] * inputs_[0];
-
- for (i=a_.size()-1; i>0; i--) {
- outputs_[0] += -a_[i] * outputs_[i];
- outputs_[i] = outputs_[i-1];
- }
-
- return outputs_[0];
-}
-
-
-StkFrames& Filter :: tick( StkFrames& frames, unsigned int channel )
-{
- if ( channel >= frames.channels() ) {
- errorString_ << "Filter::tick(): channel and StkFrames arguments are incompatible!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- if ( frames.channels() == 1 ) {
- for ( unsigned int i=0; i &coefficients )
+{
+ // Check the arguments.
+ if ( coefficients.size() == 0 ) {
+ errorString_ << "Fir: coefficient vector must have size > 0!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ gain_ = 1.0;
+ b_ = coefficients;
+
+ inputs_.resize( b_.size(), 1, 0.0 );
+ this->clear();
+}
+
+Fir :: ~Fir()
+{
+}
+
+void Fir :: setCoefficients( std::vector &coefficients, bool clearState )
+{
+ // Check the argument.
+ if ( coefficients.size() == 0 ) {
+ errorString_ << "Fir::setCoefficients: coefficient vector must have size > 0!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ if ( b_.size() != coefficients.size() ) {
+ b_ = coefficients;
+ inputs_.resize( b_.size(), 1, 0.0 );
+ }
+ else {
+ for ( unsigned int i=0; iclear();
+}
+
+} // stk namespace
diff --git a/src/Flute.cpp b/src/Flute.cpp
index 08fee16..e8bb553 100644
--- a/src/Flute.cpp
+++ b/src/Flute.cpp
@@ -18,16 +18,18 @@
- Vibrato Gain = 1
- Breath Pressure = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "Flute.h"
#include "SKINI.msg"
-Flute :: Flute(StkFloat lowestFrequency)
+namespace stk {
+
+Flute :: Flute( StkFloat lowestFrequency )
{
- length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
+ length_ = (unsigned long) ( Stk::sampleRate() / lowestFrequency + 1 );
boreDelay_.setMaximumDelay( length_ );
boreDelay_.setDelay( 100.0 );
@@ -54,11 +56,11 @@ Flute :: Flute(StkFloat lowestFrequency)
lastFrequency_ = 220.0;
}
-Flute :: ~Flute()
+Flute :: ~Flute( void )
{
}
-void Flute :: clear()
+void Flute :: clear( void )
{
jetDelay_.clear();
boreDelay_.clear();
@@ -66,7 +68,7 @@ void Flute :: clear()
dcBlock_.clear();
}
-void Flute :: setFrequency(StkFloat frequency)
+void Flute :: setFrequency( StkFloat frequency )
{
lastFrequency_ = frequency;
if ( frequency <= 0.0 ) {
@@ -87,20 +89,20 @@ void Flute :: setFrequency(StkFloat frequency)
jetDelay_.setDelay(delay * jetRatio_);
}
-void Flute :: startBlowing(StkFloat amplitude, StkFloat rate)
+void Flute :: startBlowing( StkFloat amplitude, StkFloat rate )
{
adsr_.setAttackRate( rate );
maxPressure_ = amplitude / (StkFloat) 0.8;
adsr_.keyOn();
}
-void Flute :: stopBlowing(StkFloat rate)
+void Flute :: stopBlowing( StkFloat rate )
{
adsr_.setReleaseRate( rate );
adsr_.keyOff();
}
-void Flute :: noteOn(StkFloat frequency, StkFloat amplitude)
+void Flute :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency( frequency );
this->startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02 );
@@ -112,7 +114,7 @@ void Flute :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-void Flute :: noteOff(StkFloat amplitude)
+void Flute :: noteOff( StkFloat amplitude )
{
this->stopBlowing( amplitude * 0.02 );
@@ -122,12 +124,12 @@ void Flute :: noteOff(StkFloat amplitude)
#endif
}
-void Flute :: setJetReflection(StkFloat coefficient)
+void Flute :: setJetReflection( StkFloat coefficient )
{
jetReflection_ = coefficient;
}
-void Flute :: setEndReflection(StkFloat coefficient)
+void Flute :: setEndReflection( StkFloat coefficient )
{
endReflection_ = coefficient;
}
@@ -140,28 +142,7 @@ void Flute :: setJetDelay( StkFloat aRatio )
jetDelay_.setDelay(temp * aRatio); // Scaled by ratio.
}
-StkFloat Flute :: computeSample()
-{
- StkFloat pressureDiff;
- StkFloat breathPressure;
-
- // Calculate the breath pressure (envelope + noise + vibrato)
- breathPressure = maxPressure_ * adsr_.tick();
- breathPressure += breathPressure * ( noiseGain_ * noise_.tick() + vibratoGain_ * vibrato_.tick() );
-
- StkFloat temp = filter_.tick( boreDelay_.lastOut() );
- temp = dcBlock_.tick( temp ); // Block DC on reflection.
-
- pressureDiff = breathPressure - (jetReflection_ * temp);
- pressureDiff = jetDelay_.tick( pressureDiff );
- pressureDiff = jetTable_.tick( pressureDiff ) + (endReflection_ * temp);
- lastOutput_ = (StkFloat) 0.3 * boreDelay_.tick( pressureDiff );
-
- lastOutput_ *= outputGain_;
- return lastOutput_;
-}
-
-void Flute :: controlChange(int number, StkFloat value)
+void Flute :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
@@ -195,3 +176,5 @@ void Flute :: controlChange(int number, StkFloat value)
handleError( StkError::DEBUG_WARNING );
#endif
}
+
+} // stk namespace
diff --git a/src/FormSwep.cpp b/src/FormSwep.cpp
index 4ee9302..32a73ec 100644
--- a/src/FormSwep.cpp
+++ b/src/FormSwep.cpp
@@ -2,63 +2,83 @@
/*! \class FormSwep
\brief STK sweepable formant filter class.
- This public BiQuad filter subclass implements
- a formant (resonance) which can be "swept"
- over time from one frequency setting to another.
- It provides methods for controlling the sweep
- rate and target frequency.
+ This class implements a formant (resonance) which can be "swept"
+ over time from one frequency setting to another. It provides
+ methods for controlling the sweep rate and target frequency.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#include "FormSwep.h"
+#include
-FormSwep :: FormSwep() : BiQuad()
+namespace stk {
+
+FormSwep :: FormSwep( void )
{
- frequency_ = (StkFloat) 0.0;
- radius_ = (StkFloat) 0.0;
- targetGain_ = (StkFloat) 1.0;
- targetFrequency_ = (StkFloat) 0.0;
- targetRadius_ = (StkFloat) 0.0;
- deltaGain_ = (StkFloat) 0.0;
- deltaFrequency_ = (StkFloat) 0.0;
- deltaRadius_ = (StkFloat) 0.0;
- sweepState_ = (StkFloat) 0.0;
- sweepRate_ = (StkFloat) 0.002;
+ frequency_ = 0.0;
+ radius_ = 0.0;
+ targetGain_ = 1.0;
+ targetFrequency_ = 0.0;
+ targetRadius_ = 0.0;
+ deltaGain_ = 0.0;
+ deltaFrequency_ = 0.0;
+ deltaRadius_ = 0.0;
+ sweepState_ = 0.0;
+ sweepRate_ = 0.002;
dirty_ = false;
- this->clear();
+
+ b_.resize( 3, 0.0 );
+ a_.resize( 3, 0.0 );
+ a_[0] = 1.0;
+ inputs_.resize( 3, 1, 0.0 );
+ outputs_.resize( 3, 1, 0.0 );
+
+ Stk::addSampleRateAlert( this );
}
FormSwep :: ~FormSwep()
{
+ Stk::removeSampleRateAlert( this );
}
-void FormSwep :: setResonance(StkFloat frequency, StkFloat radius)
+void FormSwep :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
+{
+ if ( !ignoreSampleRateChange_ ) {
+ errorString_ << "FormSwep::sampleRateChanged: you may need to recompute filter coefficients!";
+ handleError( StkError::WARNING );
+ }
+}
+
+void FormSwep :: setResonance( StkFloat frequency, StkFloat radius )
{
- dirty_ = false;
radius_ = radius;
frequency_ = frequency;
- BiQuad::setResonance( frequency_, radius_, true );
+ a_[2] = radius * radius;
+ a_[1] = -2.0 * radius * cos( TWO_PI * frequency / Stk::sampleRate() );
+
+ // Use zeros at +- 1 and normalize the filter peak gain.
+ b_[0] = 0.5 - 0.5 * a_[2];
+ b_[1] = 0.0;
+ b_[2] = -b_[0];
}
-void FormSwep :: setStates(StkFloat frequency, StkFloat radius, StkFloat gain)
+void FormSwep :: setStates( StkFloat frequency, StkFloat radius, StkFloat gain )
{
dirty_ = false;
if ( frequency_ != frequency || radius_ != radius )
- BiQuad::setResonance( frequency, radius, true );
+ this->setResonance( frequency, radius );
- frequency_ = frequency;
- radius_ = radius;
gain_ = gain;
targetFrequency_ = frequency;
targetRadius_ = radius;
targetGain_ = gain;
}
-void FormSwep :: setTargets(StkFloat frequency, StkFloat radius, StkFloat gain)
+void FormSwep :: setTargets( StkFloat frequency, StkFloat radius, StkFloat gain )
{
dirty_ = true;
startFrequency_ = frequency_;
@@ -70,42 +90,21 @@ void FormSwep :: setTargets(StkFloat frequency, StkFloat radius, StkFloat gain)
deltaFrequency_ = frequency - frequency_;
deltaRadius_ = radius - radius_;
deltaGain_ = gain - gain_;
- sweepState_ = (StkFloat) 0.0;
+ sweepState_ = 0.0;
}
-void FormSwep :: setSweepRate(StkFloat rate)
+void FormSwep :: setSweepRate( StkFloat rate )
{
sweepRate_ = rate;
if ( sweepRate_ > 1.0 ) sweepRate_ = 1.0;
if ( sweepRate_ < 0.0 ) sweepRate_ = 0.0;
}
-void FormSwep :: setSweepTime(StkFloat time)
+void FormSwep :: setSweepTime( StkFloat time )
{
sweepRate_ = 1.0 / ( time * Stk::sampleRate() );
if ( sweepRate_ > 1.0 ) sweepRate_ = 1.0;
if ( sweepRate_ < 0.0 ) sweepRate_ = 0.0;
}
-StkFloat FormSwep :: computeSample( StkFloat input )
-{
- if (dirty_) {
- sweepState_ += sweepRate_;
- if ( sweepState_ >= 1.0 ) {
- sweepState_ = 1.0;
- dirty_ = false;
- radius_ = targetRadius_;
- frequency_ = targetFrequency_;
- gain_ = targetGain_;
- }
- else {
- radius_ = startRadius_ + (deltaRadius_ * sweepState_);
- frequency_ = startFrequency_ + (deltaFrequency_ * sweepState_);
- gain_ = startGain_ + (deltaGain_ * sweepState_);
- }
- BiQuad::setResonance( frequency_, radius_, true );
- }
-
- return BiQuad::computeSample( input );
-}
-
+} // stk namespace
diff --git a/src/Function.cpp b/src/Function.cpp
deleted file mode 100644
index 224d2b8..0000000
--- a/src/Function.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/***************************************************/
-/*! \class Function
- \brief STK abstract function parent class.
-
- This class provides common functionality for STK classes which
- implement tables or other types of input to output function
- mappings.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
-*/
-/***************************************************/
-
-#include "Function.h"
-
-Function :: Function() : Stk()
-{
- lastOutput_ = (StkFloat) 0.0;
-}
-
-Function :: ~Function()
-{
-}
-
-StkFloat Function :: tick( StkFloat input )
-{
- return computeSample( input );
-}
-
-StkFrames& Function :: tick( StkFrames& frames, unsigned int channel )
-{
- if ( channel >= frames.channels() ) {
- errorString_ << "Function::tick(): channel and StkFrames arguments are incompatible!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- if ( frames.channels() == 1 ) {
- for ( unsigned int i=0; i= frames.channels() ) {
- errorString_ << "Generator::tick(): channel and StkFrames arguments are incompatible!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- if ( frames.channels() == 1 ) {
- for ( unsigned int i=0; i |