Version 4.4.0

This commit is contained in:
Gary Scavone
2013-09-29 23:11:39 +02:00
committed by Stephen Sinclair
parent d199342e86
commit eccd8c9981
287 changed files with 11712 additions and 7676 deletions

View File

@@ -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<frames.frames(); i++, samples += hop )
*samples = ADSR::tick();
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,10 @@
#ifndef STK_ASYMP_H
#define STK_ASYMP_H
#include "Generator.h"
namespace stk {
/***************************************************/
/*! \class Asymp
\brief STK asymptotic curve envelope class
@@ -6,7 +13,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,32 +26,27 @@
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.
*/
/***************************************************/
#ifndef STK_ASYMP_H
#define STK_ASYMP_H
#include "Envelope.h"
const StkFloat TARGET_THRESHOLD = 0.000001;
class Asymp : public Envelope
class Asymp : public Generator
{
public:
//! Default constructor.
Asymp(void);
Asymp( void );
//! Class destructor.
~Asymp(void);
~Asymp( void );
//! Set target = 1.
void keyOn(void);
void keyOn( void );
//! Set target = 0.
void keyOff(void);
void keyOff( void );
//! Set the asymptotic rate via the time factor \e tau (must be > 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<frames.frames(); i++, samples += hop )
*samples = Asymp::tick();
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,14 @@
#ifndef STK_BANDEDWG_H
#define STK_BANDEDWG_H
#include "Instrmnt.h"
#include "DelayL.h"
#include "BowTable.h"
#include "ADSR.h"
#include "BiQuad.h"
namespace stk {
/***************************************************/
/*! \class BandedWG
\brief Banded waveguide modeling class.
@@ -25,64 +36,56 @@
- Tibetan Bowl = 3
by Georg Essl, 1999 - 2004.
Modified for Stk 4.0 by Gary Scavone.
Modified for STK 4.0 by Gary Scavone.
*/
/***************************************************/
#ifndef STK_BANDEDWG_H
#define STK_BANDEDWG_H
const int MAX_BANDED_MODES = 20;
#include "Instrmnt.h"
#include "DelayL.h"
#include "BowTable.h"
#include "ADSR.h"
#include "BiQuad.h"
class BandedWG : public Instrmnt
{
public:
//! Class constructor.
BandedWG();
BandedWG( void );
//! Class destructor.
~BandedWG();
~BandedWG( void );
//! Reset and clear all internal state.
void clear();
void clear( void );
//! Set strike position (0.0 - 1.0).
void setStrikePosition(StkFloat position);
void setStrikePosition( StkFloat position );
//! Select a preset.
void setPreset(int preset);
void setPreset( int preset );
//! Set instrument parameters for a particular frequency.
void setFrequency(StkFloat frequency);
void setFrequency( StkFloat frequency );
//! Apply bow velocity/pressure to instrument with given amplitude and rate of increase.
void startBowing(StkFloat amplitude, StkFloat rate);
void startBowing( StkFloat amplitude, StkFloat rate );
//! Decrease bow velocity/breath pressure with given rate of decrease.
void stopBowing(StkFloat rate);
void stopBowing( StkFloat rate );
//! Pluck the instrument with given amplitude.
void pluck(StkFloat amp);
void pluck( StkFloat amp );
//! 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 );
bool doPluck_;
bool trackVelocity_;
int nModes_;
@@ -108,4 +111,6 @@ class BandedWG : public Instrmnt
};
} // stk namespace
#endif

View File

@@ -1,3 +1,10 @@
#ifndef STK_BEETHREE_H
#define STK_BEETHREE_H
#include "FM.h"
namespace stk {
/***************************************************/
/*! \class BeeThree
\brief STK Hammond-oid organ FM synthesis instrument.
@@ -28,15 +35,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_BEETHREE_H
#define STK_BEETHREE_H
#include "FM.h"
class BeeThree : public FM
{
public:
@@ -44,17 +46,45 @@ class BeeThree : public FM
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
BeeThree();
BeeThree( void );
//! Class destructor.
~BeeThree();
~BeeThree( void );
//! 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 BeeThree :: tick( unsigned int )
{
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();
lastFrame_[0] = temp * 0.125;
return lastFrame_[0];
}
} // stk namespace
#endif

View File

@@ -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<frames.frames(); i++, samples += hop ) {
inputs_[0] = gain_ * *samples;
*samples = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2];
*samples -= a_[2] * outputs_[2] + a_[1] * outputs_[1];
inputs_[2] = inputs_[1];
inputs_[1] = inputs_[0];
outputs_[2] = outputs_[1];
outputs_[1] = *samples;
}
lastFrame_[0] = outputs_[1];
return frames;
}
inline StkFrames& BiQuad :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[0] = gain_ * *iSamples;
*oSamples = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2];
*oSamples -= a_[2] * outputs_[2] + a_[1] * outputs_[1];
inputs_[2] = inputs_[1];
inputs_[1] = inputs_[0];
outputs_[2] = outputs_[1];
outputs_[1] = *oSamples;
}
lastFrame_[0] = outputs_[1];
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,12 @@
#ifndef STK_BLIT_H
#define STK_BLIT_H
#include "Generator.h"
#include <cmath>
#include <limits>
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<StkFloat>::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<frames.frames(); i++, samples += hop )
*samples = Blit::tick();
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,12 @@
#ifndef STK_BLITSAW_H
#define STK_BLITSAW_H
#include "Generator.h"
#include <cmath>
#include <limits>
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<StkFloat>::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<frames.frames(); i++, samples += hop )
*samples = BlitSaw::tick();
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,12 @@
#ifndef STK_BLITSQUARE_H
#define STK_BLITSQUARE_H
#include "Generator.h"
#include <cmath>
#include <limits>
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<StkFloat>::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<frames.frames(); i++, samples += hop )
*samples = BlitSquare::tick();
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,16 @@
#ifndef STK_BLOWBOTL_H
#define STK_BLOWBOTL_H
#include "Instrmnt.h"
#include "JetTable.h"
#include "BiQuad.h"
#include "PoleZero.h"
#include "Noise.h"
#include "ADSR.h"
#include "SineWave.h"
namespace stk {
/***************************************************/
/*! \class BlowBotl
\brief STK blown bottle instrument class.
@@ -12,21 +25,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_BLOWBOTL_H
#define STK_BLOWBOTL_H
#include "Instrmnt.h"
#include "JetTable.h"
#include "BiQuad.h"
#include "PoleZero.h"
#include "Noise.h"
#include "ADSR.h"
#include "SineWave.h"
class BlowBotl : public Instrmnt
{
public:
@@ -34,36 +36,37 @@ class BlowBotl : public Instrmnt
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
BlowBotl();
BlowBotl( void );
//! Class destructor.
~BlowBotl();
~BlowBotl( 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 );
//! 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 );
JetTable jetTable_;
BiQuad resonator_;
PoleZero dcBlock_;
@@ -77,4 +80,28 @@ class BlowBotl : public Instrmnt
};
inline StkFloat BlowBotl :: tick( unsigned int )
{
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 ) );
lastFrame_[0] = 0.2 * outputGain_ * dcBlock_.tick( pressureDiff );
return lastFrame_[0];
}
} // stk namespace
#endif

View File

@@ -1,3 +1,17 @@
#ifndef STK_BLOWHOLE_H
#define STK_BLOWHOLE_H
#include "Instrmnt.h"
#include "DelayL.h"
#include "ReedTable.h"
#include "OneZero.h"
#include "PoleZero.h"
#include "Envelope.h"
#include "Noise.h"
#include "SineWave.h"
namespace stk {
/***************************************************/
/*! \class BlowHole
\brief STK clarinet physical model with one
@@ -29,22 +43,10 @@
- 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.
*/
/***************************************************/
#ifndef STK_BLOWHOLE_H
#define STK_BLOWHOLE_H
#include "Instrmnt.h"
#include "DelayL.h"
#include "ReedTable.h"
#include "OneZero.h"
#include "PoleZero.h"
#include "Envelope.h"
#include "Noise.h"
#include "SineWave.h"
class BlowHole : public Instrmnt
{
public:
@@ -52,42 +54,43 @@ class BlowHole : public Instrmnt
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
BlowHole(StkFloat lowestFrequency);
BlowHole( StkFloat lowestFrequency );
//! Class destructor.
~BlowHole();
~BlowHole( 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 tonehole state (0.0 = closed, 1.0 = fully open).
void setTonehole(StkFloat newValue);
void setTonehole( StkFloat newValue );
//! Set the register hole state (0.0 = closed, 1.0 = fully open).
void setVent(StkFloat newValue);
void setVent( StkFloat newValue );
//! 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_[3];
ReedTable reedTable_;
OneZero filter_;
@@ -106,4 +109,41 @@ class BlowHole : public Instrmnt
};
inline StkFloat BlowHole :: 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();
// 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 );
lastFrame_[0] = delays_[0].tick( vent_.lastOut()+pb );
lastFrame_[0] *= 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 lastFrame_[0];
}
} // stk namespace
#endif

View File

@@ -1,3 +1,11 @@
#ifndef STK_BOWTABL_H
#define STK_BOWTABL_H
#include "Function.h"
#include <cmath>
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<frames.frames(); i++, samples += hop ) {
*samples = *samples + offset_;
*samples *= slope_;
*samples = (StkFloat) fabs( (double) *samples ) + 0.75;
*samples = (StkFloat) pow( *samples, (StkFloat) -4.0 );
if ( *samples > 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
*oSamples = *iSamples + offset_;
*oSamples *= slope_;
*oSamples = (StkFloat) fabs( (double) *oSamples ) + 0.75;
*oSamples = (StkFloat) pow( *oSamples, (StkFloat) -4.0 );
if ( *oSamples > 1.0) *oSamples = 1.0;
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -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

View File

@@ -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

View File

@@ -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<frames.frames(); i++, samples += hop ) {
*samples = effectMix_ * ( delayLine_[0].tick( *samples ) - *samples ) + *samples;
samples++;
*samples = effectMix_ * ( delayLine_[1].tick( *samples ) - *samples ) + *samples;
}
lastFrame_[0] = *(samples-hop);
lastFrame_[1] = *(samples-hop+1);
return frames;
}
inline StkFrames& Chorus :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
*oSamples++ = effectMix_ * ( delayLine_[0].tick( *iSamples ) - *iSamples ) + *iSamples;
*oSamples = effectMix_ * ( delayLine_[1].tick( *iSamples ) - *iSamples ) + *iSamples;
}
lastFrame_[0] = *(oSamples-oHop);
lastFrame_[1] = *(oSamples-oHop+1);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,16 @@
#ifndef STK_CLARINET_H
#define STK_CLARINET_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 Clarinet
\brief STK clarinet physical model class.
@@ -18,21 +31,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_CLARINET_H
#define STK_CLARINET_H
#include "Instrmnt.h"
#include "DelayL.h"
#include "ReedTable.h"
#include "OneZero.h"
#include "Envelope.h"
#include "Noise.h"
#include "SineWave.h"
class Clarinet : public Instrmnt
{
public:
@@ -40,36 +42,37 @@ class Clarinet : public Instrmnt
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
Clarinet(StkFloat lowestFrequency);
Clarinet( StkFloat lowestFrequency );
//! Class destructor.
~Clarinet();
~Clarinet( 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 );
//! 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 delayLine_;
ReedTable reedTable_;
OneZero filter_;
@@ -83,4 +86,31 @@ class Clarinet : public Instrmnt
};
inline StkFloat Clarinet :: tick( unsigned int )
{
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.
lastFrame_[0] = delayLine_.tick(breathPressure + pressureDiff * reedTable_.tick(pressureDiff));
// Apply output gain.
lastFrame_[0] *= outputGain_;
return lastFrame_[0];
}
} // stk namespace
#endif

