Version 4.3.0

This commit is contained in:
Gary Scavone
2009-03-24 23:02:15 -04:00
committed by Stephen Sinclair
parent 2cbce2d8bd
commit 27d9b79dc7
271 changed files with 22219 additions and 8834 deletions

301
save/Blotar.cpp Normal file
View File

@@ -0,0 +1,301 @@
/***************************************************/
/*! \class Blotar
\brief STK Blotar class.
This class is a port of Dan Trueman's MSP/PeRColate "blotar"
instrument, which itself was a modified version of the STK
waveguide flute model.
This port was made by Simon de Leon in the Music Technology area
at McGill University in 2006.
This is a digital waveguide model, making its use possibly subject
to patents held by Stanford University, Yamaha, and others. There
exist at least two patents, assigned to Stanford, bearing the
names of Karplus and/or Strong.
Control Change Numbers:
- Jet Delay = 2
- Noise Gain = 4
- Vibrato Frequency = 11
- Vibrato Gain = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
/***************************************************/
#include "Blotar.h"
#include "SKINI.msg"
Blotar :: Blotar()
{
this->initialize( 100.0 );
}
Blotar :: Blotar( StkFloat lowestFrequency )
{
this->initialize( lowestFrequency );
}
Blotar :: ~Blotar()
{
for ( int i=0; i<12; i++ )
delete soundfile_[i];
}
void Blotar :: initialize( StkFloat lowestFrequency )
{
length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
boreDelay_.setMaximumDelay( length_ );
boreDelay_.setDelay( 100.0 );
jetDelay_.setMaximumDelay( 2 * length_ );
jetDelay_.setDelay( 49.0 );
combDelay_.setMaximumDelay( length_ );
combDelay_.setDelay( length_ / 2 );
vibrato_.setFrequency( 5.0 );
dcBlock_.setBlockZero();
this->clear();
// Initialize control variables
pluckAmplitude_ = 0.8;
pluckPosition_ = 0.4;
lastFrequency_ = 220.0;
//endReflection_ = 0.5;
//jetReflection_ = 0.5;
endReflection_ = 0.99;
jetReflection_ = 0.06;
noiseGain_ = 0.15; // Breath pressure random component.
vibratoGain_ = 0.05; // Breath periodic vibrato component.
jetRatio_ = 0.32;
filterRatio_ = 1.0;
// Impulse responses
soundfile_[0] = new FileWvIn( (Stk::rawwavePath() + "mand1.raw").c_str(), true );
soundfile_[1] = new FileWvIn( (Stk::rawwavePath() + "mand2.raw").c_str(), true );
soundfile_[2] = new FileWvIn( (Stk::rawwavePath() + "mand3.raw").c_str(), true );
soundfile_[3] = new FileWvIn( (Stk::rawwavePath() + "mand4.raw").c_str(), true );
soundfile_[4] = new FileWvIn( (Stk::rawwavePath() + "mand5.raw").c_str(), true );
soundfile_[5] = new FileWvIn( (Stk::rawwavePath() + "mand6.raw").c_str(), true );
soundfile_[6] = new FileWvIn( (Stk::rawwavePath() + "mand7.raw").c_str(), true );
soundfile_[7] = new FileWvIn( (Stk::rawwavePath() + "mand8.raw").c_str(), true );
soundfile_[8] = new FileWvIn( (Stk::rawwavePath() + "mand9.raw").c_str(), true );
soundfile_[9] = new FileWvIn( (Stk::rawwavePath() + "mand10.raw").c_str(), true );
soundfile_[10] = new FileWvIn( (Stk::rawwavePath() + "mand11.raw").c_str(), true );
soundfile_[11] = new FileWvIn( (Stk::rawwavePath() + "mand12.raw").c_str(), true );
mic_ = 0;
waveDone_ = soundfile_[mic_]->isFinished();
this->setFrequency( lastFrequency_ );
fluteFilter_.setPole( 0.7 - ((StkFloat) 0.1 * 22050.0 / Stk::sampleRate() ) );
fluteFilter_.setGain( -1.0 );
}
void Blotar :: clear()
{
boreDelay_.clear();
jetDelay_.clear();
combDelay_.clear();
dcBlock_.clear();
fluteFilter_.clear();
}
void Blotar :: noteOn( StkFloat frequency, StkFloat amplitude )
{
if ( frequency != lastFrequency_ )
this->setFrequency( frequency );
this->pluck( amplitude );
#if defined(_STK_DEBUG_)
errorString_ << "Blotar::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Blotar :: noteOff( StkFloat amplitude )
{
}
void Blotar :: setFrequency( StkFloat frequency )
{
lastFrequency_ = frequency;
if ( frequency <= 0.0 ) {
errorString_ << "Blotar::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
lastFrequency_ = 220.0;
}
// We're overblowing here.
lastFrequency_ *= 0.66666;
// delay = length - approximate filter delay.
StkFloat delay = Stk::sampleRate() / lastFrequency_ - (StkFloat) 2.0;
if ( delay <= 0.0 ) delay = 0.3;
else if ( delay > length_ ) delay = length_;
boreDelay_.setDelay( delay );
jetDelay_.setDelay( delay * jetRatio_ );
}
void Blotar :: pluck( StkFloat amplitude )
{
// This function gets interesting, because pluck may be longer than
// string length, so we just reset the soundfile and add in the
// pluck in the tick method.
soundfile_[mic_]->reset();
waveDone_ = false;
pluckAmplitude_ = amplitude;
if ( amplitude < 0.0 ) {
errorString_ << "Blotar::pluck: amplitude parameter less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
pluckAmplitude_ = 0.0;
}
else if ( amplitude > 1.0 ) {
errorString_ << "Blotar::pluck: amplitude parameter greater than one ... setting to 1.0!";
handleError( StkError::WARNING );
pluckAmplitude_ = 1.0;
}
// Set the pick position, which puts zeroes at position * length.
combDelay_.setDelay( 0.5 * pluckPosition_ * length_ );
}
void Blotar :: setPluckPosition( StkFloat position )
{
pluckPosition_ = position;
}
void Blotar :: setBodySize( StkFloat size )
{
for ( int i=0; i<12; i++ )
soundfile_[i]->setRate( size );
}
void Blotar :: setBreathPressure( StkFloat bp )
{
maxPressure_ = bp;
}
void Blotar :: setJetDelay( StkFloat aRatio )
{
// Delay = length - approximate filter delay.
StkFloat temp = Stk::sampleRate() / lastFrequency_ - (StkFloat) 2.0;
jetRatio_ = aRatio;
jetDelay_.setDelay(temp * aRatio); // Scaled by ratio.
}
/*
void Blotar :: setJetDelay( StkFloat frequency )
{
StkFloat temp;
if ( frequency < WATCHIT )
frequency = WATCHIT;
StkFloat temp = (Stk::sampleRate() / frequency) - 2;
// Control jet length directly, not as function of bore length
jetDelay_.setDelay( temp );
jd_ = frequency;
}
*/
void Blotar :: setNoiseGain( StkFloat noiseGain )
{
noiseGain_ = noiseGain;
}
void Blotar :: setVibratoGain( StkFloat gain )
{
vibratoGain_ = gain;
}
void Blotar :: setJetReflection( StkFloat jetReflection )
{
jetReflection_ = jetReflection;
}
void Blotar :: setEndReflection( StkFloat endReflection )
{
endReflection_ = endReflection;
}
void Blotar :: setFilterRatio( StkFloat filterRatio )
{
filterRatio_ = filterRatio;
}
StkFloat Blotar :: computeSample()
{
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();
}
// Interpolate between one-pole filter of flute and one-zero filter of string
StkFloat flute = fluteFilter_.tick( boreDelay_.lastOut() + temp );
StkFloat string = lowpass_.tick( boreDelay_.lastOut() + temp );
temp = filterRatio_ * flute + ( 1 - filterRatio_ ) * string;
temp = dcBlock_.tick( temp );
// Random turbulence and vibrato
StkFloat breathPressure = maxPressure_ * ( noiseGain_ * noise_.tick() + vibratoGain_ * vibrato_.tick() );
StkFloat pressureDiff = breathPressure - ( jetReflection_ * temp );
pressureDiff = jetDelay_.tick( pressureDiff );
// Implement the "classic" mode of MSP blotar~ as if "mode" was default
//pressureDiff = jetTable_.tick( pressureDiff + ( endReflection_ * temp ) );
pressureDiff = jetTable_.tick( pressureDiff ) + ( endReflection_ * temp );
lastOutput_ = boreDelay_.tick( pressureDiff );
return lastOutput_;
}
void Blotar :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Blotar::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Blotar::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_JetDelay_) // 2
//if (number == __SK_BodySize_) // 2
//this->setBodySize( norm * 2.0 );
this->setJetDelay( (StkFloat) (0.08 + (0.48 * norm)) );
//else if (number == __SK_NoiseLevel_) // 4
else if (number == __SK_PickPosition_) // 4
this->setPluckPosition( norm );
//this->setNoiseGain( norm * 0.4 );
else if (number == __SK_ModFrequency_) // 11
vibrato_.setFrequency( norm * 12.0);
else if (number == __SK_ModWheel_) // 1
this->setVibratoGain( norm * 0.4 );
else if (number == __SK_AfterTouch_Cont_) // 128
this->setBreathPressure( norm );
else {
errorString_ << "Blotar::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Blotar::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

138
save/Blotar.h Normal file
View File

@@ -0,0 +1,138 @@
/***************************************************/
/*! \class Blotar
\brief STK Blotar class.
This class is a port of Dan Trueman's MSP/PeRColate "blotar"
instrument, which itself was a modified version of the STK
waveguide flute model.
This port was made by Simon de Leon in the Music Technology area
at McGill University in 2006.
This is a digital waveguide model, making its use possibly subject
to patents held by Stanford University, Yamaha, and others. There
exist at least two patents, assigned to Stanford, bearing the
names of Karplus and/or Strong.
Control Change Numbers:
- Jet Delay = 2
- Noise Gain = 4
- Vibrato Frequency = 11
- Vibrato Gain = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
/***************************************************/
#ifndef STK_BLOTAR_H
#define STK_BLOTAR_H
#define WATCHIT 0.00001
#include "Instrmnt.h"
#include "DelayL.h"
#include "DelayA.h"
#include "OneZero.h"
#include "OnePole.h"
#include "PoleZero.h"
#include "Noise.h"
#include "WaveLoop.h"
#include "JetTable.h"
#include "SineWave.h"
#include <cmath>
class Blotar : public Instrmnt
{
public:
//! Default class consructor, default lowest frequency is 100 Hz
Blotar();
//! Overloaded class constructor, taking the lowest desired playing frequency.
Blotar( StkFloat lowestFrequency );
//! Class destructor.
~Blotar();
//! Reset and clear all internal state.
void clear();
//! Start a note with the given frequency and amplitude.
virtual void noteOn(StkFloat frequency, StkFloat amplitude);
//! Stop a note with the given amplitude (speed of decay).
virtual void noteOff(StkFloat amplitude);
//! Set boreDelay_ line length parameters for a particular frequency
virtual void setFrequency(StkFloat frequency);
//! Set combDelay_ line length parameters to filter impulse response for particular position
void setPluckPosition(StkFloat position);
//! Set mandolin impulse response playback rate
void setBodySize(StkFloat size);
//! Set breath pressure
void setBreathPressure(StkFloat bp);
//! Set jetDelay_ line length parameter
void setJetDelay(StkFloat frequency);
//! Set gain of random breath pressure component
void setNoiseGain(StkFloat noiseGain);
//! Set read rate from sinusoidal table, which is used to scale random breath pressure component
void setVibatoFrequency( StkFloat frequency );
//! Set amplitude of sinusoidal table used to scale random breath pressure component
void setVibratoGain( StkFloat gain );
//! Set the reflection coefficient for the jet delay (-1.0 - 1.0)
void setJetReflection(StkFloat jetReflection);
//! Set the reflection coefficient for the air column delay (-1.0 - 1.0)
void setEndReflection(StkFloat endReflection);
//! Interpolates between one-pole filter of the flute and lowpass filter of plucked string
void setFilterRatio(StkFloat filterRatio);
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
protected:
void initialize( StkFloat lowestFrequency );
StkFloat computeSample( void );
void pluck( StkFloat amplitude );
DelayL boreDelay_;
DelayL jetDelay_;
DelayL combDelay_;
PoleZero dcBlock_;
OnePole fluteFilter_;
OneZero lowpass_;
Noise noise_;
JetTable jetTable_;
SineWave vibrato_;
FileWvIn *soundfile_[12];
// Performance variables
StkFloat pluckAmplitude_;
StkFloat pluckPosition_;
StkFloat maxPressure_; // breath pressure
StkFloat noiseGain_;
StkFloat vibratoGain_;
StkFloat jetReflection_;
StkFloat endReflection_;
StkFloat filterRatio_; // one-zero vs. one-pole filter ratio
StkFloat jetRatio_; // one-zero vs. one-pole filter ratio
int mic_; // directional position (NBody)
bool waveDone_;
long length_;
StkFloat lastFrequency_;
};
#endif

310
save/Ublotar.cpp Normal file
View File

@@ -0,0 +1,310 @@
/***************************************************/
/*! \class Ublotar
\brief STK Ublotar model class.
WaveGuide Flute ala Karjalainen,
Smith, Waryznyk, etc.
with polynomial Jet ala Cook
by Perry Cook, 1995-96
ported to MSP by Dan Trueman, 2000
and modified to become the nearly
righteous Ublotar. Extension of the Blotar to
include 6 strings and pre/post distortion outputs,
more plucking options; closer to the Sullivan electric
guitar model, while retaining some of the flute
potentials of the blotar~
Ublotar modifications ported to STK by
Simon de Leon, 2006.
This is a digital waveguide model, making its
use possibly subject to patents held by
Stanford University, Yamaha, and others.
There exist at least two patents, assigned to
Stanford, bearing the names of Karplus and/or
Strong.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
/***************************************************/
#include "Ublotar.h"
Ublotar :: Ublotar (StkFloat lowestFrequency)
{
// initialize variables
int i;
unsigned long length_ = (unsigned long) Stk::sampleRate()/((unsigned long) lowestFrequency + 1);
for (i=0; i<NUM_STRINGS; i++) {
// alloc and clear boreDelay
boreDelay_[i].setMaximumDelay( length_ );
boreDelay_[i].clear();
flute_filter_[i].setPole( 0.7 - (0.1 * 22050 / Stk::sampleRate()) );
flute_filter_[i].setGain( -1 );
last_output_ = 0;
lastLength_[i] = 0;
lastFreq_[i] = 0;
vibTime_ = 0;
vibRate_ = 0;
fr_[i] = 100 * (i + 1);
bp_ = 0;
ng_ = 0;
va_ = 0;
er_ = 0;
filterRatio_ = 1;
pluckAmp_[i] = 0;
pluckPos_[i] = 0;
killdc_[i].input = 0;
killdc_[i].output = 0;
killdc_[i].lastOutput = 0;
}
// alloc, clear, setDelay on jetDelay
jetDelay_.setMaximumDelay( 2*length_ );
jetDelay_.clear();
jetDelay_.setDelay( 49 );
vibLength_ = (int) length_ / 2;
vibTable_ = new StkFloat[vibLength_];
for (i=0; i<vibLength_; i++)
vibTable_[i] = sin( i*TWO_PI/vibLength_ );
// initialize all other variables
jd_ = 49;
jr_ = 0;
predistortion_gain_ = 1;
predistortion_outgain_ = 0;
postdistortion_outgain_ = 1;
limit_ = 10;
stringtopluck_ = 0; // 0-(NUM_STRINGS-1)
position_ = 5;
}
Ublotar :: ~Ublotar()
{
}
void Ublotar :: noteOn ( StkFloat frequency, StkFloat amplitude )
{
pluckAmp_[stringtopluck_] = amplitude;
pluckPos_[stringtopluck_] = position_;
squish_[stringtopluck_] = (int) position_; // bug in ublotar~, squish_ is an int!
this->setFrequency( frequency );
// pluckPos never < 0 in ublotar~, so always do Karplus with the DC block
int i, j;
int borelength;
StkFloat temp = 0;
for ( j=0; j<NUM_STRINGS; j++) {
if ( pluckAmp_[j] > 0 ) {
borelength = (int) boreDelay_[j].getDelay() - 1;
// load with noise and DC block
for ( i=0; i< borelength; i++) {
temp = makenoise_.tick() * pluckAmp_[j]; // input to DC block
// DC block
pluckblock_.output = temp - pluckblock_.input + (0.99 * pluckblock_.output);
pluckblock_.input = temp;
pluckblock_.lastOutput = pluckblock_.output;
temp = pluckblock_.lastOutput; // output from DC block, should go into bore j at location i
// ublotar~ adds noise manually into input pointer, just tick in the noise for bore length here
boreDelay_[j].tick( temp );
// ublotar~ does in-place LPF of delay line here, effect is negligible
}
// prevent this string from filling up with noise again after filling it with noise
pluckAmp_[j] = 0;
}
}
}
void Ublotar :: noteOff (StkFloat amplitude)
{
}
void Ublotar :: setFrequency (StkFloat *frequency)
{
StkFloat temp;
int i;
// Set string/bore frequency for each one
for ( i=0; i<NUM_STRINGS; i++) {
if (*(frequency + i) < 20)
in_[i] = 20;
lastLength_[i] = *(frequency + i);
lastFreq_[i] = *(frequency + i) * 0.66666;
if (lastFreq_[i] < WATCHIT)
lastFreq_[i] = WATCHIT;
temp = ( Stk::sampleRate() / lastFreq_[i] ) - 2;
boreDelay_[i].setDelay( temp );
}
}
void Ublotar :: setFrequency (StkFloat frequency)
{
StkFloat temp;
// Set string/bore frequency for stringtopluck_
if (frequency < 20)
in_[stringtopluck_] = 20;
lastLength_[stringtopluck_] = frequency;
lastFreq_[stringtopluck_] = frequency * 0.66666;
if (lastFreq_[stringtopluck_] < WATCHIT)
lastFreq_[stringtopluck_] = WATCHIT;
temp = ( Stk::sampleRate() / lastFreq_[stringtopluck_] ) - 2;
boreDelay_[stringtopluck_].setDelay( temp );
}
void Ublotar :: setPredistortionGain (StkFloat predistortionGain)
{
predistortion_outgain_ = predistortionGain;
}
void Ublotar :: setPostdistortionGain (StkFloat postdistortionGain)
{
postdistortion_outgain_ = postdistortionGain;
}
void Ublotar :: setBreathPressure (StkFloat bp)
{
bp_ = bp;
}
void Ublotar :: setJetDelay (StkFloat frequency)
{
StkFloat temp;
if (frequency < WATCHIT)
frequency = WATCHIT;
temp = ( Stk::sampleRate() / frequency ) - 2;
// Control jet length directly, not as a function of bore length
jetDelay_.setDelay( temp );
}
void Ublotar :: setStringToPluck (int stringtopluck)
{
if (stringtopluck >= NUM_STRINGS)
stringtopluck_ = NUM_STRINGS - 1;
else if (stringtopluck < 0)
stringtopluck_ = 0;
else
stringtopluck_ = stringtopluck;
}
StkFloat Ublotar :: vib()
{
long temp;
StkFloat temp_time, alpha, output;
vibTime_ += vibRate_;
while (vibTime_ >= (StkFloat) vibLength_)
vibTime_ -= (StkFloat) vibLength_;
while (vibTime_ < 0.)
vibTime_ += (StkFloat) vibLength_;
temp_time = vibTime_;
temp = (long) temp_time;
alpha = temp_time - (StkFloat) temp;
output = vibTable_[temp];
output = output + (alpha * (vibTable_[temp+1] - output));
return output;
}
StkFloat Ublotar :: computeSample ()
{
StkFloat temp = 0;
int i;
StkFloat randPressure = ng_ * makenoise_.tick();
randPressure += va_ * vib();
randPressure *= bp_;
StkFloat string_bore_output = 0;
StkFloat tempsave, sample;
for ( i=0; i<NUM_STRINGS; i++ ) {
sample = jr_ * last_output_;
temp = boreDelay_[i].tick( sample + er_ * last_output_ );
tempsave = temp;
temp = flute_filter_[i].tick( temp );
temp = filterRatio_ * temp + ( 1 - filterRatio_ ) * lowpass_[i].tick( tempsave );
// kill DC component
killdc_[i].output = temp - killdc_[i].input + ( 0.99 * killdc_[i].output );
killdc_[i].input = temp;
killdc_[i].lastOutput = killdc_[i].output;
temp = killdc_[i].lastOutput;
// limit the output
if (temp > limit_ || temp < -limit_) temp = 0;
last_output_ = temp; // return statement of blostring_tick
string_bore_output += last_output_;
}
StkFloat pressureDiff = bp_ + randPressure - string_bore_output * 1/NUM_STRINGS;
// feedback delay line
temp = jetDelay_.tick( pressureDiff );
// distortion
last_output_ = flutejet_.tick( predistortion_gain_ * temp );
StkFloat distortion_output = last_output_;
return predistortion_outgain_ * string_bore_output + postdistortion_outgain_ * distortion_output;
}
void Ublotar :: setJetReflection( StkFloat jetReflection ) // feedgain in ublotar~
{
jr_ = jetReflection;
}
void Ublotar :: setEndReflection( StkFloat endReflection ) // setsustain in ublotar~
{
// default mode for all presets set same er for all strings
er_ = endReflection;
}
void Ublotar :: setFilterRatio( StkFloat filterRatio ) // lowpasscross in ublotar~
{
// default mode for all presets set same filterRatio for all strings
filterRatio_ = filterRatio;
}
void Ublotar :: setDistortGain( StkFloat distortGain ) // distortgain in ublotar~
{
predistortion_gain_ = distortGain;
}
void Ublotar :: setLimit( StkFloat limit ) // setlimit in ublotar~
{
// set to 10 for most presets, sometimes much larger
limit_ = limit;
}
void Ublotar :: setNoiseGain( StkFloat noiseGain ) // noisegain in ublotar~
{
ng_ = noiseGain;
}
void Ublotar :: setVib( StkFloat vibFreq, StkFloat vibAmount ) // vib in ublotar~
{
va_ = vibAmount;
vibRate_ = vibLength_ / Stk::sampleRate() * vibFreq;
}

158
save/Ublotar.h Normal file
View File

@@ -0,0 +1,158 @@
/***************************************************/
/*! \class Ublotar
\brief STK Ublotar model class.
WaveGuide Flute ala Karjalainen,
Smith, Waryznyk, etc.
with polynomial Jet ala Cook
by Perry Cook, 1995-96
ported to MSP by Dan Trueman, 2000
and modified to become the nearly
righteous Ublotar. Extension of the Blotar to
include 6 strings and pre/post distortion outputs,
more plucking options; closer to the Sullivan electric
guitar model, while retaining some of the flute
potentials of the blotar~
Ublotar modifications ported to STK by
Simon de Leon, 2006.
This is a digital waveguide model, making its
use possibly subject to patents held by
Stanford University, Yamaha, and others.
There exist at least two patents, assigned to
Stanford, bearing the names of Karplus and/or
Strong.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
/***************************************************/
#ifndef STK_PLUCKED_H
#define STK_PLUCKED_H
#define WATCHIT 0.00001
#define NUM_STRINGS 6
#define MAX_INPUTS 10
#define VIBLENGTH 1024
#include "Instrmnt.h"
#include "DelayL.h"
#include "DelayA.h"
#include "OneZero.h"
#include "OnePole.h"
#include "Noise.h"
#include "WaveLoop.h"
#include "JetTable.h"
#include <cmath>
#include <vector>
#include "Flute.h"
#include "Blotar.h"
#include "TwoPole.h"
class Ublotar : public Instrmnt
{
public:
//! Default class destructor.
~Ublotar ();
//! Class constructor, taking the lowest desired playing frequency.
Ublotar (StkFloat lowestFrequency);
//! Start a note with the given frequency and amplitude
virtual void noteOn (StkFloat frequency, StkFloat amplitude);
//! Stop a note with the given amplitude (speed of decay).
virtual void noteOff (StkFloat amplitude);
//! Set boreDelay_ line length parameter of stringtopluck_ for a particular frequency
virtual void setFrequency (StkFloat frequency);
//! Set boreDelay_ line length parameters of all strings for certain frequencies
void setFrequency (StkFloat *frequency);
//! Set pre-distortion gain
void setPredistortionGain (StkFloat predistortionGain);
//! Set post-distortion gain
void setPostdistortionGain (StkFloat postdistortionGain);
//! Set breath pressure
void setBreathPressure (StkFloat bp);
//! Set jetDelay_ line length parameter
void setJetDelay (StkFloat frequency);
//! Set the reflection coefficient for the jet delay (-1.0 - 1.0)
void setJetReflection( StkFloat jetReflection ); // feedgain in ublotar~
//! Set the reflection coefficient for the air column delay (-1.0 - 1.0)
void setEndReflection( StkFloat endReflection ); // setsustain in ublotar~
//! Interpolates between one-pole filter of the flute and lowpass filter of plucked string
void setFilterRatio( StkFloat filterRatio ); // lowpasscross in ublotar~
//! Set distortion gain
void setDistortGain( StkFloat distortGain ); // distortgain in ublotar~
//! Set hard limiter value to prevent infinitely growing amplitudes
void setLimit( StkFloat limit ); // setlimit in ublotar~
//! Set gain of random breath pressure component
void setNoiseGain( StkFloat noiseGain ); // noisegain in ublotar~
//! Set vibrato parameters, which are used to scale random breath pressure component
void setVib( StkFloat vibFreq, StkFloat vibAmount ); // vib in ublotar~
//! Set string that frequency and amplitude parameters in subsequent call to noteOn will alter
void setStringToPluck (int stringtopluck);
protected:
StkFloat computeSample ( void );
StkFloat vib ( void );
// Global string parameters
StkFloat in_[MAX_INPUTS];
StkFloat jd_;
StkFloat jr_;
StkFloat predistortion_gain_;
StkFloat predistortion_outgain_;
StkFloat postdistortion_outgain_;
StkFloat limit_;
StkFloat *vibTable_;
DelayL jetDelay_;
StkFloat bp_;
StkFloat va_;
StkFloat ng_;
// String-Bore variables
StkFloat fr_[NUM_STRINGS];
StkFloat er_;
StkFloat pluckAmp_[NUM_STRINGS];
StkFloat pluckPos_[NUM_STRINGS];
int squish_[NUM_STRINGS]; // number of times to LPF the blostring
StkFloat filterRatio_;
StkFloat resetDelay_[NUM_STRINGS];
OnePole flute_filter_[NUM_STRINGS];
OneZero lowpass_[NUM_STRINGS];
StkFloat vibTime_, vibRate_;
DelayL boreDelay_[NUM_STRINGS];
StkFloat last_output_;
StkFloat lastFreq_[NUM_STRINGS], lastLength_[NUM_STRINGS];
// Auxiliary variables
StkFloat length_;
int vibLength_;
StkFloat position_;
int stringtopluck_;
struct {
StkFloat output, input, lastOutput;
} killdc_[NUM_STRINGS], pluckblock_;
Noise makenoise_;
JetTable flutejet_;
};
#endif