mirror of
https://github.com/thestk/stk
synced 2026-01-19 07:31:52 +00:00
Version 4.3.0
This commit is contained in:
committed by
Stephen Sinclair
parent
2cbce2d8bd
commit
27d9b79dc7
301
save/Blotar.cpp
Normal file
301
save/Blotar.cpp
Normal 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
138
save/Blotar.h
Normal 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
310
save/Ublotar.cpp
Normal 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
158
save/Ublotar.h
Normal 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
|
||||
Reference in New Issue
Block a user