View File

@@ -1,48 +1,40 @@
/***************************************************/
/*! \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.
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.
*/
/***************************************************/
#ifndef STK_DELAY_H
#define STK_DELAY_H
#include "Filter.h"
class Delay : protected Filter
namespace stk {
/***************************************************/
/*! \class Delay
\brief STK non-interpolating delay line class.
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.
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
class Delay : public Filter
{
public:
//! Default constructor creates a delay-line with maximum length of 4095 samples and zero delay.
Delay();
//! Overloaded constructor which specifies the current and maximum delay-line lengths.
//! The default constructor creates a delay-line with maximum length of 4095 samples and zero delay.
/*!
An StkError will be thrown if the delay parameter is less than
zero, the maximum delay parameter is less than one, or the delay
parameter is greater than the maxDelay value.
*/
Delay(unsigned long delay, unsigned long maxDelay);
Delay( unsigned long delay = 0, unsigned long maxDelay = 4095 );
//! Class destructor.
virtual ~Delay();
//! Clears the internal state of the delay line.
void clear();
~Delay();
//! Set the maximum delay-line length.
/*!
@@ -52,19 +44,16 @@ public:
likely occur. If the current maximum length is greater than the
new length, no change will be made.
*/
void setMaximumDelay(unsigned long delay);
void setMaximumDelay( unsigned long delay );
//! Set the delay-line length.
/*!
The valid range for \e theDelay is from 0 to the maximum delay-line length.
The valid range for \e delay is from 0 to the maximum delay-line length.
*/
void setDelay(unsigned long delay);
void setDelay( unsigned long delay );
//! Return the current delay-line length.
unsigned long getDelay(void) const;
//! Calculate and return the signal energy in the delay-line.
StkFloat energy(void) const;
unsigned long getDelay( void ) const { return delay_; };
//! Return the value at \e tapDelay samples from the delay-line input.
/*!
@@ -72,39 +61,114 @@ public:
relative to the last input value (i.e., a tapDelay of zero returns
the last input value).
*/
StkFloat contentsAt(unsigned long tapDelay);
StkFloat contentsAt( unsigned long tapDelay );
//! Return the last computed output value.
StkFloat lastOut(void) const;
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Return the value which will be output by the next call to tick().
//! Return the value that will be output by the next call to tick().
/*!
This method is valid only for delay settings greater than zero!
*/
virtual StkFloat nextOut(void);
StkFloat nextOut( void ) { return inputs_[outPoint_]; };
//! Calculate and return the signal energy in the delay-line.
StkFloat energy( void ) const;
//! Input one sample to the filter and return one output.
virtual 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.
*/
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 );
unsigned long inPoint_;
unsigned long outPoint_;
StkFloat delay_;
unsigned long delay_;
};
inline StkFloat Delay :: tick( StkFloat input )
{
inputs_[inPoint_++] = input * gain_;
// Check for end condition
if ( inPoint_ == inputs_.size() )
inPoint_ = 0;
// Read out next value
lastFrame_[0] = inputs_[outPoint_++];
if ( outPoint_ == inputs_.size() )
outPoint_ = 0;
return lastFrame_[0];
}
inline StkFrames& Delay :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= 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<frames.frames(); i++, samples += hop ) {
inputs_[inPoint_++] = *samples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
*samples = inputs_[outPoint_++];
if ( outPoint_ == inputs_.size() ) outPoint_ = 0;
}
lastFrame_[0] = *(samples-hop);
return frames;
}
inline StkFrames& Delay :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[inPoint_++] = *iSamples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
*oSamples = inputs_[outPoint_++];
if ( outPoint_ == inputs_.size() ) outPoint_ = 0;
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,12 +1,18 @@
#ifndef STK_DELAYA_H
#define STK_DELAYA_H
#include "Filter.h"
namespace stk {
/***************************************************/
/*! \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 0.5 is set.
An allpass filter has unity magnitude gain but variable phase
delay properties, making it useful in achieving fractional delays
@@ -15,55 +21,94 @@
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.
*/
/***************************************************/
#ifndef STK_DELAYA_H
#define STK_DELAYA_H
#include "Delay.h"
class DelayA : public Delay
class DelayA : public Filter
{
public:
//! Default constructor creates a delay-line with maximum length of 4095 samples and zero delay.
DelayA();
//! Overloaded constructor which specifies the current and maximum delay-line lengths.
//! Default constructor creates a delay-line with maximum length of 4095 samples and delay = 0.5.
/*!
An StkError will be thrown if the delay parameter is less than
zero, the maximum delay parameter is less than one, or the delay
parameter is greater than the maxDelay value.
*/
DelayA(StkFloat delay, unsigned long maxDelay);
DelayA( StkFloat delay = 0.5, unsigned long maxDelay = 4095 );
//! Class destructor.
~DelayA();
//! Clears the internal state of the delay line.
void clear();
//! Clears all internal states of the delay line.
void clear( void );
//! 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 length
/*!
The valid range for \e theDelay is from 0.5 to the maximum delay-line length.
The valid range for \e delay is from 0.5 to the maximum delay-line length.
*/
void setDelay(StkFloat delay);
void setDelay( StkFloat delay );
//! Return the current delay-line length.
StkFloat getDelay(void) const;
StkFloat getDelay( void ) const { return delay_; };
//! Return the value at \e tapDelay samples from the delay-line input.
/*!
The tap point is determined modulo the delay-line length and is
relative to the last input value (i.e., a tapDelay of zero returns
the last input value).
*/
StkFloat contentsAt( unsigned long tapDelay );
//! Return the last computed output value.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Return the value which will be output by the next call to tick().
/*!
This method is valid only for delay settings greater than zero!
*/
StkFloat nextOut(void);
StkFloat nextOut( void );
//! 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:
StkFloat computeSample( StkFloat input );
unsigned long inPoint_;
unsigned long outPoint_;
StkFloat delay_;
StkFloat alpha_;
StkFloat coeff_;
StkFloat apInput_;
@@ -71,4 +116,86 @@ protected:
bool doNextOut_;
};
inline StkFloat DelayA :: nextOut( void )
{
if ( doNextOut_ ) {
// Do allpass interpolation delay.
nextOutput_ = -coeff_ * lastFrame_[0];
nextOutput_ += apInput_ + ( coeff_ * inputs_[outPoint_] );
doNextOut_ = false;
}
return nextOutput_;
}
inline StkFloat DelayA :: tick( StkFloat input )
{
inputs_[inPoint_++] = input * gain_;
// Increment input pointer modulo length.
if ( inPoint_ == inputs_.size() )
inPoint_ = 0;
lastFrame_[0] = nextOut();
doNextOut_ = true;
// Save the allpass input and increment modulo length.
apInput_ = inputs_[outPoint_++];
if ( outPoint_ == inputs_.size() )
outPoint_ = 0;
return lastFrame_[0];
}
inline StkFrames& DelayA :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= 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<frames.frames(); i++, samples += hop ) {
inputs_[inPoint_++] = *samples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
*samples = nextOut();
lastFrame_[0] = *samples;
doNextOut_ = true;
apInput_ = inputs_[outPoint_++];
if ( outPoint_ == inputs_.size() ) outPoint_ = 0;
}
return frames;
}
inline StkFrames& DelayA :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[inPoint_++] = *iSamples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
*oSamples = nextOut();
lastFrame_[0] = *oSamples;
doNextOut_ = true;
apInput_ = inputs_[outPoint_++];
if ( outPoint_ == inputs_.size() ) outPoint_ = 0;
}
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,73 +1,197 @@
/***************************************************/
/*! \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.
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.
*/
/***************************************************/
#ifndef STK_DELAYL_H
#define STK_DELAYL_H
#include "Delay.h"
class DelayL : public Delay
namespace stk {
/***************************************************/
/*! \class DelayL
\brief STK linear interpolating delay line class.
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.
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
class DelayL : public Filter
{
public:
//! Default constructor creates a delay-line with maximum length of 4095 samples and zero delay.
DelayL();
//! Overloaded constructor which specifies the current and maximum delay-line lengths.
/*!
An StkError will be thrown if the delay parameter is less than
zero, the maximum delay parameter is less than one, or the delay
parameter is greater than the maxDelay value.
*/
DelayL(StkFloat delay, unsigned long maxDelay);
DelayL( StkFloat delay = 0.0, unsigned long maxDelay = 4095 );
//! Class destructor.
~DelayL();
//! 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 length.
/*!
The valid range for \e theDelay is from 0 to the maximum delay-line length.
The valid range for \e delay is from 0 to the maximum delay-line length.
*/
void setDelay(StkFloat delay);
void setDelay( StkFloat delay );
//! Return the current delay-line length.
StkFloat getDelay(void) const;
StkFloat getDelay( void ) const { return delay_; };
//! Return the value at \e tapDelay samples from the delay-line input.
/*!
The tap point is determined modulo the delay-line length and is
relative to the last input value (i.e., a tapDelay of zero returns
the last input value).
*/
StkFloat contentsAt( unsigned long tapDelay );
//! Return the last computed output value.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Return the value which will be output by the next call to tick().
/*!
This method is valid only for delay settings greater than zero!
*/
StkFloat nextOut(void);
StkFloat nextOut( void );
//! 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:
StkFloat computeSample( StkFloat input );
unsigned long inPoint_;
unsigned long outPoint_;
StkFloat delay_;
StkFloat alpha_;
StkFloat omAlpha_;
StkFloat nextOutput_;
bool doNextOut_;
};
inline 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_;
}
inline StkFloat DelayL :: tick( StkFloat input )
{
inputs_[inPoint_++] = input * gain_;
// Increment input pointer modulo length.
if ( inPoint_ == inputs_.size() )
inPoint_ = 0;
lastFrame_[0] = nextOut();
doNextOut_ = true;
// Increment output pointer modulo length.
if ( ++outPoint_ == inputs_.size() )
outPoint_ = 0;
return lastFrame_[0];
}
inline StkFrames& DelayL :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= 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<frames.frames(); i++, samples += hop ) {
inputs_[inPoint_++] = *samples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
*samples = nextOut();
doNextOut_ = true;
if ( ++outPoint_ == inputs_.size() ) outPoint_ = 0;
}
lastFrame_[0] = *(samples-hop);
return frames;
}
inline StkFrames& DelayL :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[inPoint_++] = *iSamples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
*oSamples = nextOut();
doNextOut_ = true;
if ( ++outPoint_ == inputs_.size() ) outPoint_ = 0;
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,12 @@
#ifndef STK_DRUMMER_H
#define STK_DRUMMER_H
#include "Instrmnt.h"
#include "FileWvIn.h"
#include "OnePole.h"
namespace stk {
/***************************************************/
/*! \class Drummer
\brief STK drum sample player class.
@@ -11,17 +20,10 @@
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.
*/
/***************************************************/
#ifndef STK_DRUMMER_H
#define STK_DRUMMER_H
#include "Instrmnt.h"
#include "FileWvIn.h"
#include "OnePole.h"
const int DRUM_NUMWAVES = 11;
const int DRUM_POLYPHONY = 4;
@@ -32,10 +34,10 @@ class Drummer : public Instrmnt
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
Drummer();
Drummer( void );
//! Class destructor.
~Drummer();
~Drummer( void );
//! Start a note with the given drum type and amplitude.
/*!
@@ -44,15 +46,16 @@ class Drummer : public Instrmnt
instrument. An StkError will be thrown if the rawwave path is
incorrectly set.
*/
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_[DRUM_POLYPHONY];
OnePole filters_[DRUM_POLYPHONY];
std::vector<int> 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<DRUM_POLYPHONY; i++ ) {
if ( soundOrder_[i] >= 0 ) {
if ( waves_[i].isFinished() ) {
// Re-order the list.
for ( int j=0; j<DRUM_POLYPHONY; j++ ) {
if ( soundOrder_[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

View File

@@ -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<frames.frames(); i++, samples += hop ) {
*samples = effectMix_ * ( delayLine_.tick( *samples ) - *samples ) + *samples;
}
lastFrame_[0] = *(samples-hop);
return frames;
}
inline StkFrames& Echo :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
*oSamples = effectMix_ * ( delayLine_.tick( *iSamples ) - *iSamples ) + *iSamples;
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,69 +1,79 @@
#ifndef STK_EFFECT_H
#define STK_EFFECT_H
#include "Stk.h"
#include <cmath>
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

View File

@@ -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<frames.frames(); i++, samples += hop )
*samples = tick();
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,14 @@
#ifndef STK_FM_H
#define STK_FM_H
#include "Instrmnt.h"
#include "ADSR.h"
#include "FileLoop.h"
#include "SineWave.h"
#include "TwoZero.h"
namespace stk {
/***************************************************/
/*! \class FM
\brief STK abstract FM synthesis base class.
@@ -19,19 +30,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_FM_H
#define STK_FM_H
#include "Instrmnt.h"
#include "ADSR.h"
#include "WaveLoop.h"
#include "SineWave.h"
#include "TwoZero.h"
class FM : public Instrmnt
{
public:
@@ -42,53 +44,54 @@ class FM : public Instrmnt
FM( unsigned int operators = 4 );
//! Class destructor.
virtual ~FM();
virtual ~FM( void );
//! Reset and clear all wave and envelope states.
void clear();
void clear( void );
//! Load the rawwave filenames in waves.
void loadWaves(const char **filenames);
void loadWaves( const char **filenames );
//! Set instrument parameters for a particular frequency.
virtual void setFrequency(StkFloat frequency);
virtual void setFrequency( StkFloat frequency );
//! Set the frequency ratio for the specified wave.
void setRatio(unsigned int waveIndex, StkFloat ratio);
void setRatio( unsigned int waveIndex, StkFloat ratio );
//! Set the gain for the specified wave.
void setGain(unsigned int waveIndex, StkFloat gain);
void setGain( unsigned int waveIndex, StkFloat gain );
//! Set the modulation speed in Hz.
void setModulationSpeed(StkFloat mSpeed);
void setModulationSpeed( StkFloat mSpeed ) { vibrato_.setFrequency( mSpeed ); };
//! Set the modulation depth.
void setModulationDepth(StkFloat mDepth);
void setModulationDepth( StkFloat mDepth ) { modDepth_ = mDepth; };
//! Set the value of control1.
void setControl1(StkFloat cVal);
void setControl1( StkFloat cVal ) { control1_ = cVal * 2.0; };
//! Set the value of control1.
void setControl2(StkFloat cVal);
void setControl2( StkFloat cVal ) { control2_ = cVal * 2.0; };
//! Start envelopes toward "on" targets.
void keyOn();
void keyOn( void );
//! Start envelopes toward "off" targets.
void keyOff();
void keyOff( void );
//! 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);
virtual void controlChange( int number, StkFloat value );
//! Compute and return one output sample.
virtual StkFloat tick( unsigned int ) = 0;
protected:
virtual StkFloat computeSample( void ) = 0;
std::vector<ADSR *> adsr_;
std::vector<WaveLoop *> waves_;
std::vector<FileLoop *> waves_;
SineWave vibrato_;
TwoZero twozero_;
unsigned int nOperators_;
@@ -104,4 +107,6 @@ class FM : public Instrmnt
};
} // stk namespace
#endif

View File

@@ -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

161
include/FileLoop.h Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 <vector>
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<StkFloat> &bCoefficients, std::vector<StkFloat> &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<StkFloat> &bCoefficients, std::vector<StkFloat> &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<StkFloat> &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<StkFloat> &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<StkFloat> b_;
std::vector<StkFloat> a_;
std::vector<StkFloat> outputs_;
std::vector<StkFloat> inputs_;
StkFrames outputs_;
StkFrames inputs_;
};
inline void Filter :: clear( void )
{
unsigned int i;
for ( i=0; i<inputs_.size(); i++ )
inputs_[i] = 0.0;
for ( i=0; i<outputs_.size(); i++ )
outputs_[i] = 0.0;
for ( i=0; i<lastFrame_.size(); i++ )
lastFrame_[i] = 0.0;
}
} // stk namespace
#endif

155
include/Fir.h Normal file
View File

@@ -0,0 +1,155 @@
#ifndef STK_FIR_H
#define STK_FIR_H
#include "Filter.h"
namespace stk {
/***************************************************/
/*! \class Fir
\brief STK general finite impulse response filter class.
This class provides a generic digital filter structure that can be
used to implement FIR filters. For filters with feedback terms,
the Iir class should be used.
In particular, this class implements the standard difference
equation:
y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb]
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 Fir : public Filter
{
public:
//! Default constructor creates a zero-order pass-through "filter".
Fir( void );
//! Overloaded constructor which takes filter coefficients.
/*!
An StkError can be thrown if the coefficient vector size is
zero.
*/
Fir( std::vector<StkFloat> &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<StkFloat> &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; j<frames.frames(); j++, samples += hop ) {
inputs_[0] = gain_ * *samples;
*samples = 0.0;
for ( i=b_.size()-1; i>0; 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; j<iFrames.frames(); j++, iSamples += iHop, oSamples += oHop ) {
inputs_[0] = gain_ * *iSamples;
*oSamples = 0.0;
for ( i=b_.size()-1; i>0; 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

View File

@@ -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

View File

@@ -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<frames.frames(); i++, samples += hop )
*samples = tick( *samples );
return frames;
}
inline StkFrames& FormSwep :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop )
*oSamples = tick( *iSamples );
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,54 +1,41 @@
#ifndef STK_FUNCTION_H
#define STK_FUNCTION_H
#include "Stk.h"
namespace stk {
/***************************************************/
/*! \class Function
\brief STK abstract function parent class.
This class provides common functionality for STK classes which
This class provides common functionality for STK classes that
implement tables or other types of input to output function
mappings.
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_FUNCTION_H
#define STK_FUNCTION_H
class Function : public Stk
{
public:
//! Class constructor.
Function();
Function( void ) { lastFrame_.resize( 1, 1, 0.0 ); };
//! Class destructor.
virtual ~Function();
//! Return the last output value.
virtual StkFloat lastOut() const { return lastOutput_; };
//! Return the last computed output sample.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! 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 function 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.
*/
virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
virtual StkFloat tick( StkFloat input ) = 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( StkFloat input ) = 0;
StkFloat lastOutput_;
StkFrames lastFrame_;
};
} // stk namespace
#endif

View File

@@ -1,53 +1,50 @@
/***************************************************/
/*! \class Generator
\brief STK abstract unit generator parent class.
This class provides common functionality for
STK unit generator sample-source subclasses.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
/***************************************************/
#ifndef STK_GENERATOR_H
#define STK_GENERATOR_H
#include "Stk.h"
namespace stk {
/***************************************************/
/*! \class Generator
\brief STK abstract unit generator parent class.
This class provides limited common functionality for STK unit
generator sample-source subclasses. It is general enough to
support both monophonic and polyphonic output classes.
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
class Generator : public Stk
{
public:
//! Class constructor.
Generator( void );
Generator( void ) { lastFrame_.resize( 1, 1, 0.0 ); };
//! Class destructor.
virtual ~Generator( void );
//! Return the number of output channels for the class.
unsigned int channelsOut( void ) const { return lastFrame_.channels(); };
//! Return the last output value.
virtual StkFloat lastOut( void ) const { return lastOutput_; };
//! Return an StkFrames reference to the last output sample frame.
const StkFrames& lastFrame( void ) const { return lastFrame_; };
//! Compute one sample and output.
StkFloat tick( void );
//! Fill a channel of the StkFrames object with computed outputs.
//! Fill the StkFrames object with computed sample frames, starting at the specified channel.
/*!
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 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 );
virtual StkFrames& tick( StkFrames& frames, 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 StkFloat computeSample( void ) = 0;
StkFloat lastOutput_;
protected:
StkFrames lastFrame_;
};
#endif
} // stk namespace
#endif

View File

@@ -1,20 +1,3 @@
/***************************************************/
/*! \class Granulate
\brief STK granular synthesis class.
This class implements a real-time granular synthesis algorithm
that operates on an input soundfile. Currently, only monophonic
files are supported. Various functions are provided to allow
control over voice and grain parameters.
The functionality of this class is based on the program MacPod by
Chris Rolfe and Damian Keller, though there are likely to be a
number of differences in the actual implementation.
by Gary Scavone, 2005.
*/
/***************************************************/
#ifndef STK_GRANULATE_H
#define STK_GRANULATE_H
@@ -23,6 +6,25 @@
#include "Envelope.h"
#include "Noise.h"
namespace stk {
/***************************************************/
/*! \class Granulate
\brief STK granular synthesis class.
This class implements a real-time granular synthesis algorithm
that operates on an input soundfile. Multi-channel files are
supported. Various functions are provided to allow control over
voice and grain parameters.
The functionality of this class is based on the program MacPod by
Chris Rolfe and Damian Keller, though there are likely to be a
number of differences in the actual implementation.
by Gary Scavone, 2005 - 2009.
*/
/***************************************************/
class Granulate: public Generator
{
public:
@@ -33,7 +35,7 @@ class Granulate: public Generator
Granulate( unsigned int nVoices, std::string fileName, bool typeRaw = false );
//! Class destructor.
~Granulate();
~Granulate( void );
//! Load a monophonic soundfile to be "granulated".
/*!
@@ -47,7 +49,7 @@ class Granulate: public Generator
Multiple grains are offset from one another in time by grain
duration / nVoices.
*/
void reset();
void reset( void );
//! Set the number of simultaneous grain "voices" to use.
/*!
@@ -96,6 +98,30 @@ class Granulate: public Generator
*/
void setRandomFactor( StkFloat randomness = 0.1 );
//! 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.
StkFloat tick( unsigned int channel = 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 );
enum GrainState {
GRAIN_STOPPED,
GRAIN_FADEIN,
@@ -124,7 +150,6 @@ class Granulate: public Generator
delayCount(0), counter(0), pointer(0), startPointer(0), repeats(0), state(GRAIN_STOPPED) {}
};
StkFloat computeSample( void );
void calculateGrain( Granulate::Grain& grain );
StkFrames data_;
@@ -144,4 +169,39 @@ class Granulate: public Generator
};
inline StkFloat Granulate :: lastOut( unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= 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; i<frames.frames(); i++, samples += hop ) {
*samples++ = tick();
for ( j=1; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,10 @@
#ifndef STK_HEVYMETL_H
#define STK_HEVYMETL_H
#include "FM.h"
namespace stk {
/***************************************************/
/*! \class HevyMetl
\brief STK heavy metal FM synthesis instrument.
@@ -24,15 +31,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_HEVYMETL_H
#define STK_HEVYMETL_H
#include "FM.h"
class HevyMetl : public FM
{
public:
@@ -40,17 +42,48 @@ class HevyMetl : public FM
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
HevyMetl();
HevyMetl( void );
//! Class destructor.
~HevyMetl();
~HevyMetl( void );
//! 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 HevyMetl :: 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]);
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

202
include/Iir.h Normal file
View File

@@ -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<StkFloat> &bCoefficients, std::vector<StkFloat> &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<StkFloat> &bCoefficients, std::vector<StkFloat> &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<StkFloat> &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<StkFloat> &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; j<frames.frames(); j++, samples += hop ) {
outputs_[0] = 0.0;
inputs_[0] = gain_ * *samples;
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];
}
*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; j<iFrames.frames(); j++, iSamples += iHop, oSamples += oHop ) {
outputs_[0] = 0.0;
inputs_[0] = gain_ * *iSamples;
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];
}
*oSamples = outputs_[0];
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -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

View File

@@ -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

View File

@@ -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<frames.frames(); i++, samples += hop )
*samples++ = tick();
}
else {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples++ = tick();
for ( j=1; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
}
return frames;
}
inline void Instrmnt :: controlChange( int number, StkFloat value )
{
errorString_ << "Instrmnt::controlChange: virtual function call!";
handleError( StkError::WARNING );
}
} // stk namespace
#endif

View File

@@ -1,24 +1,25 @@
/***************************************************/
/*! \class JCRev
\brief John Chowning's reverberator class.
This class is derived from the CLM JCRev
function, which is based on the use of
networks of simple allpass and comb delay
filters. This class implements three series
allpass units, followed by four parallel comb
filters, and two decorrelation delay lines in
parallel at the output.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
/***************************************************/
#ifndef STK_JCREV_H
#define STK_JCREV_H
#include "Effect.h"
#include "Delay.h"
#include "Delay.h"
namespace stk {
/***************************************************/
/*! \class JCRev
\brief John Chowning's reverberator class.
This class takes a monophonic input signal and produces a stereo
output signal. It is derived from the CLM JCRev function, which
is based on the use of networks of simple allpass and comb delay
filters. This class implements three series allpass units,
followed by four parallel comb filters, and two decorrelation
delay lines in parallel at the output.
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
class JCRev : public Effect
{
@@ -26,18 +27,58 @@ class JCRev : public Effect
//! Class constructor taking a T60 decay time argument (one second default value).
JCRev( StkFloat T60 = 1.0 );
//! Class destructor.
~JCRev();
//! 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_[3];
Delay combDelays_[4];
@@ -48,5 +89,70 @@ class JCRev : public Effect
};
inline StkFloat JCRev :: lastOut( unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel > 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

View File

@@ -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<frames.frames(); i++, samples += hop ) {
*samples = *samples * (*samples * *samples - 1.0);
if ( *samples > 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
*oSamples = *oSamples * (*oSamples * *oSamples - 1.0);
if ( *oSamples > 1.0) *oSamples = 1.0;
if ( *oSamples < -1.0) *oSamples = -1.0;
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -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

View File

@@ -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

View File

@@ -1,3 +1,21 @@
#ifndef STK_MESSAGER_H
#define STK_MESSAGER_H
#include "Stk.h"
#include "Skini.h"
#include <queue>
#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 <queue>
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

View File

@@ -1,3 +1,14 @@
#ifndef STK_MIDIFILEIN_H
#define STK_MIDIFILEIN_H
#include "Stk.h"
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
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 <string>
#include <vector>
#include <fstream>
#include <sstream>
class MidiFileIn : public Stk
{
public:
@@ -128,4 +130,6 @@ class MidiFileIn : public Stk
std::vector<unsigned int> trackTempoIndex_;
};
} // stk namespace
#endif

View File

@@ -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; i<nModes_; i++ )
temp2 += filters_[i]->tick(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

View File

@@ -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

View File

@@ -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; i<frames.frames(); i++, samples += hop )
*samples = Modulate::tick();
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,11 @@
#ifndef STK_MOOG_H
#define STK_MOOG_H
#include "Sampler.h"
#include "FormSwep.h"
namespace stk {
/***************************************************/
/*! \class Moog
\brief STK moog-like swept filter sampling synthesis class.
@@ -14,16 +22,10 @@
- Vibrato Gain = 1
- Gain = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#ifndef STK_MOOG_H
#define STK_MOOG_H
#include "Sampler.h"
#include "FormSwep.h"
class Moog : public Sampler
{
public:
@@ -31,30 +33,31 @@ class Moog : public Sampler
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
Moog();
Moog( void );
//! Class destructor.
~Moog();
~Moog( 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 );
//! Set the modulation (vibrato) speed in Hz.
void setModulationSpeed(StkFloat mSpeed);
void setModulationSpeed( StkFloat mSpeed ) { loops_[1]->setFrequency( 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

View File

@@ -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

View File

@@ -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

View File

@@ -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.frames(); i++, samples += hop )
*samples = (StkFloat) ( 2.0 * rand() / (RAND_MAX + 1.0) - 1.0 );
lastFrame_[0] = *(samples-hop);
return frames;
}
} // stk namespace
#endif

View File

@@ -1,43 +1,40 @@
/***************************************************/
/*! \class OnePole
\brief STK one-pole filter class.
This protected Filter subclass implements
a one-pole digital filter. A method is
provided for setting the pole position along
the real axis of the z-plane while maintaining
a constant peak filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
/***************************************************/
#ifndef STK_ONEPOLE_H
#define STK_ONEPOLE_H
#include "Filter.h"
class OnePole : protected Filter
namespace stk {
/***************************************************/
/*! \class OnePole
\brief STK one-pole filter class.
This class implements a one-pole digital filter. A method is
provided for setting the pole position along the real axis of the
z-plane while maintaining a constant peak filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
class OnePole : public Filter
{
public:
//! Default constructor creates a first-order low-pass filter.
OnePole();
//! Overloaded constructor which sets the pole position during instantiation.
OnePole( StkFloat thePole );
//! The default constructor creates a low-pass filter (pole at z = 0.9).
OnePole( StkFloat thePole = 0.9 );
//! Class destructor.
~OnePole();
//! Clears the internal state 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 all filter coefficients.
void setCoefficients( StkFloat b0, StkFloat a1, bool clearState = false );
//! Set the pole position in the z-plane.
/*!
@@ -47,33 +44,90 @@ public:
pole value produces a high-pass filter. This method does not
affect the filter \e gain value.
*/
void setPole(StkFloat thePole);
//! 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 setPole( StkFloat thePole );
//! 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 );
};
inline StkFloat OnePole :: tick( StkFloat input )
{
inputs_[0] = gain_ * input;
lastFrame_[0] = b_[0] * inputs_[0] - a_[1] * outputs_[1];
outputs_[1] = lastFrame_[0];
return lastFrame_[0];
}
inline StkFrames& OnePole :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= 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<frames.frames(); i++, samples += hop ) {
inputs_[0] = gain_ * *samples;
*samples = b_[0] * inputs_[0] - a_[1] * outputs_[1];
outputs_[1] = *samples;
}
lastFrame_[0] = outputs_[1];
return frames;
}
inline StkFrames& OnePole :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[0] = gain_ * *iSamples;
*oSamples = b_[0] * inputs_[0] - a_[1] * outputs_[1];
outputs_[1] = *oSamples;
}
lastFrame_[0] = outputs_[1];
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,43 +1,40 @@
/***************************************************/
/*! \class OneZero
\brief STK one-zero filter class.
This protected Filter subclass implements
a one-zero digital filter. A method is
provided for setting the zero position
along the real axis of the z-plane while
maintaining a constant filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
/***************************************************/
#ifndef STK_ONEZERO_H
#define STK_ONEZERO_H
#include "Filter.h"
class OneZero : protected Filter
namespace stk {
/***************************************************/
/*! \class OneZero
\brief STK one-zero filter class.
This class implements a one-zero digital filter. A method is
provided for setting the zero position along the real axis of the
z-plane while maintaining a constant filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
class OneZero : public Filter
{
public:
//! Default constructor creates a first-order low-pass filter.
OneZero();
//! Overloaded constructor which sets the zero position during instantiation.
OneZero(StkFloat theZero);
//! The default constructor creates a low-pass filter (zero at z = -1.0).
OneZero( StkFloat theZero = -1.0 );
//! Class destructor.
~OneZero();
//! Clears the internal state 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 all filter coefficients.
void setCoefficients( StkFloat b0, StkFloat b1, bool clearState = false );
//! Set the zero position in the z-plane.
/*!
@@ -47,33 +44,91 @@ class OneZero : protected Filter
negative zero value produces a low-pass filter. This method does
not affect the filter \e gain value.
*/
void setZero(StkFloat theZero);
//! 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 setZero( StkFloat theZero );
//! 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 );
};
inline StkFloat OneZero :: tick( StkFloat input )
{
inputs_[0] = gain_ * input;
lastFrame_[0] = b_[1] * inputs_[1] + b_[0] * inputs_[0];
inputs_[1] = inputs_[0];
return lastFrame_[0];
}
inline StkFrames& OneZero :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= 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<frames.frames(); i++, samples += hop ) {
inputs_[0] = gain_ * *samples;
*samples = b_[1] * inputs_[1] + b_[0] * inputs_[0];
inputs_[1] = inputs_[0];
}
lastFrame_[0] = *(samples-hop);
return frames;
}
inline StkFrames& OneZero :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[0] = gain_ * *iSamples;
*oSamples = b_[1] * inputs_[1] + b_[0] * inputs_[0];
inputs_[1] = inputs_[0];
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,43 +1,84 @@
#ifndef STK_PRCREV_H
#define STK_PRCREV_H
#include "Effect.h"
#include "Delay.h"
namespace stk {
/***************************************************/
/*! \class PRCRev
\brief Perry's simple reverberator class.
This class is based on some of the famous
Stanford/CCRMA reverbs (NRev, KipRev), which
were based on the Chowning/Moorer/Schroeder
reverberators using networks of simple allpass
and comb delay filters. This class implements
two series allpass units and two parallel comb
filters.
This class takes a monophonic input signal and produces a stereo
output signal. It is based on some of the famous Stanford/CCRMA
reverbs (NRev, KipRev), which were based on the
Chowning/Moorer/Schroeder reverberators using networks of simple
allpass and comb delay filters. This class implements two series
allpass units and two parallel comb filters.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#ifndef STK_PRCREV_H
#define STK_PRCREV_H
#include "Effect.h"
#include "Delay.h"
class PRCRev : public Effect
{
public:
//! Class constructor taking a T60 decay time argument (one second default value).
PRCRev( StkFloat T60 = 1.0 );
//! Class destructor.
~PRCRev();
//! 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_[2];
Delay combDelays_[2];
@@ -46,5 +87,54 @@ protected:
};
inline StkFloat PRCRev :: lastOut( unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel > 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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<frames.frames(); i++, samples += hop ) {
inputs_[0] = gain_ * *samples;
*samples = b_[0] * inputs_[0] + b_[1] * inputs_[1] - a_[1] * outputs_[1];
inputs_[1] = inputs_[0];
outputs_[1] = *samples;
}
lastFrame_[0] = outputs_[1];
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,10 @@
#ifndef STK_REEDTABLE_H
#define STK_REEDTABLE_H
#include "Function.h"
namespace stk {
/***************************************************/
/*! \class ReedTable
\brief STK reed table class.
@@ -13,23 +20,15 @@
Smith (1986), Hirschman, Cook, Scavone, 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_REEDTABLE_H
#define STK_REEDTABLE_H
#include "Function.h"
class ReedTable : public Function
{
public:
//! Default constructor.
ReedTable();
//! Class destructor.
~ReedTable();
ReedTable( void ) : offset_(0.6), slope_(-0.8) {};
//! Set the table offset value.
/*!
@@ -37,7 +36,7 @@ public:
of the initial reed tip opening (a greater offset
represents a smaller opening).
*/
void setOffset(StkFloat offset);
void setOffset( StkFloat offset ) { offset_ = offset; };
//! Set the table slope value.
/*!
@@ -45,15 +44,100 @@ public:
stiffness (a greater slope represents a harder
reed).
*/
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 ReedTable :: tick( StkFloat input )
{
// The input is differential pressure across the reed.
lastFrame_[0] = offset_ + (slope_ * input);
// If output is > 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<frames.frames(); i++, samples += hop ) {
*samples = offset_ + (slope_ * *samples);
if ( *samples > 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
*oSamples = offset_ + (slope_ * *iSamples);
if ( *oSamples > 1.0) *oSamples = 1.0;
if ( *oSamples < -1.0) *oSamples = -1.0;
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -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

View File

@@ -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

View File

@@ -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<RtAudio::DeviceInfo> 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,

View File

@@ -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<unsigned char> *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<MidiMessage> 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

View File

@@ -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

View File

@@ -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

View File

@@ -9,10 +9,12 @@
where <name> 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

View File

@@ -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

View File

@@ -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<FileWvIn *> attacks_;
std::vector<WaveLoop *> loops_;
std::vector<FileLoop *> loops_;
OnePole filter_;
StkFloat baseFrequency_;
std::vector<StkFloat> attackRatios_;
@@ -60,4 +63,6 @@ class Sampler : public Instrmnt
};
} // stk namespace
#endif

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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<frames.frames(); i++, samples += hop ) {
// 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_;
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

View File

@@ -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<frames.frames(); i++, samples += hop )
*samples = SingWave::tick();
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,15 @@
#ifndef STK_SITAR_H
#define STK_SITAR_H
#include "Instrmnt.h"
#include "DelayA.h"
#include "OneZero.h"
#include "Noise.h"
#include "ADSR.h"
#include <cmath>
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

View File

@@ -1,3 +1,13 @@
#ifndef STK_SKINI_H
#define STK_SKINI_H
#include "Stk.h"
#include <vector>
#include <string>
#include <fstream>
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 <vector>
#include <string>
#include <fstream>
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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,3 +1,20 @@
#ifndef STK_STK_H
#define STK_STK_H
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <stdlib.h>
/*! \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 <string>
#include <iostream>
#include <sstream>
#include <vector>
//#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<size_; i++ )
*dptr++ += *fptr++;
}
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<size_; i++ )
*dptr++ *= *fptr++;
}
// Here are a few other useful typedefs.
typedef unsigned short UINT16;
@@ -412,6 +530,6 @@ const StkFloat ONE_OVER_128 = 0.0078125;
#define __STK_REALTIME__
#endif
//#define _STK_DEBUG_
} // stk namespace
#endif

View File

@@ -1,43 +0,0 @@
/***************************************************/
/*! \class SubNoise
\brief STK sub-sampled noise generator.
Generates a new random number every "rate" ticks
using the 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.
*/
/***************************************************/
#ifndef STK_SUBNOISE_H
#define STK_SUBNOISE_H
#include "Noise.h"
class SubNoise : public Noise
{
public:
//! Default constructor sets sub-sample rate to 16.
SubNoise( int subRate = 16 );
//! Class destructor.
~SubNoise();
//! Return the current sub-sampling rate.
int subRate( void ) const { return rate_; };
//! Set the sub-sampling rate.
void setRate( int subRate );
protected:
StkFloat computeSample( void );
int counter_;
int rate_;
};
#endif

216
include/TapDelay.h Normal file
View File

@@ -0,0 +1,216 @@
#ifndef STK_TAPDELAY_H
#define STK_TAPDELAY_H
#include "Filter.h"
namespace stk {
/***************************************************/
/*! \class TapDelay
\brief STK non-interpolating tapped delay line class.
This class implements a non-interpolating digital delay-line with
an arbitrary number of output "taps". If the maximum length and
tap delays are not specified during instantiation, a fixed maximum
length of 4095 and a single tap delay of zero is set.
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 - 2009.
*/
/***************************************************/
class TapDelay : public Filter
{
public:
//! The default constructor creates a delay-line with maximum length of 4095 samples and a single tap at delay = 0.
/*!
An StkError will be thrown if any tap delay parameter is less
than zero, the maximum delay parameter is less than one, or any
tap delay parameter is greater than the maxDelay value.
*/
TapDelay( std::vector<unsigned long> taps = std::vector<unsigned long>( 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<unsigned long> taps );
//! Return the current delay-line length.
std::vector<unsigned long> 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<unsigned long> outPoint_;
std::vector<unsigned long> 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<outPoint_.size(); i++ ) {
*outs++ = inputs_[outPoint_[i]];
lastFrame_[i] = *outs;
if ( ++outPoint_[i] == inputs_.size() )
outPoint_[i] = 0;
}
return outputs;
}
inline StkFrames& TapDelay :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= 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<frames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[inPoint_++] = *iSamples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
for ( j=0; j<outPoint_.size(); j++ ) {
*oSamples++ = inputs_[outPoint_[j]];
if ( ++outPoint_[j] == inputs_.size() ) outPoint_[j] = 0;
}
}
oSamples -= frames.channels();
for ( j=0; j<outPoint_.size(); j++ ) lastFrame_[j] = *oSamples++;
return frames;
}
inline StkFrames& TapDelay :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= 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; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[inPoint_++] = *iSamples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
for ( j=0; j<outPoint_.size(); j++ ) {
*oSamples++ = inputs_[outPoint_[j]];
if ( ++outPoint_[j] == inputs_.size() ) outPoint_[j] = 0;
}
}
oSamples -= oFrames.channels();
for ( j=0; j<outPoint_.size(); j++ ) lastFrame_[j] = *oSamples++;
return iFrames;
}
#endif
} // stk namespace

View File

@@ -1,3 +1,10 @@
#ifndef STK_TCPCLIENT_H
#define STK_TCPCLIENT_H
#include "Socket.h"
namespace stk {
/***************************************************/
/*! \class TcpClient
\brief STK TCP socket client class.
@@ -19,15 +26,10 @@
less than or equal to zero indicate a closed
or lost connection or the occurence of an error.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#ifndef STK_TCPCLIENT_H
#define STK_TCPCLIENT_H
#include "Socket.h"
class TcpClient : public Socket
{
public:
@@ -58,4 +60,6 @@ class TcpClient : public Socket
};
#endif // defined(STK_TCPCLIENT_H)
} // stk namespace
#endif

View File

@@ -1,3 +1,10 @@
#ifndef STK_TCPSERVER_H
#define STK_TCPSERVER_H
#include "Socket.h"
namespace stk {
/***************************************************/
/*! \class TcpServer
\brief STK TCP socket server class.
@@ -19,15 +26,10 @@
less than or equal to zero indicate a closed
or lost connection or the occurence of an error.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#ifndef STK_TCPSERVER_H
#define STK_TCPSERVER_H
#include "Socket.h"
class TcpServer : public Socket
{
public:
@@ -58,4 +60,6 @@ class TcpServer : public Socket
};
#endif // defined(STK_TCPSERVER_H)
} // stk namespace
#endif

View File

@@ -1,25 +1,3 @@
/***************************************************/
/*! \class Thread
\brief STK thread class.
This class provides a uniform interface for cross-platform
threads. On unix systems, the pthread library is used. Under
Windows, the C runtime threadex functions are used.
Each instance of the Thread class can be used to control a single
thread process. Routines are provided to signal cancelation
and/or joining with a thread, though it is not possible for this
class to know the running status of a thread once it is started.
For cross-platform compatability, thread functions should be
declared as follows:
THREAD_RETURN THREAD_TYPE thread_function(void *ptr)
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
/***************************************************/
#ifndef STK_THREAD_H
#define STK_THREAD_H
@@ -44,6 +22,30 @@
#endif
namespace stk {
/***************************************************/
/*! \class Thread
\brief STK thread class.
This class provides a uniform interface for cross-platform
threads. On unix systems, the pthread library is used. Under
Windows, the C runtime threadex functions are used.
Each instance of the Thread class can be used to control a single
thread process. Routines are provided to signal cancelation
and/or joining with a thread, though it is not possible for this
class to know the running status of a thread once it is started.
For cross-platform compatability, thread functions should be
declared as follows:
THREAD_RETURN THREAD_TYPE thread_function(void *ptr)
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
class Thread : public Stk
{
public:
@@ -91,4 +93,6 @@ class Thread : public Stk
};
} // stk namespace
#endif

View File

@@ -1,3 +1,10 @@
#ifndef STK_TUBEBELL_H
#define STK_TUBEBELL_H
#include "FM.h"
namespace stk {
/***************************************************/
/*! \class TubeBell
\brief STK tubular bell (orchestral chime) 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_TUBEBELL_H
#define STK_TUBEBELL_H
#include "FM.h"
class TubeBell : public FM
{
public:
@@ -42,17 +44,45 @@ class TubeBell : public FM
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
TubeBell();
TubeBell( void );
//! Class destructor.
~TubeBell();
~TubeBell( void );
//! 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 TubeBell :: 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

View File

@@ -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<frames.frames(); i++, samples += hop ) {
inputs_[0] = gain_ * *samples;
*samples = b_[0] * inputs_[0] - a_[1] * outputs_[1] - a_[2] * outputs_[2];
outputs_[2] = outputs_[1];
outputs_[1] = *samples;
}
lastFrame_[0] = outputs_[1];
return frames;
}
inline StkFrames& TwoPole :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[0] = gain_ * *iSamples;
*oSamples = b_[0] * inputs_[0] - a_[1] * outputs_[1] - a_[2] * outputs_[2];
outputs_[2] = outputs_[1];
outputs_[1] = *oSamples;
}
lastFrame_[0] = outputs_[1];
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,23 +1,23 @@
/***************************************************/
/*! \class TwoZero
\brief STK two-zero filter class.
This protected Filter subclass implements
a two-zero digital filter. A method is
provided for creating a "notch" in the
frequency response while maintaining a
constant filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
/***************************************************/
#ifndef STK_TWOZERO_H
#define STK_TWOZERO_H
#include "Filter.h"
class TwoZero : protected Filter
namespace stk {
/***************************************************/
/*! \class TwoZero
\brief STK two-zero filter class.
This class implements a two-zero digital filter. A method is
provided for creating a "notch" in the frequency response while
maintaining a constant filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
class TwoZero : public Filter
{
public:
//! Default constructor creates a second-order pass-through filter.
@@ -29,17 +29,17 @@ class TwoZero : 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 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 all filter coefficients.
void setCoefficients( StkFloat b0, StkFloat b1, StkFloat b2, bool clearState = false );
//! Sets the filter coefficients for a "notch" at \e frequency (in Hz).
/*!
@@ -52,36 +52,96 @@ class TwoZero : protected Filter
frequency. The closer the zeros are to the unit-circle (\e radius
close to or equal to one), the narrower the resulting notch width.
*/
void setNotch(StkFloat frequency, StkFloat radius);
//! 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 setNotch( StkFloat frequency, StkFloat radius );
//! 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 );
void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
};
inline StkFloat TwoZero :: tick( StkFloat input )
{
inputs_[0] = gain_ * input;
lastFrame_[0] = b_[2] * inputs_[2] + b_[1] * inputs_[1] + b_[0] * inputs_[0];
inputs_[2] = inputs_[1];
inputs_[1] = inputs_[0];
return lastFrame_[0];
}
inline StkFrames& TwoZero :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= 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<frames.frames(); i++, samples += hop ) {
inputs_[0] = gain_ * *samples;
*samples = b_[2] * inputs_[2] + b_[1] * inputs_[1] + b_[0] * inputs_[0];
inputs_[2] = inputs_[1];
inputs_[1] = inputs_[0];
}
lastFrame_[0] = *(samples-hop);
return frames;
}
inline StkFrames& TwoZero :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= 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<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[0] = gain_ * *iSamples;
*oSamples = b_[2] * inputs_[2] + b_[1] * inputs_[1] + b_[0] * inputs_[0];
inputs_[2] = inputs_[1];
inputs_[1] = inputs_[0];
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,10 @@
#ifndef STK_UDPSOCKET_H
#define STK_UDPSOCKET_H
#include "Socket.h"
namespace stk {
/***************************************************/
/*! \class UdpSocket
\brief STK UDP socket server/client class.
@@ -17,15 +24,10 @@
read/write methods. Values less than or equal to zero indicate
the occurence of an error.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
by Perry R. Cook and Gary P. Scavone, 1995 - 2009.
*/
/***************************************************/
#ifndef STK_UDPSOCKET_H
#define STK_UDPSOCKET_H
#include "Socket.h"
class UdpSocket : public Socket
{
public:
@@ -69,4 +71,6 @@ class UdpSocket : public Socket
};
#endif // defined(STK_UDPSOCKET_H)
} // stk namespace
#endif

View File

@@ -1,56 +1,68 @@
#ifndef STK_VECTOR3D_H
#define STK_VECTOR3D_H
#include "Stk.h"
#include <cmath>
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

View File

@@ -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

View File

@@ -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 <vector>
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<Voice> 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; j<lastFrame_.channels(); j++ ) lastFrame_[j] = 0.0;
for ( unsigned int i=0; i<voices_.size(); i++ ) {
if ( voices_[i].sounding != 0 ) {
voices_[i].instrument->tick();
for ( j=0; j<voices_[i].instrument->channelsOut(); 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; i<frames.frames(); i++, samples += hop ) {
tick();
for ( j=0; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
return frames;
}
} // stk namespace
#endif

View File

@@ -1,93 +0,0 @@
/***************************************************/
/*! \class WaveLoop
\brief STK waveform 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.
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.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
/***************************************************/
#ifndef STK_WAVELOOP_H
#define STK_WAVELOOP_H
#include "FileWvIn.h"
class WaveLoop : public FileWvIn
{
public:
//! Default constructor.
WaveLoop( unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 );
//! Class constructor that opens a specified file.
WaveLoop( std::string fileName, bool raw = false, bool doNormalize = true,
unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 );
//! Class destructor.
virtual ~WaveLoop();
//! 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 );
//! 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 );
//! 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 );
protected:
virtual void computeFrame( void );
virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
StkFrames firstFrame_;
StkFloat phaseOffset_;
};
#endif

View File

@@ -1,3 +1,16 @@
#ifndef STK_WHISTLE_H
#define STK_WHISTLE_H
#include "Instrmnt.h"
#include "Sphere.h"
#include "Vector3D.h"
#include "Noise.h"
#include "SineWave.h"
#include "OnePole.h"
#include "Envelope.h"
namespace stk {
/***************************************************/
/*! \class Whistle
\brief STK police/referee whistle instrument class.
@@ -12,21 +25,10 @@
- Blowing Frequency Modulation = 2
- Volume = 128
by Perry R. Cook 1996 - 2004.
by Perry R. Cook 1996 - 2009.
*/
/***************************************************/
#ifndef STK_WHISTLE_H
#define STK_WHISTLE_H
#include "Instrmnt.h"
#include "Sphere.h"
#include "Vector3D.h"
#include "Noise.h"
#include "SineWave.h"
#include "OnePole.h"
#include "Envelope.h"
class Whistle : public Instrmnt
{
public:
@@ -34,36 +36,37 @@ public:
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
Whistle();
Whistle( void );
//! Class destructor.
~Whistle();
~Whistle( 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 );
//! 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 );
Vector3D *tempVectorP_;
Vector3D tempVector_;
OnePole onepole_;
@@ -84,4 +87,5 @@ protected:
int subSample_, subSampCount_;
};
} // stk namespace
#endif

View File

@@ -1,3 +1,10 @@
#ifndef STK_WURLEY_H
#define STK_WURLEY_H
#include "FM.h"
namespace stk {
/***************************************************/
/*! \class Wurley
\brief STK Wurlitzer 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_WURLEY_H
#define STK_WURLEY_H
#include "FM.h"
class Wurley : public FM
{
public:
@@ -42,20 +44,48 @@ class Wurley : public FM
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
Wurley();
Wurley( void );
//! Class destructor.
~Wurley();
~Wurley( 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 Wurley :: 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

View File

@@ -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 <vector>
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

Some files were not shown because too many files have changed in this diff Show More