Version 4.2.0

This commit is contained in:
Gary Scavone
2009-03-24 23:02:14 -04:00
committed by Stephen Sinclair
parent cf06b7598b
commit a6381b9d38
281 changed files with 17152 additions and 12000 deletions

View File

@@ -11,22 +11,21 @@
envelope value reaches 0.0 in the
ADSR::RELEASE state.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "ADSR.h"
#include <stdio.h>
ADSR :: ADSR() : Envelope()
{
target = (MY_FLOAT) 0.0;
value = (MY_FLOAT) 0.0;
attackRate = (MY_FLOAT) 0.001;
decayRate = (MY_FLOAT) 0.001;
sustainLevel = (MY_FLOAT) 0.5;
releaseRate = (MY_FLOAT) 0.01;
state = ATTACK;
target_ = 0.0;
value_ = 0.0;
attackRate_ = 0.001;
decayRate_ = 0.001;
sustainLevel_ = 0.5;
releaseRate_ = 0.01;
state_ = ATTACK;
}
ADSR :: ~ADSR()
@@ -35,82 +34,89 @@ ADSR :: ~ADSR()
void ADSR :: keyOn()
{
target = (MY_FLOAT) 1.0;
rate = attackRate;
state = ATTACK;
target_ = 1.0;
rate_ = attackRate_;
state_ = ATTACK;
}
void ADSR :: keyOff()
{
target = (MY_FLOAT) 0.0;
rate = releaseRate;
state = RELEASE;
target_ = 0.0;
rate_ = releaseRate_;
state_ = RELEASE;
}
void ADSR :: setAttackRate(MY_FLOAT aRate)
void ADSR :: setAttackRate(StkFloat rate)
{
if (aRate < 0.0) {
printf("ADSR: negative rates not allowed ... correcting!\n");
attackRate = -aRate;
if (rate < 0.0) {
errorString_ << "ADSR::setAttackRate: negative rates not allowed ... correcting!";
handleError( StkError::WARNING );
attackRate_ = -rate;
}
else attackRate = aRate;
else attackRate_ = rate;
}
void ADSR :: setDecayRate(MY_FLOAT aRate)
void ADSR :: setDecayRate(StkFloat rate)
{
if (aRate < 0.0) {
printf("ADSR: negative rates not allowed ... correcting!\n");
decayRate = -aRate;
if (rate < 0.0) {
errorString_ << "ADSR::setDecayRate: negative rates not allowed ... correcting!";
handleError( StkError::WARNING );
decayRate_ = -rate;
}
else decayRate = aRate;
else decayRate_ = rate;
}
void ADSR :: setSustainLevel(MY_FLOAT aLevel)
void ADSR :: setSustainLevel(StkFloat level)
{
if (aLevel < 0.0 ) {
printf("ADSR: sustain level out of range ... correcting!\n");
sustainLevel = (MY_FLOAT) 0.0;
if (level < 0.0 ) {
errorString_ << "ADSR::setSustainLevel: level out of range ... correcting!";
handleError( StkError::WARNING );
sustainLevel_ = 0.0;
}
else sustainLevel = aLevel;
else sustainLevel_ = level;
}
void ADSR :: setReleaseRate(MY_FLOAT aRate)
void ADSR :: setReleaseRate(StkFloat rate)
{
if (aRate < 0.0) {
printf("ADSR: negative rates not allowed ... correcting!\n");
releaseRate = -aRate;
if (rate < 0.0) {
errorString_ << "ADSR::setReleaseRate: negative rates not allowed ... correcting!";
handleError( StkError::WARNING );
releaseRate_ = -rate;
}
else releaseRate = aRate;
else releaseRate_ = rate;
}
void ADSR :: setAttackTime(MY_FLOAT aTime)
void ADSR :: setAttackTime(StkFloat time)
{
if (aTime < 0.0) {
printf("ADSR: negative rates not allowed ... correcting!\n");
attackRate = 1.0 / ( -aTime * Stk::sampleRate() );
if (time < 0.0) {
errorString_ << "ADSR::setAttackTime: negative times not allowed ... correcting!";
handleError( StkError::WARNING );
attackRate_ = 1.0 / ( -time * Stk::sampleRate() );
}
else attackRate = 1.0 / ( aTime * Stk::sampleRate() );
else attackRate_ = 1.0 / ( time * Stk::sampleRate() );
}
void ADSR :: setDecayTime(MY_FLOAT aTime)
void ADSR :: setDecayTime(StkFloat time)
{
if (aTime < 0.0) {
printf("ADSR: negative times not allowed ... correcting!\n");
decayRate = 1.0 / ( -aTime * Stk::sampleRate() );
if (time < 0.0) {
errorString_ << "ADSR::setDecayTime: negative times not allowed ... correcting!";
handleError( StkError::WARNING );
decayRate_ = 1.0 / ( -time * Stk::sampleRate() );
}
else decayRate = 1.0 / ( aTime * Stk::sampleRate() );
else decayRate_ = 1.0 / ( time * Stk::sampleRate() );
}
void ADSR :: setReleaseTime(MY_FLOAT aTime)
void ADSR :: setReleaseTime(StkFloat time)
{
if (aTime < 0.0) {
printf("ADSR: negative times not allowed ... correcting!\n");
releaseRate = sustainLevel / ( -aTime * Stk::sampleRate() );
if (time < 0.0) {
errorString_ << "ADSR::setReleaseTime: negative times not allowed ... correcting!";
handleError( StkError::WARNING );
releaseRate_ = sustainLevel_ / ( -time * Stk::sampleRate() );
}
else releaseRate = sustainLevel / ( aTime * Stk::sampleRate() );
else releaseRate_ = sustainLevel_ / ( time * Stk::sampleRate() );
}
void ADSR :: setAllTimes(MY_FLOAT aTime, MY_FLOAT dTime, MY_FLOAT sLevel, MY_FLOAT rTime)
void ADSR :: setAllTimes(StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime)
{
this->setAttackTime(aTime);
this->setDecayTime(dTime);
@@ -118,73 +124,76 @@ void ADSR :: setAllTimes(MY_FLOAT aTime, MY_FLOAT dTime, MY_FLOAT sLevel, MY_FLO
this->setReleaseTime(rTime);
}
void ADSR :: setTarget(MY_FLOAT aTarget)
void ADSR :: setTarget(StkFloat target)
{
target = aTarget;
if (value < target) {
state = ATTACK;
this->setSustainLevel(target);
rate = attackRate;
target_ = target;
if (value_ < target_) {
state_ = ATTACK;
this->setSustainLevel(target_);
rate_ = attackRate_;
}
if (value > target) {
this->setSustainLevel(target);
state = DECAY;
rate = decayRate;
if (value_ > target_) {
this->setSustainLevel(target_);
state_ = DECAY;
rate_ = decayRate_;
}
}
void ADSR :: setValue(MY_FLOAT aValue)
void ADSR :: setValue(StkFloat value)
{
state = SUSTAIN;
target = aValue;
value = aValue;
this->setSustainLevel(aValue);
rate = (MY_FLOAT) 0.0;
state_ = SUSTAIN;
target_ = value;
value_ = value;
this->setSustainLevel(value);
rate_ = (StkFloat) 0.0;
}
int ADSR :: getState(void) const
{
return state;
return state_;
}
MY_FLOAT ADSR :: tick()
StkFloat ADSR :: tick()
{
switch (state) {
switch (state_) {
case ATTACK:
value += rate;
if (value >= target) {
value = target;
rate = decayRate;
target = sustainLevel;
state = DECAY;
value_ += rate_;
if (value_ >= target_) {
value_ = target_;
rate_ = decayRate_;
target_ = sustainLevel_;
state_ = DECAY;
}
break;
case DECAY:
value -= decayRate;
if (value <= sustainLevel) {
value = sustainLevel;
rate = (MY_FLOAT) 0.0;
state = SUSTAIN;
value_ -= decayRate_;
if (value_ <= sustainLevel_) {
value_ = sustainLevel_;
rate_ = (StkFloat) 0.0;
state_ = SUSTAIN;
}
break;
case RELEASE:
value -= releaseRate;
if (value <= 0.0) {
value = (MY_FLOAT) 0.0;
state = DONE;
value_ -= releaseRate_;
if (value_ <= 0.0) {
value_ = (StkFloat) 0.0;
state_ = DONE;
}
}
return value;
lastOutput_ = value_;
return value_;
}
MY_FLOAT *ADSR :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *ADSR :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick();
return vector;
return Generator::tick( vector, vectorSize );
}
StkFrames& ADSR :: tick( StkFrames& frames, unsigned int channel )
{
return Generator::tick( frames, channel );
}

115
src/Asymp.cpp Normal file
View File

@@ -0,0 +1,115 @@
/***************************************************/
/*! \class Asymp
\brief STK asymptotic curve envelope class
This class implements a simple envelope generator
which asymptotically approaches a target value.
The algorithm used is of the form:
x[n] = a x[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
constant (default value = 0.3) and target value.
Theoretically, this recursion never reaches its
target, though the calculations in this class are
stopped when the current value gets within a small
threshold value of the target (at which time the
current value is set to the target). It responds
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 - 2004.
*/
/***************************************************/
#include "Asymp.h"
#include <math.h>
Asymp :: Asymp(void) : Envelope()
{
factor_ = exp( -1.0 / ( 0.3 * Stk::sampleRate() ) );
constant_ = 0.0;
}
Asymp :: ~Asymp(void)
{
}
void Asymp :: keyOn(void)
{
Envelope::keyOn();
constant_ = ( 1.0 - factor_ ) * target_;
}
void Asymp :: keyOff(void)
{
Envelope::keyOff();
constant_ = ( 1.0 - factor_ ) * target_;
}
void Asymp :: setTau(StkFloat tau)
{
if (tau <= 0.0) {
errorString_ << "Asymp::setTau: negative or zero tau not allowed ... ignoring!";
handleError( StkError::WARNING );
return;
}
factor_ = exp( -1.0 / ( tau * Stk::sampleRate() ) );
constant_ = ( 1.0 - factor_ ) * target_;
}
void Asymp :: setTime(StkFloat time)
{
if (time <= 0.0) {
errorString_ << "Asymp::setTime: negative or zero times not allowed ... ignoring!";
handleError( StkError::WARNING );
return;
}
StkFloat tau = -time / log( TARGET_THRESHOLD );
factor_ = exp( -1.0 / ( tau * Stk::sampleRate() ) );
constant_ = ( 1.0 - factor_ ) * target_;
}
void Asymp :: setTarget(StkFloat target)
{
Envelope::setTarget( target );
constant_ = ( 1.0 - factor_ ) * target_;
}
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;
}
}
}
lastOutput_ = value_;
return value_;
}
StkFloat *Asymp :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Generator::tick( vector, vectorSize );
}
StkFrames& Asymp :: tick( StkFrames& frames, unsigned int channel )
{
return Generator::tick( frames, channel );
}

View File

@@ -24,7 +24,7 @@
- Glass Harmonica = 2
- Tibetan Bowl = 3
by Georg Essl, 1999 - 2002.
by Georg Essl, 1999 - 2004.
Modified for Stk 4.0 by Gary Scavone.
*/
/***************************************************/
@@ -36,45 +36,35 @@
BandedWG :: BandedWG()
{
doPluck = true;
doPluck_ = true;
delay = new DelayL[MAX_BANDED_MODES];
bandpass = new BiQuad[MAX_BANDED_MODES];
bowTable_.setSlope( 3.0 );
adsr_.setAllTimes( 0.02, 0.005, 0.9, 0.01);
frequency_ = 220.0;
this->setPreset(0);
bowPosition_ = 0;
baseGain_ = (StkFloat) 0.999;
bowTabl = new BowTabl;
bowTabl->setSlope( 3.0 );
integrationConstant_ = 0.0;
trackVelocity_ = false;
adsr = new ADSR;
adsr->setAllTimes( 0.02, 0.005, 0.9, 0.01);
bowVelocity_ = 0.0;
bowTarget_ = 0.0;
freakency = 220.0;
setPreset(0);
bowPosition = 0;
baseGain = (MY_FLOAT) 0.999;
integrationConstant = 0.0;
trackVelocity = false;
bowVelocity = 0.0;
bowTarget = 0.0;
strikeAmp = 0.0;
strikeAmp_ = 0.0;
}
BandedWG :: ~BandedWG()
{
delete bowTabl;
delete adsr;
delete [] bandpass;
delete [] delay;
}
void BandedWG :: clear()
{
for (int i=0; i<nModes; i++) {
delay[i].clear();
bandpass[i].clear();
for (int i=0; i<nModes_; i++) {
delay_[i].clear();
bandpass_[i].clear();
}
}
@@ -84,297 +74,315 @@ void BandedWG :: setPreset(int preset)
switch (preset){
case 1: // Tuned Bar
presetModes = 4;
modes[0] = (MY_FLOAT) 1.0;
modes[1] = (MY_FLOAT) 4.0198391420;
modes[2] = (MY_FLOAT) 10.7184986595;
modes[3] = (MY_FLOAT) 18.0697050938;
presetModes_ = 4;
modes_[0] = (StkFloat) 1.0;
modes_[1] = (StkFloat) 4.0198391420;
modes_[2] = (StkFloat) 10.7184986595;
modes_[3] = (StkFloat) 18.0697050938;
for (i=0; i<presetModes; i++) {
basegains[i] = (MY_FLOAT) pow(0.999,(double) i+1);
excitation[i] = 1.0;
for (i=0; i<presetModes_; i++) {
basegains_[i] = (StkFloat) pow(0.999,(double) i+1);
excitation_[i] = 1.0;
}
break;
case 2: // Glass Harmonica
presetModes = 5;
modes[0] = (MY_FLOAT) 1.0;
modes[1] = (MY_FLOAT) 2.32;
modes[2] = (MY_FLOAT) 4.25;
modes[3] = (MY_FLOAT) 6.63;
modes[4] = (MY_FLOAT) 9.38;
// modes[5] = (MY_FLOAT) 12.22;
presetModes_ = 5;
modes_[0] = (StkFloat) 1.0;
modes_[1] = (StkFloat) 2.32;
modes_[2] = (StkFloat) 4.25;
modes_[3] = (StkFloat) 6.63;
modes_[4] = (StkFloat) 9.38;
// modes_[5] = (StkFloat) 12.22;
for (i=0; i<presetModes; i++) {
basegains[i] = (MY_FLOAT) pow(0.999,(double) i+1);
excitation[i] = 1.0;
for (i=0; i<presetModes_; i++) {
basegains_[i] = (StkFloat) pow(0.999,(double) i+1);
excitation_[i] = 1.0;
}
/*
baseGain = (MY_FLOAT) 0.99999;
for (i=0; i<presetModes; i++)
gains[i]= (MY_FLOAT) pow(baseGain, delay[i].getDelay()+i);
baseGain_ = (StkFloat) 0.99999;
for (i=0; i<presetModes_; i++)
gains_[i]= (StkFloat) pow(baseGain_, delay_[i].getDelay()+i);
*/
break;
case 3: // Tibetan Prayer Bowl (ICMC'02)
presetModes = 12;
modes[0]=0.996108344;
basegains[0]=0.999925960128219;
excitation[0]=11.900357/10.0;
modes[1]=1.0038916562;
basegains[1]=0.999925960128219;
excitation[1]=11.900357/10.;
modes[2]=2.979178;
basegains[2]=0.999982774366897;
excitation[2]=10.914886/10.;
modes[3]=2.99329767;
basegains[3]=0.999982774366897;
excitation[3]=10.914886/10.;
modes[4]=5.704452;
basegains[4]=1.0; //0.999999999999999999987356406352;
excitation[4]=42.995041/10.;
modes[5]=5.704452;
basegains[5]=1.0; //0.999999999999999999987356406352;
excitation[5]=42.995041/10.;
modes[6]=8.9982;
basegains[6]=1.0; //0.999999999999999999996995497558225;
excitation[6]=40.063034/10.;
modes[7]=9.01549726;
basegains[7]=1.0; //0.999999999999999999996995497558225;
excitation[7]=40.063034/10.;
modes[8]=12.83303;
basegains[8]=0.999965497558225;
excitation[8]=7.063034/10.;
modes[9]=12.807382;
basegains[9]=0.999965497558225;
excitation[9]=7.063034/10.;
modes[10]=17.2808219;
basegains[10]=0.9999999999999999999965497558225;
excitation[10]=57.063034/10.;
modes[11]=21.97602739726;
basegains[11]=0.999999999999999965497558225;
excitation[11]=57.063034/10.;
presetModes_ = 12;
modes_[0]=0.996108344;
basegains_[0]=0.999925960128219;
excitation_[0]=11.900357/10.0;
modes_[1]=1.0038916562;
basegains_[1]=0.999925960128219;
excitation_[1]=11.900357/10.;
modes_[2]=2.979178;
basegains_[2]=0.999982774366897;
excitation_[2]=10.914886/10.;
modes_[3]=2.99329767;
basegains_[3]=0.999982774366897;
excitation_[3]=10.914886/10.;
modes_[4]=5.704452;
basegains_[4]=1.0; //0.999999999999999999987356406352;
excitation_[4]=42.995041/10.;
modes_[5]=5.704452;
basegains_[5]=1.0; //0.999999999999999999987356406352;
excitation_[5]=42.995041/10.;
modes_[6]=8.9982;
basegains_[6]=1.0; //0.999999999999999999996995497558225;
excitation_[6]=40.063034/10.;
modes_[7]=9.01549726;
basegains_[7]=1.0; //0.999999999999999999996995497558225;
excitation_[7]=40.063034/10.;
modes_[8]=12.83303;
basegains_[8]=0.999965497558225;
excitation_[8]=7.063034/10.;
modes_[9]=12.807382;
basegains_[9]=0.999965497558225;
excitation_[9]=7.063034/10.;
modes_[10]=17.2808219;
basegains_[10]=0.9999999999999999999965497558225;
excitation_[10]=57.063034/10.;
modes_[11]=21.97602739726;
basegains_[11]=0.999999999999999965497558225;
excitation_[11]=57.063034/10.;
break;
default: // Uniform Bar
presetModes = 4;
modes[0] = (MY_FLOAT) 1.0;
modes[1] = (MY_FLOAT) 2.756;
modes[2] = (MY_FLOAT) 5.404;
modes[3] = (MY_FLOAT) 8.933;
presetModes_ = 4;
modes_[0] = (StkFloat) 1.0;
modes_[1] = (StkFloat) 2.756;
modes_[2] = (StkFloat) 5.404;
modes_[3] = (StkFloat) 8.933;
for (i=0; i<presetModes; i++) {
basegains[i] = (MY_FLOAT) pow(0.9,(double) i+1);
excitation[i] = 1.0;
for (i=0; i<presetModes_; i++) {
basegains_[i] = (StkFloat) pow(0.9,(double) i+1);
excitation_[i] = 1.0;
}
break;
}
nModes = presetModes;
setFrequency( freakency );
nModes_ = presetModes_;
setFrequency( frequency_ );
}
void BandedWG :: setFrequency(MY_FLOAT frequency)
void BandedWG :: setFrequency(StkFloat frequency)
{
freakency = frequency;
frequency_ = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "BandedWG: setFrequency parameter is less than or equal to zero!" << std::endl;
freakency = 220.0;
errorString_ << "BandedWG::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
frequency_ = 220.0;
}
if (freakency > 1568.0) freakency = 1568.0;
if (frequency_ > 1568.0) frequency_ = 1568.0;
MY_FLOAT radius;
MY_FLOAT base = Stk::sampleRate() / freakency;
MY_FLOAT length;
for (int i=0; i<presetModes; i++) {
StkFloat radius;
StkFloat base = Stk::sampleRate() / frequency_;
StkFloat length;
for (int i=0; i<presetModes_; i++) {
// Calculate the delay line lengths for each mode.
length = (int)(base / modes[i]);
length = (int)(base / modes_[i]);
if ( length > 2.0) {
delay[i].setDelay( length );
gains[i]=basegains[i];
// gains[i]=(MY_FLOAT) pow(basegains[i], 1/((MY_FLOAT)delay[i].getDelay()));
// std::cerr << gains[i];
delay_[i].setDelay( length );
gains_[i]=basegains_[i];
// gains_[i]=(StkFloat) pow(basegains_[i], 1/((StkFloat)delay_[i].getDelay()));
// std::cerr << gains_[i];
}
else {
nModes = i;
nModes_ = i;
break;
}
// std::cerr << std::endl;
// Set the bandpass filter resonances
radius = 1.0 - PI * 32 / Stk::sampleRate(); //freakency * modes[i] / Stk::sampleRate()/32;
radius = 1.0 - PI * 32 / Stk::sampleRate(); //frequency_ * modes_[i] / Stk::sampleRate()/32;
if ( radius < 0.0 ) radius = 0.0;
bandpass[i].setResonance(freakency * modes[i], radius, true);
bandpass_[i].setResonance(frequency_ * modes_[i], radius, true);
delay[i].clear();
bandpass[i].clear();
delay_[i].clear();
bandpass_[i].clear();
}
//int olen = (int)(delay[0].getDelay());
//strikePosition = (int)(strikePosition*(length/modes[0])/olen);
//int olen = (int)(delay_[0].getDelay());
//strikePosition_ = (int)(strikePosition_*(length/modes_[0])/olen);
}
void BandedWG :: setStrikePosition(MY_FLOAT position)
void BandedWG :: setStrikePosition(StkFloat position)
{
strikePosition = (int)(delay[0].getDelay() * position / 2.0);
strikePosition_ = (int)(delay_[0].getDelay() * position / 2.0);
}
void BandedWG :: startBowing(MY_FLOAT amplitude, MY_FLOAT rate)
void BandedWG :: startBowing(StkFloat amplitude, StkFloat rate)
{
adsr->setRate(rate);
adsr->keyOn();
maxVelocity = 0.03 + (0.1 * amplitude);
adsr_.setRate(rate);
adsr_.keyOn();
maxVelocity_ = 0.03 + (0.1 * amplitude);
}
void BandedWG :: stopBowing(MY_FLOAT rate)
void BandedWG :: stopBowing(StkFloat rate)
{
adsr->setRate(rate);
adsr->keyOff();
adsr_.setRate(rate);
adsr_.keyOff();
}
void BandedWG :: pluck(MY_FLOAT amplitude)
void BandedWG :: pluck(StkFloat amplitude)
{
int j;
MY_FLOAT min_len = delay[nModes-1].getDelay();
for (int i=0; i<nModes; i++)
for(j=0; j<(int)(delay[i].getDelay()/min_len); j++)
delay[i].tick( excitation[i]*amplitude / nModes /*/ (delay[i].getDelay()/min_len)*/);
StkFloat min_len = delay_[nModes_-1].getDelay();
for (int i=0; i<nModes_; i++)
for(j=0; j<(int)(delay_[i].getDelay()/min_len); j++)
delay_[i].tick( excitation_[i]*amplitude / nModes_ );
/* strikeAmp += amplitude;*/
// strikeAmp_ += amplitude;
}
void BandedWG :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void BandedWG :: noteOn(StkFloat frequency, StkFloat amplitude)
{
this->setFrequency(frequency);
if ( doPluck )
if ( doPluck_ )
this->pluck(amplitude);
else
this->startBowing(amplitude, amplitude * 0.001);
#if defined(_STK_DEBUG_)
std::cerr << "BandedWG: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "BandedWG::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void BandedWG :: noteOff(MY_FLOAT amplitude)
void BandedWG :: noteOff(StkFloat amplitude)
{
if ( !doPluck )
if ( !doPluck_ )
this->stopBowing((1.0 - amplitude) * 0.005);
#if defined(_STK_DEBUG_)
std::cerr << "BandedWG: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "BandedWG::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT BandedWG :: tick()
StkFloat BandedWG :: tick()
{
int k;
MY_FLOAT input = 0.0;
if ( doPluck ) {
StkFloat input = 0.0;
if ( doPluck_ ) {
input = 0.0;
// input = strikeAmp/nModes;
// strikeAmp = 0.0;
// input = strikeAmp_/nModes_;
// strikeAmp_ = 0.0;
}
else {
if (integrationConstant == 0.0)
velocityInput = 0.0;
if (integrationConstant_ == 0.0)
velocityInput_ = 0.0;
else
velocityInput = integrationConstant * velocityInput;
velocityInput_ = integrationConstant_ * velocityInput_;
for (k=0; k<nModes; k++)
velocityInput += baseGain * delay[k].lastOut();
for (k=0; k<nModes_; k++)
velocityInput_ += baseGain_ * delay_[k].lastOut();
if ( trackVelocity ) {
bowVelocity *= 0.9995;
bowVelocity += bowTarget;
bowTarget *= 0.995;
if ( trackVelocity_ ) {
bowVelocity_ *= 0.9995;
bowVelocity_ += bowTarget_;
bowTarget_ *= 0.995;
}
else
bowVelocity = adsr->tick() * maxVelocity;
bowVelocity_ = adsr_.tick() * maxVelocity_;
input = bowVelocity - velocityInput;
input = input * bowTabl->tick(input);
input = input/(MY_FLOAT)nModes;
input = bowVelocity_ - velocityInput_;
input = input * bowTable_.tick(input);
input = input/(StkFloat)nModes_;
}
MY_FLOAT data = 0.0;
for (k=0; k<nModes; k++) {
bandpass[k].tick(input + gains[k] * delay[k].lastOut());
delay[k].tick(bandpass[k].lastOut());
data += bandpass[k].lastOut();
StkFloat data = 0.0;
for (k=0; k<nModes_; k++) {
bandpass_[k].tick(input + gains_[k] * delay_[k].lastOut());
delay_[k].tick(bandpass_[k].lastOut());
data += bandpass_[k].lastOut();
}
//lastOutput = data * nModes;
lastOutput = data * 4;
return lastOutput;
//lastOutput = data * nModes_;
lastOutput_ = data * 4;
return lastOutput_;
}
void BandedWG :: controlChange(int number, MY_FLOAT value)
StkFloat *BandedWG :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& BandedWG :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void BandedWG :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "BandedWG: Control value less than zero!" << std::endl;
errorString_ << "BandedWG::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "BandedWG: Control value greater than 128.0!" << std::endl;
errorString_ << "BandedWG::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_BowPressure_) { // 2
if ( norm == 0.0 )
doPluck = true;
doPluck_ = true;
else {
doPluck = false;
bowTabl->setSlope( 10.0 - (9.0 * norm));
doPluck_ = false;
bowTable_.setSlope( 10.0 - (9.0 * norm));
}
}
else if (number == 4) { // 4
if ( !trackVelocity ) trackVelocity = true;
bowTarget += 0.005 * (norm - bowPosition);
bowPosition = norm;
//adsr->setTarget(bowPosition);
if ( !trackVelocity_ ) trackVelocity_ = true;
bowTarget_ += 0.005 * (norm - bowPosition_);
bowPosition_ = norm;
//adsr_.setTarget(bowPosition_);
}
else if (number == 8) // 8
this->setStrikePosition( norm );
else if (number == __SK_AfterTouch_Cont_) { // 128
//bowTarget += 0.02 * (norm - bowPosition);
//bowPosition = norm;
if ( trackVelocity ) trackVelocity = false;
maxVelocity = 0.13 * norm;
adsr->setTarget(norm);
//bowTarget_ += 0.02 * (norm - bowPosition_);
//bowPosition_ = norm;
if ( trackVelocity_ ) trackVelocity_ = false;
maxVelocity_ = 0.13 * norm;
adsr_.setTarget(norm);
}
else if (number == __SK_ModWheel_) { // 1
// baseGain = 0.9989999999 + (0.001 * norm );
baseGain = 0.8999999999999999 + (0.1 * norm);
// baseGain_ = 0.9989999999 + (0.001 * norm );
baseGain_ = 0.8999999999999999 + (0.1 * norm);
// std::cerr << "Yuck!" << std::endl;
for (int i=0; i<nModes; i++)
gains[i]=(MY_FLOAT) basegains[i]*baseGain;
// gains[i]=(MY_FLOAT) pow(baseGain, (int)((MY_FLOAT)delay[i].getDelay()+i));
for (int i=0; i<nModes_; i++)
gains_[i]=(StkFloat) basegains_[i]*baseGain_;
// gains_[i]=(StkFloat) pow(baseGain_, (int)((StkFloat)delay_[i].getDelay()+i));
}
else if (number == __SK_ModFrequency_) // 11
integrationConstant = norm;
integrationConstant_ = norm;
else if (number == __SK_Sustain_) { // 64
if (value < 65) doPluck = true;
else doPluck = false;
if (value < 65) doPluck_ = true;
else doPluck_ = false;
}
else if (number == __SK_Portamento_) { // 65
if (value < 65) trackVelocity = false;
else trackVelocity = true;
if (value < 65) trackVelocity_ = false;
else trackVelocity_ = true;
}
else if (number == __SK_ProphesyRibbon_) // 16
this->setPreset((int) value);
else
std::cerr << "BandedWG: Undefined Control Number (" << number << ")!!" << std::endl;
else {
errorString_ << "BandedWG::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "BandedWG: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "BandedWG::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -28,7 +28,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -38,66 +38,77 @@ BeeThree :: BeeThree()
: FM()
{
// Concatenate the STK rawwave path to the rawwave files
for ( int i=0; i<3; i++ )
waves[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
waves[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), TRUE );
for ( unsigned int i=0; i<3; i++ )
waves_[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
waves_[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true );
this->setRatio(0, 0.999);
this->setRatio(1, 1.997);
this->setRatio(2, 3.006);
this->setRatio(3, 6.009);
gains[0] = __FM_gains[95];
gains[1] = __FM_gains[95];
gains[2] = __FM_gains[99];
gains[3] = __FM_gains[95];
gains_[0] = fmGains_[95];
gains_[1] = fmGains_[95];
gains_[2] = fmGains_[99];
gains_[3] = fmGains_[95];
adsr[0]->setAllTimes( 0.005, 0.003, 1.0, 0.01);
adsr[1]->setAllTimes( 0.005, 0.003, 1.0, 0.01);
adsr[2]->setAllTimes( 0.005, 0.003, 1.0, 0.01);
adsr[3]->setAllTimes( 0.005, 0.001, 0.4, 0.03);
adsr_[0]->setAllTimes( 0.005, 0.003, 1.0, 0.01);
adsr_[1]->setAllTimes( 0.005, 0.003, 1.0, 0.01);
adsr_[2]->setAllTimes( 0.005, 0.003, 1.0, 0.01);
adsr_[3]->setAllTimes( 0.005, 0.001, 0.4, 0.03);
twozero->setGain( 0.1 );
twozero_.setGain( 0.1 );
}
BeeThree :: ~BeeThree()
{
}
void BeeThree :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void BeeThree :: noteOn(StkFloat frequency, StkFloat amplitude)
{
gains[0] = amplitude * __FM_gains[95];
gains[1] = amplitude * __FM_gains[95];
gains[2] = amplitude * __FM_gains[99];
gains[3] = amplitude * __FM_gains[95];
this->setFrequency(frequency);
gains_[0] = amplitude * fmGains_[95];
gains_[1] = amplitude * fmGains_[95];
gains_[2] = amplitude * fmGains_[99];
gains_[3] = amplitude * fmGains_[95];
this->setFrequency( frequency );
this->keyOn();
#if defined(_STK_DEBUG_)
cerr << "BeeThree: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << endl;
errorString_ << "BeeThree::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT BeeThree :: tick()
StkFloat BeeThree :: tick()
{
register MY_FLOAT temp;
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]);
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);
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();
temp += control2_ * 2.0 * gains_[2] * adsr_[2]->tick() * waves_[2]->tick();
temp += gains_[1] * adsr_[1]->tick() * waves_[1]->tick();
temp += gains_[0] * adsr_[0]->tick() * waves_[0]->tick();
lastOutput = temp * 0.125;
return lastOutput;
lastOutput_ = temp * 0.125;
return lastOutput_;
}
StkFloat *BeeThree :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& BeeThree :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

View File

@@ -8,7 +8,7 @@
frequency response while maintaining a constant
filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -17,9 +17,11 @@
BiQuad :: BiQuad() : Filter()
{
MY_FLOAT B[3] = {1.0, 0.0, 0.0};
MY_FLOAT A[3] = {1.0, 0.0, 0.0};
Filter::setCoefficients( 3, B, 3, A );
std::vector<StkFloat> b(3, 0.0);
std::vector<StkFloat> a(3, 0.0);
b[0] = 1.0;
a[0] = 1.0;
Filter::setCoefficients( b, a );
}
BiQuad :: ~BiQuad()
@@ -31,90 +33,92 @@ void BiQuad :: clear(void)
Filter::clear();
}
void BiQuad :: setB0(MY_FLOAT b0)
void BiQuad :: setB0(StkFloat b0)
{
b[0] = b0;
b_[0] = b0;
}
void BiQuad :: setB1(MY_FLOAT b1)
void BiQuad :: setB1(StkFloat b1)
{
b[1] = b1;
b_[1] = b1;
}
void BiQuad :: setB2(MY_FLOAT b2)
void BiQuad :: setB2(StkFloat b2)
{
b[2] = b2;
b_[2] = b2;
}
void BiQuad :: setA1(MY_FLOAT a1)
void BiQuad :: setA1(StkFloat a1)
{
a[1] = a1;
a_[1] = a1;
}
void BiQuad :: setA2(MY_FLOAT a2)
void BiQuad :: setA2(StkFloat a2)
{
a[2] = a2;
a_[2] = a2;
}
void BiQuad :: setResonance(MY_FLOAT frequency, MY_FLOAT radius, bool normalize)
void BiQuad :: setResonance(StkFloat frequency, StkFloat radius, bool normalize)
{
a[2] = radius * radius;
a[1] = -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate());
a_[2] = radius * radius;
a_[1] = -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate());
if ( normalize ) {
// Use zeros at +- 1 and normalize the filter peak gain.
b[0] = 0.5 - 0.5 * a[2];
b[1] = 0.0;
b[2] = -b[0];
b_[0] = 0.5 - 0.5 * a_[2];
b_[1] = 0.0;
b_[2] = -b_[0];
}
}
void BiQuad :: setNotch(MY_FLOAT frequency, MY_FLOAT radius)
void BiQuad :: setNotch(StkFloat frequency, StkFloat radius)
{
// This method does not attempt to normalize the filter gain.
b[2] = radius * radius;
b[1] = (MY_FLOAT) -2.0 * radius * cos(TWO_PI * (double) frequency / Stk::sampleRate());
b_[2] = radius * radius;
b_[1] = (StkFloat) -2.0 * radius * cos(TWO_PI * (double) frequency / Stk::sampleRate());
}
void BiQuad :: setEqualGainZeroes()
{
b[0] = 1.0;
b[1] = 0.0;
b[2] = -1.0;
b_[0] = 1.0;
b_[1] = 0.0;
b_[2] = -1.0;
}
void BiQuad :: setGain(MY_FLOAT theGain)
void BiQuad :: setGain(StkFloat gain)
{
Filter::setGain(theGain);
Filter::setGain(gain);
}
MY_FLOAT BiQuad :: getGain(void) const
StkFloat BiQuad :: getGain(void) const
{
return Filter::getGain();
}
MY_FLOAT BiQuad :: lastOut(void) const
StkFloat BiQuad :: lastOut(void) const
{
return Filter::lastOut();
}
MY_FLOAT BiQuad :: tick(MY_FLOAT sample)
StkFloat BiQuad :: tick(StkFloat sample)
{
inputs[0] = gain * sample;
outputs[0] = b[0] * inputs[0] + b[1] * inputs[1] + b[2] * inputs[2];
outputs[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];
inputs_[0] = gain_ * sample;
outputs_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2];
outputs_[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];
return outputs[0];
return outputs_[0];
}
MY_FLOAT *BiQuad :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *BiQuad :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Filter::tick( vector, vectorSize );
}
StkFrames& BiQuad :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
}

View File

@@ -12,7 +12,7 @@
- Vibrato Gain = 1
- Volume = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -23,133 +23,138 @@
BlowBotl :: BlowBotl()
{
jetTable = new JetTabl();
dcBlock = new PoleZero();
dcBlock->setBlockZero();
dcBlock_.setBlockZero();
// Concatenate the STK rawwave path to the rawwave file
vibrato = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
vibrato->setFrequency( 5.925 );
vibratoGain = 0.0;
vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
vibrato_->setFrequency( 5.925 );
vibratoGain_ = 0.0;
resonator = new BiQuad();
resonator->setResonance(500.0, __BOTTLE_RADIUS_, true);
resonator_.setResonance(500.0, __BOTTLE_RADIUS_, true);
adsr_.setAllTimes( 0.005, 0.01, 0.8, 0.010);
adsr = new ADSR();
adsr->setAllTimes( 0.005, 0.01, 0.8, 0.010);
noise = new Noise();
noiseGain = 20.0;
maxPressure = (MY_FLOAT) 0.0;
noiseGain_ = 20.0;
maxPressure_ = (StkFloat) 0.0;
}
BlowBotl :: ~BlowBotl()
{
delete jetTable;
delete resonator;
delete dcBlock;
delete noise;
delete adsr;
delete vibrato;
delete vibrato_;
}
void BlowBotl :: clear()
{
resonator->clear();
resonator_.clear();
}
void BlowBotl :: setFrequency(MY_FLOAT frequency)
void BlowBotl :: setFrequency(StkFloat frequency)
{
MY_FLOAT freakency = frequency;
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "BlowBotl: setFrequency parameter is less than or equal to zero!" << std::endl;
errorString_ << "BlowBotl::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
}
resonator->setResonance( freakency, __BOTTLE_RADIUS_, true );
resonator_.setResonance( freakency, __BOTTLE_RADIUS_, true );
}
void BlowBotl :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate)
void BlowBotl :: startBlowing(StkFloat amplitude, StkFloat rate)
{
adsr->setAttackRate(rate);
maxPressure = amplitude;
adsr->keyOn();
adsr_.setAttackRate(rate);
maxPressure_ = amplitude;
adsr_.keyOn();
}
void BlowBotl :: stopBlowing(MY_FLOAT rate)
void BlowBotl :: stopBlowing(StkFloat rate)
{
adsr->setReleaseRate(rate);
adsr->keyOff();
adsr_.setReleaseRate(rate);
adsr_.keyOff();
}
void BlowBotl :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void BlowBotl :: noteOn(StkFloat frequency, StkFloat amplitude)
{
setFrequency(frequency);
this->setFrequency(frequency);
startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02);
outputGain = amplitude + 0.001;
outputGain_ = amplitude + 0.001;
#if defined(_STK_DEBUG_)
std::cerr << "BlowBotl: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "BlowBotl::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void BlowBotl :: noteOff(MY_FLOAT amplitude)
void BlowBotl :: noteOff(StkFloat amplitude)
{
this->stopBlowing(amplitude * 0.02);
#if defined(_STK_DEBUG_)
std::cerr << "BlowBotl: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "BlowBotl::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT BlowBotl :: tick()
StkFloat BlowBotl :: tick()
{
MY_FLOAT breathPressure;
MY_FLOAT randPressure;
MY_FLOAT pressureDiff;
StkFloat breathPressure;
StkFloat randPressure;
StkFloat pressureDiff;
// Calculate the breath pressure (envelope + vibrato)
breathPressure = maxPressure * adsr->tick();
breathPressure += vibratoGain * vibrato->tick();
breathPressure = maxPressure_ * adsr_.tick();
breathPressure += vibratoGain_ * vibrato_->tick();
pressureDiff = breathPressure - resonator->lastOut();
pressureDiff = breathPressure - resonator_.lastOut();
randPressure = noiseGain * noise->tick();
randPressure = noiseGain_ * noise_.tick();
randPressure *= breathPressure;
randPressure *= (1.0 + pressureDiff);
resonator->tick( breathPressure + randPressure - ( jetTable->tick( pressureDiff ) * pressureDiff ) );
lastOutput = 0.2 * outputGain * dcBlock->tick( pressureDiff );
resonator_.tick( breathPressure + randPressure - ( jetTable_.tick( pressureDiff ) * pressureDiff ) );
lastOutput_ = 0.2 * outputGain_ * dcBlock_.tick( pressureDiff );
return lastOutput;
return lastOutput_;
}
void BlowBotl :: controlChange(int number, MY_FLOAT value)
StkFloat *BlowBotl :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& BlowBotl :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void BlowBotl :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "BlowBotl: Control value less than zero!" << std::endl;
errorString_ << "BlowBotl::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "BlowBotl: Control value greater than 128.0!" << std::endl;
errorString_ << "BlowBotl::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_NoiseLevel_) // 4
noiseGain = norm * 30.0;
noiseGain_ = norm * 30.0;
else if (number == __SK_ModFrequency_) // 11
vibrato->setFrequency( norm * 12.0 );
vibrato_->setFrequency( norm * 12.0 );
else if (number == __SK_ModWheel_) // 1
vibratoGain = norm * 0.4;
vibratoGain_ = norm * 0.4;
else if (number == __SK_AfterTouch_Cont_) // 128
adsr->setTarget( norm );
else
std::cerr << "BlowBotl: Undefined Control Number (" << number << ")!!" << std::endl;
adsr_.setTarget( norm );
else {
errorString_ << "BlowBotl::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "BlowBotl: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "BlowBotl::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -29,7 +29,7 @@
- Register State = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -37,221 +37,232 @@
#include "SKINI.msg"
#include <math.h>
BlowHole :: BlowHole(MY_FLOAT lowestFrequency)
BlowHole :: BlowHole(StkFloat lowestFrequency)
{
length = (long) (Stk::sampleRate() / lowestFrequency + 1);
length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
// delays[0] is the delay line between the reed and the register vent.
delays[0] = (DelayL *) new DelayL( 5.0 * Stk::sampleRate() / 22050.0, 100 );
delays_[0].setDelay( 5.0 * Stk::sampleRate() / 22050.0 );
// delays[1] is the delay line between the register vent and the tonehole.
delays[1] = (DelayL *) new DelayL( length >> 1, length );
delays_[1].setMaximumDelay( length_ );
delays_[1].setDelay( length_ >> 1 );
// delays[2] is the delay line between the tonehole and the end of the bore.
delays[2] = (DelayL *) new DelayL( 4.0 * Stk::sampleRate() / 22050.0, 100 );
reedTable = new ReedTabl();
reedTable->setOffset((MY_FLOAT) 0.7);
reedTable->setSlope((MY_FLOAT) -0.3);
filter = new OneZero;
envelope = new Envelope;
noise = new Noise;
delays_[2].setDelay( 4.0 * Stk::sampleRate() / 22050.0 );
reedTable_.setOffset( 0.7 );
reedTable_.setSlope( -0.3 );
// Calculate the initial tonehole three-port scattering coefficient
double r_b = 0.0075; // main bore radius
r_th = 0.003; // tonehole radius
scatter = -pow(r_th,2) / ( pow(r_th,2) + 2*pow(r_b,2) );
StkFloat rb = 0.0075; // main bore radius
StkFloat rth = 0.003; // tonehole radius
scatter_ = -pow(rth,2) / ( pow(rth,2) + 2*pow(rb,2) );
// Calculate tonehole coefficients
MY_FLOAT te = 1.4 * r_th; // effective length of the open hole
th_coeff = (te*2*Stk::sampleRate() - 347.23) / (te*2*Stk::sampleRate() + 347.23);
tonehole = new PoleZero;
// Start with tonehole open
tonehole->setA1(-th_coeff);
tonehole->setB0(th_coeff);
tonehole->setB1(-1.0);
// Calculate tonehole coefficients and set for initially open.
StkFloat te = 1.4 * rth; // effective length of the open hole
thCoeff_ = (te*2*Stk::sampleRate() - 347.23) / (te*2*Stk::sampleRate() + 347.23);
tonehole_.setA1(-thCoeff_);
tonehole_.setB0(thCoeff_);
tonehole_.setB1(-1.0);
// Calculate register hole filter coefficients
double r_rh = 0.0015; // register vent radius
te = 1.4 * r_rh; // effective length of the open hole
te = 1.4 * r_rh; // effective length of the open hole
double xi = 0.0; // series resistance term
double zeta = 347.23 + 2*PI*pow(r_b,2)*xi/1.1769;
double psi = 2*PI*pow(r_b,2)*te / (PI*pow(r_rh,2));
rh_coeff = (zeta - 2 * Stk::sampleRate() * psi) / (zeta + 2 * Stk::sampleRate() * psi);
rh_gain = -347.23 / (zeta + 2 * Stk::sampleRate() * psi);
vent = new PoleZero;
vent->setA1(rh_coeff);
vent->setB0(1.0);
vent->setB1(1.0);
double zeta = 347.23 + 2*PI*pow(rb,2)*xi/1.1769;
double psi = 2*PI*pow(rb,2)*te / (PI*pow(r_rh,2));
StkFloat rhCoeff = (zeta - 2 * Stk::sampleRate() * psi) / (zeta + 2 * Stk::sampleRate() * psi);
rhGain_ = -347.23 / (zeta + 2 * Stk::sampleRate() * psi);
vent_.setA1( rhCoeff );
vent_.setB0(1.0);
vent_.setB1(1.0);
// Start with register vent closed
vent->setGain(0.0);
vent_.setGain(0.0);
// Concatenate the STK rawwave path to the rawwave file
vibrato = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
vibrato->setFrequency((MY_FLOAT) 5.735);
outputGain = (MY_FLOAT) 1.0;
noiseGain = (MY_FLOAT) 0.2;
vibratoGain = (MY_FLOAT) 0.01;
vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
vibrato_->setFrequency((StkFloat) 5.735);
outputGain_ = 1.0;
noiseGain_ = 0.2;
vibratoGain_ = 0.01;
}
BlowHole :: ~BlowHole()
{
delete delays[0];
delete delays[1];
delete delays[2];
delete reedTable;
delete filter;
delete tonehole;
delete vent;
delete envelope;
delete noise;
delete vibrato;
delete vibrato_;
}
void BlowHole :: clear()
{
delays[0]->clear();
delays[1]->clear();
delays[2]->clear();
filter->tick((MY_FLOAT) 0.0);
tonehole->tick((MY_FLOAT) 0.0);
vent->tick((MY_FLOAT) 0.0);
delays_[0].clear();
delays_[1].clear();
delays_[2].clear();
filter_.tick( 0.0 );
tonehole_.tick( 0.0 );
vent_.tick( 0.0 );
}
void BlowHole :: setFrequency(MY_FLOAT frequency)
void BlowHole :: setFrequency(StkFloat frequency)
{
MY_FLOAT freakency = frequency;
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "BlowHole: setFrequency parameter is less than or equal to zero!" << std::endl;
freakency = 220.0;
}
// Delay = length - approximate filter delay.
MY_FLOAT delay = (Stk::sampleRate() / freakency) * 0.5 - 3.5;
delay -= delays[0]->getDelay() + delays[2]->getDelay();
StkFloat delay = (Stk::sampleRate() / freakency) * 0.5 - 3.5;
delay -= delays_[0].getDelay() + delays_[2].getDelay();
if (delay <= 0.0) delay = 0.3;
else if (delay > length) delay = length;
delays[1]->setDelay(delay);
else if (delay > length_) delay = length_;
delays_[1].setDelay(delay);
}
void BlowHole :: setVent(MY_FLOAT newValue)
void BlowHole :: setVent(StkFloat newValue)
{
// This method allows setting of the register vent "open-ness" at
// any point between "Open" (newValue = 1) and "Closed"
// (newValue = 0).
MY_FLOAT gain;
StkFloat gain;
if (newValue <= 0.0) gain = 0.0;
else if (newValue >= 1.0) gain = rh_gain;
else gain = newValue * rh_gain;
vent->setGain(gain);
if (newValue <= 0.0)
gain = 0.0;
else if (newValue >= 1.0)
gain = rhGain_;
else
gain = newValue * rhGain_;
vent_.setGain( gain );
}
void BlowHole :: setTonehole(MY_FLOAT newValue)
void BlowHole :: setTonehole(StkFloat newValue)
{
// This method allows setting of the tonehole "open-ness" at
// any point between "Open" (newValue = 1) and "Closed"
// (newValue = 0).
MY_FLOAT new_coeff;
StkFloat new_coeff;
if (newValue <= 0.0) new_coeff = 0.9995;
else if (newValue >= 1.0) new_coeff = th_coeff;
else new_coeff = (newValue * (th_coeff - 0.9995)) + 0.9995;
tonehole->setA1(-new_coeff);
tonehole->setB0(new_coeff);
if ( newValue <= 0.0 )
new_coeff = 0.9995;
else if ( newValue >= 1.0 )
new_coeff = thCoeff_;
else
new_coeff = (newValue * (thCoeff_ - 0.9995)) + 0.9995;
tonehole_.setA1( -new_coeff );
tonehole_.setB0( new_coeff );
}
void BlowHole :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate)
void BlowHole :: startBlowing(StkFloat amplitude, StkFloat rate)
{
envelope->setRate(rate);
envelope->setTarget(amplitude);
envelope_.setRate( rate );
envelope_.setTarget( amplitude );
}
void BlowHole :: stopBlowing(MY_FLOAT rate)
void BlowHole :: stopBlowing(StkFloat rate)
{
envelope->setRate(rate);
envelope->setTarget((MY_FLOAT) 0.0);
envelope_.setRate( rate );
envelope_.setTarget( 0.0 );
}
void BlowHole :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void BlowHole :: noteOn(StkFloat frequency, StkFloat amplitude)
{
setFrequency(frequency);
startBlowing((MY_FLOAT) 0.55 + (amplitude * 0.30), amplitude * 0.005);
outputGain = amplitude + 0.001;
this->setFrequency( frequency );
this->startBlowing( 0.55 + (amplitude * 0.30), amplitude * 0.005 );
outputGain_ = amplitude + 0.001;
#if defined(_STK_DEBUG_)
std::cerr << "BlowHole: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "BlowHole::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void BlowHole :: noteOff(MY_FLOAT amplitude)
void BlowHole :: noteOff(StkFloat amplitude)
{
this->stopBlowing(amplitude * 0.01);
this->stopBlowing( amplitude * 0.01 );
#if defined(_STK_DEBUG_)
std::cerr << "BlowHole: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "BlowHole::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT BlowHole :: tick()
StkFloat BlowHole :: tick()
{
MY_FLOAT pressureDiff;
MY_FLOAT breathPressure;
MY_FLOAT temp;
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();
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;
pressureDiff = delays_[0].lastOut() - breathPressure;
// Do two-port junction scattering for register vent
MY_FLOAT pa = breathPressure + pressureDiff * reedTable->tick(pressureDiff);
MY_FLOAT pb = delays[1]->lastOut();
vent->tick(pa+pb);
StkFloat pa = breathPressure + pressureDiff * reedTable_.tick( pressureDiff );
StkFloat pb = delays_[1].lastOut();
vent_.tick( pa+pb );
lastOutput = delays[0]->tick(vent->lastOut()+pb);
lastOutput *= outputGain;
lastOutput_ = delays_[0].tick( vent_.lastOut()+pb );
lastOutput_ *= outputGain_;
// Do three-port junction scattering (under tonehole)
pa += vent->lastOut();
pb = delays[2]->lastOut();
MY_FLOAT pth = tonehole->lastOut();
temp = scatter * (pa + pb - 2 * pth);
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);
delays_[2].tick( filter_.tick(pa + temp) * -0.95 );
delays_[1].tick( pb + temp );
tonehole_.tick( pa + pb - pth + temp );
return lastOutput;
return lastOutput_;
}
void BlowHole :: controlChange(int number, MY_FLOAT value)
StkFloat *BlowHole :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& BlowHole :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void BlowHole :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "BlowHole: Control value less than zero!" << std::endl;
errorString_ << "BlowHole::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "BlowHole: Control value greater than 128.0!" << std::endl;
errorString_ << "BlowHole::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_ReedStiffness_) // 2
reedTable->setSlope( -0.44 + (0.26 * norm) );
reedTable_.setSlope( -0.44 + (0.26 * norm) );
else if (number == __SK_NoiseLevel_) // 4
noiseGain = ( norm * 0.4);
noiseGain_ = ( norm * 0.4);
else if (number == __SK_ModFrequency_) // 11
this->setTonehole( norm );
else if (number == __SK_ModWheel_) // 1
this->setVent( norm );
else if (number == __SK_AfterTouch_Cont_) // 128
envelope->setValue( norm );
else
std::cerr << "BlowHole: Undefined Control Number (" << number << ")!!" << std::endl;
envelope_.setValue( norm );
else {
errorString_ << "BlowHole::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "BlowHole: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "BlowHole::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -1,63 +0,0 @@
/***************************************************/
/*! \class BowTabl
\brief STK bowed string table class.
This class implements a simple bowed string
non-linear function, as described by Smith (1986).
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
*/
/***************************************************/
#include "BowTabl.h"
#include <math.h>
BowTabl :: BowTabl()
{
offSet = (MY_FLOAT) 0.0;
slope = (MY_FLOAT) 0.1;
}
BowTabl :: ~BowTabl()
{
}
void BowTabl :: setOffset(MY_FLOAT aValue)
{
offSet = aValue;
}
void BowTabl :: setSlope(MY_FLOAT aValue)
{
slope = aValue;
}
MY_FLOAT BowTabl :: lastOut() const
{
return lastOutput;
}
MY_FLOAT BowTabl :: tick(MY_FLOAT input)
{
// The input represents differential string vs. bow velocity.
MY_FLOAT sample;
sample = input + offSet; // add bias to input
sample *= slope; // then scale it
lastOutput = (MY_FLOAT) fabs((double) sample) + (MY_FLOAT) 0.75;
lastOutput = (MY_FLOAT) pow( lastOutput,(MY_FLOAT) -4.0 );
// Set minimum friction to 0.0
//if (lastOutput < 0.0 ) lastOutput = 0.0;
// Set maximum friction to 1.0.
if (lastOutput > 1.0 ) lastOutput = (MY_FLOAT) 1.0;
return lastOutput;
}
MY_FLOAT *BowTabl :: tick(MY_FLOAT *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
}

60
src/BowTable.cpp Normal file
View File

@@ -0,0 +1,60 @@
/***************************************************/
/*! \class BowTable
\brief STK bowed string table class.
This class implements a simple bowed string
non-linear function, as described by Smith (1986).
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "BowTable.h"
#include <math.h>
BowTable :: BowTable()
{
offset_ = (StkFloat) 0.0;
slope_ = (StkFloat) 0.1;
}
BowTable :: ~BowTable()
{
}
void BowTable :: setOffset(StkFloat offset)
{
offset_ = offset;
}
void BowTable :: setSlope(StkFloat slope)
{
slope_ = slope;
}
StkFloat BowTable :: tick(StkFloat input)
{
// The input represents differential string vs. bow velocity.
StkFloat sample;
sample = input + offset_; // add bias to input
sample *= slope_; // then scale it
lastOutput_ = (StkFloat) fabs( (double) sample ) + (StkFloat) 0.75;
lastOutput_ = (StkFloat) pow( lastOutput_, (StkFloat) -4.0 );
// Set minimum friction to 0.0
// if (lastOutput < 0.0 ) lastOutput = 0.0;
// Set maximum friction to 1.0.
if (lastOutput_ > 1.0 ) lastOutput_ = (StkFloat) 1.0;
return lastOutput_;
}
StkFloat *BowTable :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Function::tick( vector, vectorSize );
}
StkFrames& BowTable :: tick( StkFrames& frames, unsigned int channel )
{
return Function::tick( frames, channel );
}

View File

@@ -17,173 +17,184 @@
- Vibrato Gain = 1
- Volume = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Bowed.h"
#include "SKINI.msg"
Bowed :: Bowed(MY_FLOAT lowestFrequency)
Bowed :: Bowed(StkFloat lowestFrequency)
{
long length;
length = (long) (Stk::sampleRate() / lowestFrequency + 1);
neckDelay = new DelayL(100.0, length);
length >>= 1;
bridgeDelay = new DelayL(29.0, length);
unsigned long length;
length = (long) ( Stk::sampleRate() / lowestFrequency + 1 );
neckDelay_.setMaximumDelay( length );
neckDelay_.setDelay( 100.0 );
bowTable = new BowTabl;
bowTable->setSlope((MY_FLOAT) 3.0);
length >>= 1;
bridgeDelay_.setMaximumDelay( length );
bridgeDelay_.setDelay( 29.0 );
bowTable_.setSlope(3.0 );
// Concatenate the STK rawwave path to the rawwave file
vibrato = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
vibrato->setFrequency((MY_FLOAT) 6.12723);
vibratoGain = (MY_FLOAT) 0.0;
vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
vibrato_->setFrequency( 6.12723 );
vibratoGain_ = 0.0;
stringFilter = new OnePole;
stringFilter->setPole((MY_FLOAT) (0.6 - (0.1 * 22050.0 / Stk::sampleRate() ) ) );
stringFilter->setGain((MY_FLOAT) 0.95);
stringFilter_.setPole( 0.6 - (0.1 * 22050.0 / Stk::sampleRate()) );
stringFilter_.setGain( 0.95 );
bodyFilter = new BiQuad;
bodyFilter->setResonance( 500.0, 0.85, TRUE );
bodyFilter->setGain((MY_FLOAT) 0.2);
bodyFilter_.setResonance( 500.0, 0.85, true );
bodyFilter_.setGain( 0.2 );
adsr = new ADSR;
adsr->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.005,(MY_FLOAT) 0.9,(MY_FLOAT) 0.01);
adsr_.setAllTimes( 0.02, 0.005, 0.9, 0.01 );
betaRatio = (MY_FLOAT) 0.127236;
betaRatio_ = 0.127236;
// Necessary to initialize internal variables.
setFrequency( 220.0 );
this->setFrequency( 220.0 );
}
Bowed :: ~Bowed()
{
delete neckDelay;
delete bridgeDelay;
delete bowTable;
delete stringFilter;
delete bodyFilter;
delete vibrato;
delete adsr;
delete vibrato_;
}
void Bowed :: clear()
{
neckDelay->clear();
bridgeDelay->clear();
neckDelay_.clear();
bridgeDelay_.clear();
}
void Bowed :: setFrequency(MY_FLOAT frequency)
void Bowed :: setFrequency(StkFloat frequency)
{
MY_FLOAT freakency = frequency;
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "Bowed: setFrequency parameter is less than or equal to zero!" << std::endl;
errorString_ << "Bowed::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
}
// Delay = length - approximate filter delay.
baseDelay = Stk::sampleRate() / freakency - (MY_FLOAT) 4.0;
if ( baseDelay <= 0.0 ) baseDelay = 0.3;
bridgeDelay->setDelay(baseDelay * betaRatio); // bow to bridge length
neckDelay->setDelay(baseDelay * ((MY_FLOAT) 1.0 - betaRatio)); // bow to nut (finger) length
baseDelay_ = Stk::sampleRate() / freakency - 4.0;
if ( baseDelay_ <= 0.0 ) baseDelay_ = 0.3;
bridgeDelay_.setDelay( baseDelay_ * betaRatio_ ); // bow to bridge length
neckDelay_.setDelay( baseDelay_ * (1.0 - betaRatio_) ); // bow to nut (finger) length
}
void Bowed :: startBowing(MY_FLOAT amplitude, MY_FLOAT rate)
void Bowed :: startBowing(StkFloat amplitude, StkFloat rate)
{
adsr->setRate(rate);
adsr->keyOn();
maxVelocity = (MY_FLOAT) 0.03 + ((MY_FLOAT) 0.2 * amplitude);
adsr_.setRate( rate );
adsr_.keyOn();
maxVelocity_ = 0.03 + ( 0.2 * amplitude );
}
void Bowed :: stopBowing(MY_FLOAT rate)
void Bowed :: stopBowing(StkFloat rate)
{
adsr->setRate(rate);
adsr->keyOff();
adsr_.setRate( rate );
adsr_.keyOff();
}
void Bowed :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Bowed :: noteOn(StkFloat frequency, StkFloat amplitude)
{
this->startBowing(amplitude, amplitude * 0.001);
this->setFrequency(frequency);
this->startBowing( amplitude, amplitude * 0.001 );
this->setFrequency( frequency );
#if defined(_STK_DEBUG_)
std::cerr << "Bowed: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Bowed::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Bowed :: noteOff(MY_FLOAT amplitude)
void Bowed :: noteOff(StkFloat amplitude)
{
this->stopBowing(((MY_FLOAT) 1.0 - amplitude) * (MY_FLOAT) 0.005);
this->stopBowing( (1.0 - amplitude) * 0.005 );
#if defined(_STK_DEBUG_)
std::cerr << "Bowed: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Bowed::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Bowed :: setVibrato(MY_FLOAT gain)
void Bowed :: setVibrato(StkFloat gain)
{
vibratoGain = gain;
vibratoGain_ = gain;
}
MY_FLOAT Bowed :: tick()
StkFloat Bowed :: tick()
{
MY_FLOAT bowVelocity;
MY_FLOAT bridgeRefl;
MY_FLOAT nutRefl;
MY_FLOAT newVel;
MY_FLOAT velDiff;
MY_FLOAT stringVel;
StkFloat bowVelocity;
StkFloat bridgeRefl;
StkFloat nutRefl;
StkFloat newVel;
StkFloat velDiff;
StkFloat stringVel;
bowVelocity = maxVelocity * adsr->tick();
bowVelocity = maxVelocity_ * adsr_.tick();
bridgeRefl = -stringFilter->tick( bridgeDelay->lastOut() );
nutRefl = -neckDelay->lastOut();
bridgeRefl = -stringFilter_.tick( bridgeDelay_.lastOut() );
nutRefl = -neckDelay_.lastOut();
stringVel = bridgeRefl + nutRefl; // Sum is String Velocity
velDiff = bowVelocity - stringVel; // Differential Velocity
newVel = velDiff * bowTable->tick( velDiff ); // Non-Linear Bow Function
neckDelay->tick(bridgeRefl + newVel); // Do string propagations
bridgeDelay->tick(nutRefl + newVel);
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 * ((MY_FLOAT) 1.0 - betaRatio)) +
(baseDelay * vibratoGain * vibrato->tick()));
if ( vibratoGain_ > 0.0 ) {
neckDelay_.setDelay( (baseDelay_ * (1.0 - betaRatio_) ) +
(baseDelay_ * vibratoGain_ * vibrato_->tick()) );
}
lastOutput = bodyFilter->tick(bridgeDelay->lastOut());
lastOutput_ = bodyFilter_.tick( bridgeDelay_.lastOut() );
return lastOutput;
return lastOutput_;
}
void Bowed :: controlChange(int number, MY_FLOAT value)
StkFloat *Bowed :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Bowed :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void Bowed :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "Bowed: Control value less than zero!" << std::endl;
errorString_ << "Bowed::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "Bowed: Control value greater than 128.0!" << std::endl;
errorString_ << "Bowed::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_BowPressure_) // 2
bowTable->setSlope( 5.0 - (4.0 * norm) );
bowTable_.setSlope( 5.0 - (4.0 * norm) );
else if (number == __SK_BowPosition_) { // 4
betaRatio = 0.027236 + (0.2 * norm);
bridgeDelay->setDelay(baseDelay * betaRatio);
neckDelay->setDelay(baseDelay * ((MY_FLOAT) 1.0 - betaRatio));
betaRatio_ = 0.027236 + (0.2 * norm);
bridgeDelay_.setDelay( baseDelay_ * betaRatio_ );
neckDelay_.setDelay( baseDelay_ * (1.0 - betaRatio_) );
}
else if (number == __SK_ModFrequency_) // 11
vibrato->setFrequency( norm * 12.0 );
vibrato_->setFrequency( norm * 12.0 );
else if (number == __SK_ModWheel_) // 1
vibratoGain = ( norm * 0.4 );
vibratoGain_ = ( norm * 0.4 );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr->setTarget(norm);
else
std::cerr << "Bowed: Undefined Control Number (" << number << ")!!" << std::endl;
adsr_.setTarget(norm);
else {
errorString_ << "Bowed::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "Bowed: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "Bowed::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -16,7 +16,7 @@
- Vibrato Gain = 1
- Volume = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -24,153 +24,167 @@
#include "SKINI.msg"
#include <math.h>
Brass :: Brass(MY_FLOAT lowestFrequency)
Brass :: Brass(StkFloat lowestFrequency)
{
length = (long) (Stk::sampleRate() / lowestFrequency + 1);
delayLine = new DelayA( 0.5 * length, length );
length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( 0.5 * length_ );
lipFilter = new BiQuad();
lipFilter->setGain( 0.03 );
dcBlock = new PoleZero();
dcBlock->setBlockZero();
lipFilter_.setGain( 0.03 );
dcBlock_.setBlockZero();
adsr = new ADSR;
adsr->setAllTimes( 0.005, 0.001, 1.0, 0.010);
adsr_.setAllTimes( 0.005, 0.001, 1.0, 0.010);
// Concatenate the STK rawwave path to the rawwave file
vibrato = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
vibrato->setFrequency( 6.137 );
vibratoGain = 0.0;
vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
vibrato_->setFrequency( 6.137 );
vibratoGain_ = 0.0;
this->clear();
maxPressure = (MY_FLOAT) 0.0;
lipTarget = 0.0;
maxPressure_ = 0.0;
lipTarget_ = 0.0;
// Necessary to initialize variables.
setFrequency( 220.0 );
// This is necessary to initialize variables.
this->setFrequency( 220.0 );
}
Brass :: ~Brass()
{
delete delayLine;
delete lipFilter;
delete dcBlock;
delete adsr;
delete vibrato;
delete vibrato_;
}
void Brass :: clear()
{
delayLine->clear();
lipFilter->clear();
dcBlock->clear();
delayLine_.clear();
lipFilter_.clear();
dcBlock_.clear();
}
void Brass :: setFrequency(MY_FLOAT frequency)
void Brass :: setFrequency(StkFloat frequency)
{
MY_FLOAT freakency = frequency;
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "Brass: setFrequency parameter is less than or equal to zero!" << std::endl;
errorString_ << "Brass::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
}
// Fudge correction for filter delays.
slideTarget = (Stk::sampleRate() / freakency * 2.0) + 3.0;
delayLine->setDelay(slideTarget); // play a harmonic
slideTarget_ = (Stk::sampleRate() / freakency * 2.0) + 3.0;
delayLine_.setDelay( slideTarget_ ); // play a harmonic
lipTarget = freakency;
lipFilter->setResonance( freakency, 0.997 );
lipTarget_ = freakency;
lipFilter_.setResonance( freakency, 0.997 );
}
void Brass :: setLip(MY_FLOAT frequency)
void Brass :: setLip(StkFloat frequency)
{
MY_FLOAT freakency = frequency;
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "Brass: setLip parameter is less than or equal to zero!" << std::endl;
errorString_ << "Brass::setLip: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
}
lipFilter->setResonance( freakency, 0.997 );
lipFilter_.setResonance( freakency, 0.997 );
}
void Brass :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate)
void Brass :: startBlowing(StkFloat amplitude, StkFloat rate)
{
adsr->setAttackRate(rate);
maxPressure = amplitude;
adsr->keyOn();
adsr_.setAttackRate( rate );
maxPressure_ = amplitude;
adsr_.keyOn();
}
void Brass :: stopBlowing(MY_FLOAT rate)
void Brass :: stopBlowing(StkFloat rate)
{
adsr->setReleaseRate(rate);
adsr->keyOff();
adsr_.setReleaseRate( rate );
adsr_.keyOff();
}
void Brass :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Brass :: noteOn(StkFloat frequency, StkFloat amplitude)
{
setFrequency(frequency);
this->startBlowing(amplitude, amplitude * 0.001);
this->setFrequency( frequency );
this->startBlowing( amplitude, amplitude * 0.001 );
#if defined(_STK_DEBUG_)
std::cerr << "Brass: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Brass::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Brass :: noteOff(MY_FLOAT amplitude)
void Brass :: noteOff(StkFloat amplitude)
{
this->stopBlowing(amplitude * 0.005);
this->stopBlowing( amplitude * 0.005 );
#if defined(_STK_DEBUG_)
std::cerr << "Brass: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Brass::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT Brass :: tick()
StkFloat Brass :: tick()
{
MY_FLOAT breathPressure = maxPressure * adsr->tick();
breathPressure += vibratoGain * vibrato->tick();
StkFloat breathPressure = maxPressure_ * adsr_.tick();
breathPressure += vibratoGain_ * vibrato_->tick();
MY_FLOAT mouthPressure = 0.3 * breathPressure;
MY_FLOAT borePressure = 0.85 * delayLine->lastOut();
MY_FLOAT deltaPressure = mouthPressure - borePressure; // Differential pressure.
deltaPressure = lipFilter->tick( deltaPressure ); // Force - > position.
StkFloat mouthPressure = 0.3 * breathPressure;
StkFloat borePressure = 0.85 * delayLine_.lastOut();
StkFloat deltaPressure = mouthPressure - borePressure; // Differential pressure.
deltaPressure = lipFilter_.tick( deltaPressure ); // Force - > position.
deltaPressure *= deltaPressure; // Basic position to area mapping.
if ( deltaPressure > 1.0 ) deltaPressure = 1.0; // Non-linear saturation.
// The following input scattering assumes the mouthPressure = area.
lastOutput = deltaPressure * mouthPressure + ( 1.0 - deltaPressure) * borePressure;
lastOutput = delayLine->tick( dcBlock->tick( lastOutput ) );
if ( deltaPressure > 1.0 ) deltaPressure = 1.0; // Non-linear saturation.
return lastOutput;
// The following input scattering assumes the mouthPressure = area.
lastOutput_ = deltaPressure * mouthPressure + ( 1.0 - deltaPressure) * borePressure;
lastOutput_ = delayLine_.tick( dcBlock_.tick( lastOutput_ ) );
return lastOutput_;
}
void Brass :: controlChange(int number, MY_FLOAT value)
StkFloat *Brass :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Brass :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void Brass :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "Brass: Control value less than zero!" << std::endl;
errorString_ << "Brass::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "Brass: Control value greater than 128.0!" << std::endl;
errorString_ << "Brass::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_LipTension_) { // 2
MY_FLOAT temp = lipTarget * pow( 4.0, (2.0 * norm) - 1.0 );
StkFloat temp = lipTarget_ * pow( 4.0, (2.0 * norm) - 1.0 );
this->setLip(temp);
}
else if (number == __SK_SlideLength_) // 4
delayLine->setDelay( slideTarget * (0.5 + norm) );
delayLine_.setDelay( slideTarget_ * (0.5 + norm) );
else if (number == __SK_ModFrequency_) // 11
vibrato->setFrequency( norm * 12.0 );
vibrato_->setFrequency( norm * 12.0 );
else if (number == __SK_ModWheel_ ) // 1
vibratoGain = norm * 0.4;
vibratoGain_ = norm * 0.4;
else if (number == __SK_AfterTouch_Cont_) // 128
adsr->setTarget( norm );
else
std::cerr << "Brass: Undefined Control Number (" << number << ")!!" << std::endl;
adsr_.setTarget( norm );
else {
errorString_ << "Brass::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "Brass: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "Brass::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -4,99 +4,73 @@
This class implements a chorus effect.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Chorus.h"
#include <iostream>
Chorus :: Chorus(MY_FLOAT baseDelay)
Chorus :: Chorus(StkFloat baseDelay)
{
delayLine[0] = new DelayL((long) baseDelay, (long) (baseDelay * 1.414) + 2);
delayLine[1] = new DelayL((long) (baseDelay), (long) baseDelay + 2);
baseLength = baseDelay;
delayLine_[0].setMaximumDelay( (unsigned long) (baseDelay * 1.414) + 2);
delayLine_[0].setDelay( baseDelay );
delayLine_[1].setMaximumDelay( (unsigned long) (baseDelay * 1.414) + 2);
delayLine_[1].setDelay( baseDelay );
baseLength_ = baseDelay;
// Concatenate the STK rawwave path to the rawwave file
mods[0] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
mods[1] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
mods[0]->setFrequency(0.2);
mods[1]->setFrequency(0.222222);
modDepth = 0.05;
effectMix = 0.5;
mods_[0] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
mods_[1] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
mods_[0]->setFrequency(0.2);
mods_[1]->setFrequency(0.222222);
modDepth_ = 0.05;
effectMix_ = 0.5;
this->clear();
}
Chorus :: ~Chorus()
{
delete delayLine[0];
delete delayLine[1];
delete mods[0];
delete mods[1];
delete mods_[0];
delete mods_[1];
}
void Chorus :: clear()
{
delayLine[0]->clear();
delayLine[1]->clear();
lastOutput[0] = 0.0;
lastOutput[1] = 0.0;
delayLine_[0].clear();
delayLine_[1].clear();
lastOutput_[0] = 0.0;
lastOutput_[1] = 0.0;
}
void Chorus :: setEffectMix(MY_FLOAT mix)
void Chorus :: setModDepth(StkFloat depth)
{
effectMix = mix;
if ( mix < 0.0 ) {
std::cerr << "Chorus: setEffectMix parameter is less than zero!" << std::endl;
effectMix = 0.0;
}
else if ( mix > 1.0 ) {
std::cerr << "Chorus: setEffectMix parameter is greater than 1.0!" << std::endl;
effectMix = 1.0;
}
modDepth_ = depth;
}
void Chorus :: setModDepth(MY_FLOAT depth)
void Chorus :: setModFrequency(StkFloat frequency)
{
modDepth = depth;
mods_[0]->setFrequency(frequency);
mods_[1]->setFrequency(frequency * 1.1111);
}
void Chorus :: setModFrequency(MY_FLOAT frequency)
StkFloat Chorus :: tick(StkFloat input)
{
mods[0]->setFrequency(frequency);
mods[1]->setFrequency(frequency * 1.1111);
delayLine_[0].setDelay( baseLength_ * 0.707 * (1.0 + mods_[0]->tick()) );
delayLine_[1].setDelay( baseLength_ * 0.5 * (1.0 - mods_[1]->tick()) );
lastOutput_[0] = input * (1.0 - effectMix_);
lastOutput_[0] += effectMix_ * delayLine_[0].tick(input);
lastOutput_[1] = input * (1.0 - effectMix_);
lastOutput_[1] += effectMix_ * delayLine_[1].tick(input);
return Effect::lastOut();
}
MY_FLOAT Chorus :: lastOut() const
StkFloat *Chorus :: tick(StkFloat *vector, unsigned int vectorSize)
{
return (lastOutput[0] + lastOutput[1]) * (MY_FLOAT) 0.5;
return Effect::tick( vector, vectorSize );
}
MY_FLOAT Chorus :: lastOutLeft() const
StkFrames& Chorus :: tick( StkFrames& frames, unsigned int channel )
{
return lastOutput[0];
}
MY_FLOAT Chorus :: lastOutRight() const
{
return lastOutput[1];
}
MY_FLOAT Chorus :: tick(MY_FLOAT input)
{
delayLine[0]->setDelay(baseLength * 0.707 * (1.0 + mods[0]->tick()));
delayLine[1]->setDelay(baseLength * 0.5 * (1.0 - mods[1]->tick()));
lastOutput[0] = input * (1.0 - effectMix);
lastOutput[0] += effectMix * delayLine[0]->tick(input);
lastOutput[1] = input * (1.0 - effectMix);
lastOutput[1] += effectMix * delayLine[1]->tick(input);
return (lastOutput[0] + lastOutput[1]) * (MY_FLOAT) 0.5;
}
MY_FLOAT *Chorus :: tick(MY_FLOAT *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Effect::tick( frames, channel );
}

View File

@@ -18,146 +18,156 @@
- Vibrato Gain = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Clarinet.h"
#include "SKINI.msg"
Clarinet :: Clarinet(MY_FLOAT lowestFrequency)
Clarinet :: Clarinet(StkFloat lowestFrequency)
{
length = (long) (Stk::sampleRate() / lowestFrequency + 1);
delayLine = new DelayL( (MY_FLOAT)(length / 2.0), length);
reedTable = new ReedTabl();
reedTable->setOffset((MY_FLOAT) 0.7);
reedTable->setSlope((MY_FLOAT) -0.3);
filter = new OneZero;
envelope = new Envelope;
noise = new Noise;
length_ = (long) (Stk::sampleRate() / lowestFrequency + 1);
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( length_ / 2.0 );
reedTable_.setOffset((StkFloat) 0.7);
reedTable_.setSlope((StkFloat) -0.3);
// Concatenate the STK rawwave path to the rawwave file
vibrato = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
vibrato->setFrequency((MY_FLOAT) 5.735);
outputGain = (MY_FLOAT) 1.0;
noiseGain = (MY_FLOAT) 0.2;
vibratoGain = (MY_FLOAT) 0.1;
vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
vibrato_->setFrequency((StkFloat) 5.735);
outputGain_ = (StkFloat) 1.0;
noiseGain_ = (StkFloat) 0.2;
vibratoGain_ = (StkFloat) 0.1;
}
Clarinet :: ~Clarinet()
{
delete delayLine;
delete reedTable;
delete filter;
delete envelope;
delete noise;
delete vibrato;
delete vibrato_;
}
void Clarinet :: clear()
{
delayLine->clear();
filter->tick((MY_FLOAT) 0.0);
delayLine_.clear();
filter_.tick((StkFloat) 0.0);
}
void Clarinet :: setFrequency(MY_FLOAT frequency)
void Clarinet :: setFrequency(StkFloat frequency)
{
MY_FLOAT freakency = frequency;
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "Clarinet: setFrequency parameter is less than or equal to zero!" << std::endl;
errorString_ << "Clarinet::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
}
// Delay = length - approximate filter delay.
MY_FLOAT delay = (Stk::sampleRate() / freakency) * 0.5 - 1.5;
StkFloat delay = (Stk::sampleRate() / freakency) * 0.5 - 1.5;
if (delay <= 0.0) delay = 0.3;
else if (delay > length) delay = length;
delayLine->setDelay(delay);
else if (delay > length_) delay = length_;
delayLine_.setDelay(delay);
}
void Clarinet :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate)
void Clarinet :: startBlowing(StkFloat amplitude, StkFloat rate)
{
envelope->setRate(rate);
envelope->setTarget(amplitude);
envelope_.setRate(rate);
envelope_.setTarget(amplitude);
}
void Clarinet :: stopBlowing(MY_FLOAT rate)
void Clarinet :: stopBlowing(StkFloat rate)
{
envelope->setRate(rate);
envelope->setTarget((MY_FLOAT) 0.0);
envelope_.setRate(rate);
envelope_.setTarget((StkFloat) 0.0);
}
void Clarinet :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Clarinet :: noteOn(StkFloat frequency, StkFloat amplitude)
{
this->setFrequency(frequency);
this->startBlowing((MY_FLOAT) 0.55 + (amplitude * (MY_FLOAT) 0.30), amplitude * (MY_FLOAT) 0.005);
outputGain = amplitude + (MY_FLOAT) 0.001;
this->startBlowing((StkFloat) 0.55 + (amplitude * (StkFloat) 0.30), amplitude * (StkFloat) 0.005);
outputGain_ = amplitude + (StkFloat) 0.001;
#if defined(_STK_DEBUG_)
std::cerr << "Clarinet: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Clarinet::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Clarinet :: noteOff(MY_FLOAT amplitude)
void Clarinet :: noteOff(StkFloat amplitude)
{
this->stopBlowing(amplitude * (MY_FLOAT) 0.01);
this->stopBlowing( amplitude * 0.01 );
#if defined(_STK_DEBUG_)
std::cerr << "Clarinet: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Clarinet::NoteOff: amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT Clarinet :: tick()
StkFloat Clarinet :: tick()
{
MY_FLOAT pressureDiff;
MY_FLOAT breathPressure;
StkFloat pressureDiff;
StkFloat breathPressure;
// Calculate the breath pressure (envelope + noise + vibrato)
breathPressure = envelope->tick();
breathPressure += breathPressure * noiseGain * noise->tick();
breathPressure += breathPressure * vibratoGain * vibrato->tick();
breathPressure = envelope_.tick();
breathPressure += breathPressure * noiseGain_ * noise_.tick();
breathPressure += breathPressure * vibratoGain_ * vibrato_->tick();
// Perform commuted loss filtering.
pressureDiff = -0.95 * filter->tick(delayLine->lastOut());
pressureDiff = -0.95 * filter_.tick(delayLine_.lastOut());
// Calculate pressure difference of reflected and mouthpiece pressures.
pressureDiff = pressureDiff - breathPressure;
// Perform non-linear scattering using pressure difference in reed function.
lastOutput = delayLine->tick(breathPressure + pressureDiff * reedTable->tick(pressureDiff));
lastOutput_ = delayLine_.tick(breathPressure + pressureDiff * reedTable_.tick(pressureDiff));
// Apply output gain.
lastOutput *= outputGain;
lastOutput_ *= outputGain_;
return lastOutput;
return lastOutput_;
}
void Clarinet :: controlChange(int number, MY_FLOAT value)
StkFloat *Clarinet :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Clarinet :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void Clarinet :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "Clarinet: Control value less than zero!" << std::endl;
errorString_ << "Clarinet::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "Clarinet: Control value greater than 128.0!" << std::endl;
errorString_ << "Clarinet::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_ReedStiffness_) // 2
reedTable->setSlope((MY_FLOAT) -0.44 + ( (MY_FLOAT) 0.26 * norm ));
reedTable_.setSlope((StkFloat) -0.44 + ( (StkFloat) 0.26 * norm ));
else if (number == __SK_NoiseLevel_) // 4
noiseGain = (norm * (MY_FLOAT) 0.4);
noiseGain_ = (norm * (StkFloat) 0.4);
else if (number == __SK_ModFrequency_) // 11
vibrato->setFrequency((norm * (MY_FLOAT) 12.0));
vibrato_->setFrequency((norm * (StkFloat) 12.0));
else if (number == __SK_ModWheel_) // 1
vibratoGain = (norm * (MY_FLOAT) 0.5);
vibratoGain_ = (norm * (StkFloat) 0.5);
else if (number == __SK_AfterTouch_Cont_) // 128
envelope->setValue(norm);
else
std::cerr << "Clarinet: Undefined Control Number (" << number << ")!!" << std::endl;
envelope_.setValue(norm);
else {
errorString_ << "Clarinet::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "Clarinet: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "Clarinet::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -14,40 +14,45 @@
used in fixed delay-length applications, such
as for reverberation.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Delay.h"
#include <iostream>
Delay :: Delay()
Delay :: Delay() : Filter()
{
// Default max delay length set to 4095.
length = 4096;
delete [] inputs;
inputs = new MY_FLOAT[length];
// Default maximum delay length set to 4095.
inputs_.resize( 4096 );
this->clear();
inPoint = 0;
outPoint = 0;
delay = 0;
inPoint_ = 0;
outPoint_ = 0;
delay_ = 0;
}
Delay :: Delay(long theDelay, long maxDelay)
Delay :: Delay(unsigned long delay, unsigned long maxDelay)
{
// Writing before reading allows delays from 0 to length-1.
// If we want to allow a delay of maxDelay, we need a
// delay-line of length = maxDelay+1.
length = maxDelay+1;
if ( maxDelay < 1 ) {
errorString_ << "Delay::Delay: maxDelay must be > 0!\n";
handleError( StkError::FUNCTION_ARGUMENT );
}
// We need to delete the previously allocated inputs.
delete [] inputs;
inputs = new MY_FLOAT[length];
this->clear();
if ( delay > maxDelay ) {
errorString_ << "Delay::Delay: maxDelay must be > than delay argument!\n";
handleError( StkError::FUNCTION_ARGUMENT );
}
inPoint = 0;
this->setDelay(theDelay);
if ( maxDelay > inputs_.size()-1 ) {
inputs_.resize( maxDelay+1 );
this->clear();
}
inPoint_ = 0;
this->setDelay( delay );
}
Delay :: ~Delay()
@@ -56,109 +61,135 @@ Delay :: ~Delay()
void Delay :: clear(void)
{
long i;
for (i=0;i<length;i++) inputs[i] = 0.0;
outputs[0] = 0.0;
for (unsigned int i=0; i<inputs_.size(); i++)
inputs_[i] = 0.0;
outputs_[0] = 0.0;
}
void Delay :: setDelay(long theDelay)
void Delay :: setMaximumDelay(unsigned long delay)
{
if (theDelay > length-1) { // The value is too big.
std::cerr << "Delay: setDelay(" << theDelay << ") too big!" << std::endl;
// Force delay to maxLength.
outPoint = inPoint + 1;
delay = length - 1;
if ( delay < inputs_.size() ) return;
if ( delay < 0 ) {
errorString_ << "Delay::setMaximumDelay: argument (" << delay << ") less than zero!\n";
handleError( StkError::WARNING );
return;
}
else if (theDelay < 0 ) {
std::cerr << "Delay: setDelay(" << theDelay << ") less than zero!" << std::endl;
outPoint = inPoint;
delay = 0;
}
else {
outPoint = inPoint - (long) theDelay; // read chases write
delay = theDelay;
else if (delay < delay_ ) {
errorString_ << "Delay::setMaximumDelay: argument (" << delay << ") less than current delay setting (" << delay_ << ")!\n";
handleError( StkError::WARNING );
return;
}
while (outPoint < 0) outPoint += length; // modulo maximum length
inputs_.resize( delay + 1 );
}
long Delay :: getDelay(void) const
void Delay :: setDelay(unsigned long delay)
{
return (long)delay;
if ( delay > inputs_.size() - 1 ) { // The value is too big.
errorString_ << "Delay::setDelay: argument (" << delay << ") too big ... setting to maximum!\n";
handleError( StkError::WARNING );
// Force delay to maximum length.
outPoint_ = inPoint_ + 1;
if ( outPoint_ == inputs_.size() ) outPoint_ = 0;
delay_ = inputs_.size() - 1;
}
else if ( delay < 0 ) {
errorString_ << "Delay::setDelay: argument (" << delay << ") less than zero ... setting to zero!\n";
handleError( StkError::WARNING );
outPoint_ = inPoint_;
delay_ = 0;
}
else { // read chases write
if ( inPoint_ >= delay ) outPoint_ = inPoint_ - delay;
else outPoint_ = inputs_.size() + inPoint_ - delay;
delay_ = delay;
}
}
MY_FLOAT Delay :: energy(void) const
unsigned long Delay :: getDelay(void) const
{
int i;
register MY_FLOAT e = 0;
if (inPoint >= outPoint) {
for (i=outPoint; i<inPoint; i++) {
register MY_FLOAT t = inputs[i];
return (unsigned long) delay_;
}
StkFloat Delay :: energy(void) const
{
unsigned long i;
register StkFloat e = 0;
if (inPoint_ >= outPoint_) {
for (i=outPoint_; i<inPoint_; i++) {
register StkFloat t = inputs_[i];
e += t*t;
}
} else {
for (i=outPoint; i<length; i++) {
register MY_FLOAT t = inputs[i];
for (i=outPoint_; i<inputs_.size(); i++) {
register StkFloat t = inputs_[i];
e += t*t;
}
for (i=0; i<inPoint; i++) {
register MY_FLOAT t = inputs[i];
for (i=0; i<inPoint_; i++) {
register StkFloat t = inputs_[i];
e += t*t;
}
}
return e;
}
MY_FLOAT Delay :: contentsAt(unsigned long tapDelay) const
StkFloat Delay :: contentsAt(unsigned long tapDelay)
{
long i = tapDelay;
unsigned long i = tapDelay;
if (i < 1) {
std::cerr << "Delay: contentsAt(" << tapDelay << ") too small!" << std::endl;
i = 1;
errorString_ << "Delay::contentsAt: argument (" << tapDelay << ") too small!";
handleError( StkError::WARNING );
return 0.0;
}
else if (i > delay) {
std::cerr << "Delay: contentsAt(" << tapDelay << ") too big!" << std::endl;
i = (long) delay;
else if (i > delay_) {
errorString_ << "Delay::contentsAt: argument (" << tapDelay << ") too big!";
handleError( StkError::WARNING );
return 0.0;
}
long tap = inPoint - i;
long tap = inPoint_ - i;
if (tap < 0) // Check for wraparound.
tap += length;
tap += inputs_.size();
return inputs[tap];
return inputs_[tap];
}
MY_FLOAT Delay :: lastOut(void) const
StkFloat Delay :: lastOut(void) const
{
return Filter::lastOut();
}
MY_FLOAT Delay :: nextOut(void) const
StkFloat Delay :: nextOut(void)
{
return inputs[outPoint];
return inputs_[outPoint_];
}
MY_FLOAT Delay :: tick(MY_FLOAT sample)
StkFloat Delay :: tick(StkFloat sample)
{
inputs[inPoint++] = sample;
inputs_[inPoint_++] = sample;
// Check for end condition
if (inPoint == length)
inPoint -= length;
if (inPoint_ == inputs_.size())
inPoint_ = 0;
// Read out next value
outputs[0] = inputs[outPoint++];
outputs_[0] = inputs_[outPoint_++];
if (outPoint>=length)
outPoint -= length;
if (outPoint_ == inputs_.size())
outPoint_ = 0;
return outputs[0];
return outputs_[0];
}
MY_FLOAT *Delay :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *Delay :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Filter::tick( vector, vectorSize );
}
StkFrames& Delay :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
}

View File

@@ -18,36 +18,41 @@
response, the minimum delay possible in this
implementation is limited to a value of 0.5.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "DelayA.h"
#include <iostream>
DelayA :: DelayA()
DelayA :: DelayA() : Delay()
{
this->setDelay( 0.5 );
apInput = 0.0;
doNextOut = true;
apInput_ = 0.0;
doNextOut_ = true;
}
DelayA :: DelayA(MY_FLOAT theDelay, long maxDelay)
DelayA :: DelayA(StkFloat delay, unsigned long maxDelay)
{
// Writing before reading allows delays from 0 to length-1.
length = maxDelay+1;
if ( delay < 0.0 || maxDelay < 1 ) {
errorString_ << "DelayA::DelayA: delay must be >= 0.0, maxDelay must be > 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( length > 4096 ) {
// We need to delete the previously allocated inputs.
delete [] inputs;
inputs = new MY_FLOAT[length];
if ( delay > (StkFloat) maxDelay ) {
errorString_ << "DelayA::DelayA: maxDelay must be > than delay argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
// Writing before reading allows delays from 0 to length-1.
if ( maxDelay > inputs_.size()-1 ) {
inputs_.resize( maxDelay+1 );
this->clear();
}
inPoint = 0;
this->setDelay(theDelay);
apInput = 0.0;
doNextOut = true;
inPoint_ = 0;
this->setDelay(delay);
apInput_ = 0.0;
doNextOut_ = true;
}
DelayA :: ~DelayA()
@@ -57,74 +62,90 @@ DelayA :: ~DelayA()
void DelayA :: clear()
{
Delay::clear();
apInput = 0.0;
apInput_ = 0.0;
}
void DelayA :: setDelay(MY_FLOAT theDelay)
void DelayA :: setDelay(StkFloat delay)
{
MY_FLOAT outPointer;
StkFloat outPointer;
unsigned long length = inputs_.size();
if ( delay > inputs_.size() - 1 ) { // The value is too big.
errorString_ << "DelayA::setDelay: argument (" << delay << ") too big ... setting to maximum!";
handleError( StkError::WARNING );
if (theDelay > length-1) {
std::cerr << "DelayA: setDelay(" << theDelay << ") too big!" << std::endl;
// Force delay to maxLength
outPointer = inPoint + 1.0;
delay = length - 1;
outPointer = inPoint_ + 1.0;
delay_ = length - 1;
}
else if (theDelay < 0.5) {
std::cerr << "DelayA: setDelay(" << theDelay << ") less than 0.5 not possible!" << std::endl;
outPointer = inPoint + 0.4999999999;
delay = 0.5;
else if (delay < 0.5) {
errorString_ << "DelayA::setDelay: argument (" << delay << ") less than 0.5 not possible!";
handleError( StkError::WARNING );
outPointer = inPoint_ + 0.4999999999;
delay_ = 0.5;
}
else {
outPointer = inPoint - theDelay + 1.0; // outPoint chases inpoint
delay = theDelay;
outPointer = inPoint_ - delay + 1.0; // outPoint chases inpoint
delay_ = delay;
}
if (outPointer < 0)
outPointer += length; // modulo maximum length
outPoint = (long) outPointer; // integer part
alpha = 1.0 + outPoint - outPointer; // fractional part
outPoint_ = (long) outPointer; // integer part
if ( outPoint_ == length ) outPoint_ = 0;
alpha_ = 1.0 + outPoint_ - outPointer; // fractional part
if (alpha < 0.5) {
if (alpha_ < 0.5) {
// The optimal range for alpha is about 0.5 - 1.5 in order to
// achieve the flattest phase delay response.
outPoint += 1;
if (outPoint >= length) outPoint -= length;
alpha += (MY_FLOAT) 1.0;
outPoint_ += 1;
if (outPoint_ >= length) outPoint_ -= length;
alpha_ += (StkFloat) 1.0;
}
coeff = ((MY_FLOAT) 1.0 - alpha) /
((MY_FLOAT) 1.0 + alpha); // coefficient for all pass
coeff_ = ((StkFloat) 1.0 - alpha_) /
((StkFloat) 1.0 + alpha_); // coefficient for all pass
}
MY_FLOAT DelayA :: nextOut(void)
StkFloat DelayA :: nextOut(void)
{
if ( doNextOut ) {
if ( doNextOut_ ) {
// Do allpass interpolation delay.
nextOutput = -coeff * outputs[0];
nextOutput += apInput + (coeff * inputs[outPoint]);
doNextOut = false;
nextOutput_ = -coeff_ * outputs_[0];
nextOutput_ += apInput_ + (coeff_ * inputs_[outPoint_]);
doNextOut_ = false;
}
return nextOutput;
return nextOutput_;
}
MY_FLOAT DelayA :: tick(MY_FLOAT sample)
StkFloat DelayA :: tick(StkFloat sample)
{
inputs[inPoint++] = sample;
inputs_[inPoint_++] = sample;
// Increment input pointer modulo length.
if (inPoint == length)
inPoint -= length;
if (inPoint_ == inputs_.size())
inPoint_ = 0;
outputs[0] = nextOut();
doNextOut = true;
outputs_[0] = nextOut();
doNextOut_ = true;
// Save the allpass input and increment modulo length.
apInput = inputs[outPoint++];
if (outPoint == length)
outPoint -= length;
apInput_ = inputs_[outPoint_++];
if (outPoint_ == inputs_.size())
outPoint_ = 0;
return outputs[0];
return outputs_[0];
}
StkFloat *DelayA :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Filter::tick( vector, vectorSize );
}
StkFrames& DelayA :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
}

View File

@@ -18,102 +18,122 @@
order Lagrange interpolators can typically
improve (minimize) this attenuation characteristic.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "DelayL.h"
#include <iostream>
DelayL :: DelayL()
DelayL :: DelayL() : Delay()
{
doNextOut = true;
doNextOut_ = true;
}
DelayL :: DelayL(MY_FLOAT theDelay, long maxDelay)
DelayL :: DelayL(StkFloat delay, unsigned long maxDelay)
{
// Writing before reading allows delays from 0 to length-1.
length = maxDelay+1;
if ( delay < 0.0 || maxDelay < 1 ) {
errorString_ << "DelayL::DelayL: delay must be >= 0.0, maxDelay must be > 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( length > 4096 ) {
// We need to delete the previously allocated inputs.
delete [] inputs;
inputs = new MY_FLOAT[length];
if ( delay > (StkFloat) maxDelay ) {
errorString_ << "DelayL::DelayL: maxDelay must be > than delay argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
// Writing before reading allows delays from 0 to length-1.
if ( maxDelay > inputs_.size()-1 ) {
inputs_.resize( maxDelay+1 );
this->clear();
}
inPoint = 0;
this->setDelay(theDelay);
doNextOut = true;
inPoint_ = 0;
this->setDelay(delay);
doNextOut_ = true;
}
DelayL :: ~DelayL()
{
}
void DelayL :: setDelay(MY_FLOAT theDelay)
void DelayL :: setDelay(StkFloat delay)
{
MY_FLOAT outPointer;
StkFloat outPointer;
if ( delay > inputs_.size() - 1 ) { // The value is too big.
errorString_ << "DelayL::setDelay: argument (" << delay << ") too big ... setting to maximum!";
handleError( StkError::WARNING );
if (theDelay > length-1) {
std::cerr << "DelayL: setDelay(" << theDelay << ") too big!" << std::endl;
// Force delay to maxLength
outPointer = inPoint + 1.0;
delay = length - 1;
outPointer = inPoint_ + 1.0;
delay_ = inputs_.size() - 1;
}
else if (theDelay < 0 ) {
std::cerr << "DelayL: setDelay(" << theDelay << ") less than zero!" << std::endl;
outPointer = inPoint;
delay = 0;
else if (delay < 0 ) {
errorString_ << "DelayL::setDelay: argument (" << delay << ") less than zero ... setting to zero!";
handleError( StkError::WARNING );
outPointer = inPoint_;
delay_ = 0;
}
else {
outPointer = inPoint - theDelay; // read chases write
delay = theDelay;
outPointer = inPoint_ - delay; // read chases write
delay_ = delay;
}
while (outPointer < 0)
outPointer += length; // modulo maximum length
outPointer += inputs_.size(); // modulo maximum length
outPoint = (long) outPointer; // integer part
alpha = outPointer - outPoint; // fractional part
omAlpha = (MY_FLOAT) 1.0 - alpha;
outPoint_ = (long) outPointer; // integer part
if ( outPoint_ == inputs_.size() ) outPoint_ = 0;
alpha_ = outPointer - outPoint_; // fractional part
omAlpha_ = (StkFloat) 1.0 - alpha_;
}
MY_FLOAT DelayL :: getDelay(void) const
StkFloat DelayL :: getDelay(void) const
{
return delay;
return delay_;
}
MY_FLOAT DelayL :: nextOut(void)
StkFloat DelayL :: nextOut(void)
{
if ( doNextOut ) {
if ( doNextOut_ ) {
// First 1/2 of interpolation
nextOutput = inputs[outPoint] * omAlpha;
nextOutput_ = inputs_[outPoint_] * omAlpha_;
// Second 1/2 of interpolation
if (outPoint+1 < length)
nextOutput += inputs[outPoint+1] * alpha;
if (outPoint_+1 < inputs_.size())
nextOutput_ += inputs_[outPoint_+1] * alpha_;
else
nextOutput += inputs[0] * alpha;
doNextOut = false;
nextOutput_ += inputs_[0] * alpha_;
doNextOut_ = false;
}
return nextOutput;
return nextOutput_;
}
MY_FLOAT DelayL :: tick(MY_FLOAT sample)
StkFloat DelayL :: tick(StkFloat sample)
{
inputs[inPoint++] = sample;
inputs_[inPoint_++] = sample;
// Increment input pointer modulo length.
if (inPoint == length)
inPoint -= length;
if (inPoint_ == inputs_.size())
inPoint_ = 0;
outputs[0] = nextOut();
doNextOut = true;
outputs_[0] = nextOut();
doNextOut_ = true;
// Increment output pointer modulo length.
if (++outPoint >= length)
outPoint -= length;
if (++outPoint_ == inputs_.size())
outPoint_ = 0;
return outputs[0];
return outputs_[0];
}
StkFloat *DelayL :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Filter::tick( vector, vectorSize );
}
StkFrames& DelayL :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
}

View File

@@ -11,14 +11,14 @@
of simultaneous voices) via a #define in the
Drummer.h.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Drummer.h"
#include <math.h>
// Not really General MIDI yet. Coming soon.
// Not really General MIDI yet.
unsigned char genMIDIMap[128] =
{ 0,0,0,0,0,0,0,0, // 0-7
0,0,0,0,0,0,0,0, // 8-15
@@ -55,122 +55,133 @@ char waveNames[DRUM_NUMWAVES][16] =
Drummer :: Drummer() : Instrmnt()
{
for (int i=0; i<DRUM_POLYPHONY; i++) {
filters[i] = new OnePole;
sounding[i] = -1;
for ( int i=0; i<DRUM_POLYPHONY; i++ ) {
filters_[i] = new OnePole;
sounding_[i] = -1;
}
// This counts the number of sounding voices.
nSounding = 0;
nSounding_ = 0;
}
Drummer :: ~Drummer()
{
int i;
for ( i=0; i<nSounding-1; i++ ) delete waves[i];
for ( i=0; i<DRUM_POLYPHONY; i++ ) delete filters[i];
for ( i=0; i<nSounding_; i++ ) delete waves_[i];
for ( i=0; i<DRUM_POLYPHONY; i++ ) delete filters_[i];
}
void Drummer :: noteOn(MY_FLOAT instrument, MY_FLOAT amplitude)
void Drummer :: noteOn(StkFloat instrument, StkFloat amplitude)
{
#if defined(_STK_DEBUG_)
std::cerr << "Drummer: NoteOn instrument = " << instrument << ", amplitude = " << amplitude << std::endl;
errorString_ << "Drummer::NoteOn: instrument = " << instrument << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
MY_FLOAT gain = amplitude;
StkFloat gain = amplitude;
if ( amplitude > 1.0 ) {
std::cerr << "Drummer: noteOn amplitude parameter is greater than 1.0!" << std::endl;
errorString_ << "Drummer::noteOn: amplitude parameter is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
gain = 1.0;
}
else if ( amplitude < 0.0 ) {
std::cerr << "Drummer: noteOn amplitude parameter is less than 0.0!" << std::endl;
errorString_ << "Drummer::noteOn: amplitude parameter is less than 0.0 ... doing nothing!";
handleError( StkError::WARNING );
return;
}
// Yes, this is tres kludgey.
int noteNum = (int) ((12*log(instrument/220.0)/log(2.0)) + 57.01);
int noteNum = (int) ( ( 12*log(instrument/220.0)/log(2.0) ) + 57.01 );
// Check first to see if there's already one like this sounding.
int i, waveIndex = -1;
for (i=0; i<DRUM_POLYPHONY; i++) {
if (sounding[i] == noteNum) waveIndex = i;
for ( i=0; i<DRUM_POLYPHONY; i++ ) {
if (sounding_[i] == noteNum) waveIndex = i;
}
if ( waveIndex >= 0 ) {
// Reset this sound.
waves[waveIndex]->reset();
filters[waveIndex]->setPole((MY_FLOAT) 0.999 - (gain * 0.6));
filters[waveIndex]->setGain(gain);
waves_[waveIndex]->reset();
filters_[waveIndex]->setPole( 0.999 - (gain * 0.6) );
filters_[waveIndex]->setGain( gain );
}
else {
if (nSounding == DRUM_POLYPHONY) {
if (nSounding_ == DRUM_POLYPHONY) {
// If we're already at maximum polyphony, then preempt the oldest voice.
delete waves[0];
filters[0]->clear();
WvIn *tempWv = waves[0];
OnePole *tempFilt = filters[0];
delete waves_[0];
filters_[0]->clear();
OnePole *tempFilt = filters_[0];
// Re-order the list.
for (i=0; i<DRUM_POLYPHONY-1; i++) {
waves[i] = waves[i+1];
filters[i] = filters[i+1];
for ( i=0; i<DRUM_POLYPHONY-1; i++ ) {
waves_[i] = waves_[i+1];
filters_[i] = filters_[i+1];
}
waves[DRUM_POLYPHONY-1] = tempWv;
filters[DRUM_POLYPHONY-1] = tempFilt;
waves_[DRUM_POLYPHONY-1] = 0;
filters_[DRUM_POLYPHONY-1] = tempFilt;
}
else
nSounding += 1;
nSounding_ += 1;
sounding[nSounding-1] = noteNum;
sounding_[nSounding_-1] = noteNum;
// Concatenate the STK rawwave path to the rawwave file
waves[nSounding-1] = new WvIn( (Stk::rawwavePath() + waveNames[genMIDIMap[noteNum]]).c_str(), TRUE );
waves_[nSounding_-1] = new WvIn( (Stk::rawwavePath() + waveNames[genMIDIMap[noteNum]]).c_str(), true );
if (Stk::sampleRate() != 22050.0)
waves[nSounding-1]->setRate( 22050.0 / Stk::sampleRate() );
filters[nSounding-1]->setPole((MY_FLOAT) 0.999 - (gain * 0.6) );
filters[nSounding-1]->setGain( gain );
waves_[nSounding_-1]->setRate( 22050.0 / Stk::sampleRate() );
filters_[nSounding_-1]->setPole( 0.999 - (gain * 0.6) );
filters_[nSounding_-1]->setGain( gain );
}
#if defined(_STK_DEBUG_)
std::cerr << "Number Sounding = " << nSounding << std::endl;
for (i=0; i<nSounding; i++) std::cerr << sounding[i] << " ";
std::cerr << "\n";
errorString_ << "Drummer::noteOn: number sounding = " << nSounding_ << '\n';
for (i=0; i<nSounding_; i++) errorString_ << sounding_[i] << " ";
errorString_ << '\n';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Drummer :: noteOff(MY_FLOAT amplitude)
void Drummer :: noteOff(StkFloat amplitude)
{
// Set all sounding wave filter gains low.
int i = 0;
while(i < nSounding) {
filters[i++]->setGain( amplitude * 0.01 );
}
while ( i < nSounding_ ) filters_[i++]->setGain( amplitude * 0.01 );
}
MY_FLOAT Drummer :: tick()
StkFloat Drummer :: tick()
{
MY_FLOAT output = 0.0;
OnePole *tempFilt;
int j, i = 0;
while (i < nSounding) {
if ( waves[i]->isFinished() ) {
delete waves[i];
tempFilt = filters[i];
lastOutput_ = 0.0;
while (i < nSounding_) {
if ( waves_[i]->isFinished() ) {
delete waves_[i];
tempFilt = filters_[i];
// Re-order the list.
for (j=i; j<nSounding-1; j++) {
sounding[j] = sounding[j+1];
waves[j] = waves[j+1];
filters[j] = filters[j+1];
for ( j=i; j<nSounding_-1; j++ ) {
sounding_[j] = sounding_[j+1];
waves_[j] = waves_[j+1];
filters_[j] = filters_[j+1];
}
filters[j] = tempFilt;
filters[j]->clear();
sounding[j] = -1;
nSounding -= 1;
filters_[j] = tempFilt;
filters_[j]->clear();
sounding_[j] = -1;
nSounding_ -= 1;
i -= 1;
}
else
output += filters[i]->tick( waves[i]->tick() );
lastOutput_ += filters_[i]->tick( waves_[i]->tick() );
i++;
}
return output;
return lastOutput_;
}
StkFloat *Drummer :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Drummer :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

View File

@@ -2,78 +2,72 @@
/*! \class Echo
\brief STK echo effect class.
This class implements a echo effect.
This class implements an echo effect.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Echo.h"
#include <iostream>
Echo :: Echo(MY_FLOAT longestDelay)
Echo :: Echo( unsigned long maximumDelay ) : Effect()
{
length = (long) longestDelay + 2;
delayLine = new Delay(length>>1, length);
effectMix = 0.5;
this->setMaximumDelay( maximumDelay );
delayLine_.setDelay( length_ >> 1 );
effectMix_ = 0.5;
this->clear();
}
Echo :: ~Echo()
{
delete delayLine;
}
void Echo :: clear()
{
delayLine->clear();
lastOutput = 0.0;
delayLine_.clear();
lastOutput_[0] = 0.0;
lastOutput_[1] = 0.0;
}
void Echo :: setDelay(MY_FLOAT delay)
void Echo :: setMaximumDelay( unsigned long delay )
{
MY_FLOAT size = delay;
if ( delay < 0.0 ) {
std::cerr << "Echo: setDelay parameter is less than zero!" << std::endl;
size = 0.0;
}
else if ( delay > length ) {
std::cerr << "Echo: setDelay parameter is greater than delay length!" << std::endl;
size = length;
length_ = delay;
if ( delay == 0 ) {
errorString_ << "Echo::setMaximumDelay: parameter cannot be zero ... setting to 10!";
handleError( StkError::WARNING );
length_ = 10;
}
delayLine->setDelay((long)size);
delayLine_.setMaximumDelay( length_ );
}
void Echo :: setEffectMix(MY_FLOAT mix)
void Echo :: setDelay( unsigned long delay )
{
effectMix = mix;
if ( mix < 0.0 ) {
std::cerr << "Echo: setEffectMix parameter is less than zero!" << std::endl;
effectMix = 0.0;
}
else if ( mix > 1.0 ) {
std::cerr << "Echo: setEffectMix parameter is greater than 1.0!" << std::endl;
effectMix = 1.0;
unsigned long size = delay;
if ( delay > length_ ) {
errorString_ << "Echo::setDelay: parameter is greater than maximum delay length ... setting to max!";
handleError( StkError::WARNING );
size = length_;
}
delayLine_.setDelay( size );
}
MY_FLOAT Echo :: lastOut() const
StkFloat Echo :: tick(StkFloat input)
{
return lastOutput;
lastOutput_[0] = effectMix_ * delayLine_.tick(input);
lastOutput_[0] += input * (1.0 - effectMix_);
lastOutput_[1] = lastOutput_[0];
return lastOutput_[0];
}
MY_FLOAT Echo :: tick(MY_FLOAT input)
StkFloat *Echo :: tick(StkFloat *vector, unsigned int vectorSize)
{
lastOutput = effectMix * delayLine->tick(input);
lastOutput += input * (1.0 - effectMix);
return lastOutput;
return Effect::tick( vector, vectorSize );
}
MY_FLOAT *Echo :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFrames& Echo :: tick( StkFrames& frames, unsigned int channel )
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Effect::tick( frames, channel );
}

99
src/Effect.cpp Normal file
View File

@@ -0,0 +1,99 @@
/***************************************************/
/*! \class Effect
\brief STK abstract effects parent class.
This class provides common functionality for
STK effects subclasses.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Effect.h"
#include <math.h>
Effect :: Effect()
{
}
Effect :: ~Effect()
{
}
void Effect :: setEffectMix(StkFloat mix)
{
if ( mix < 0.0 ) {
errorString_ << "Effect::setEffectMix: mix parameter is less than zero ... setting to zero!";
handleError( StkError::WARNING );
effectMix_ = 0.0;
}
else if ( mix > 1.0 ) {
errorString_ << "Effect::setEffectMix: mix parameter is greater than 1.0 ... setting to one!";
handleError( StkError::WARNING );
effectMix_ = 1.0;
}
else
effectMix_ = mix;
}
StkFloat Effect :: lastOut() const
{
return (lastOutput_[0] + lastOutput_[1]) * 0.5;
}
StkFloat Effect :: lastOutLeft() const
{
return lastOutput_[0];
}
StkFloat Effect :: lastOutRight() const
{
return lastOutput_[1];
}
StkFloat *Effect :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
}
StkFrames& Effect :: tick( StkFrames& frames, unsigned int channel )
{
if ( channel == 0 || frames.channels() < channel ) {
errorString_ << "Effect::tick(): channel argument (" << channel << ") is zero or > channels in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( frames.channels() == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[i] = tick( frames[i] );
}
else if ( frames.interleaved() ) {
unsigned int hop = frames.channels();
unsigned int index = channel - 1;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
frames[index] = tick( frames[index] );
index += hop;
}
}
else {
unsigned int iStart = (channel - 1) * frames.frames();
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[iStart + i] = tick( frames[iStart + i] );
}
return frames;
}
bool Effect :: isPrime(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
}

View File

@@ -9,19 +9,18 @@
\e keyOff messages, ramping to 1.0 on
keyOn and to 0.0 on keyOff.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Envelope.h"
#include <stdio.h>
Envelope :: Envelope(void) : Stk()
Envelope :: Envelope(void) : Generator()
{
target = (MY_FLOAT) 0.0;
value = (MY_FLOAT) 0.0;
rate = (MY_FLOAT) 0.001;
state = 0;
target_ = 0.0;
value_ = 0.0;
rate_ = 0.001;
state_ = 0;
}
Envelope :: ~Envelope(void)
@@ -30,85 +29,85 @@ Envelope :: ~Envelope(void)
void Envelope :: keyOn(void)
{
target = (MY_FLOAT) 1.0;
if (value != target) state = 1;
target_ = 1.0;
if (value_ != target_) state_ = 1;
}
void Envelope :: keyOff(void)
{
target = (MY_FLOAT) 0.0;
if (value != target) state = 1;
target_ = 0.0;
if (value_ != target_) state_ = 1;
}
void Envelope :: setRate(MY_FLOAT aRate)
void Envelope :: setRate(StkFloat rate)
{
if (aRate < 0.0) {
printf("Envelope: negative rates not allowed ... correcting!\n");
rate = -aRate;
if (rate < 0.0) {
errorString_ << "Envelope::setRate: negative rates not allowed ... correcting!";
handleError( StkError::WARNING );
rate_ = -rate;
}
else
rate = aRate;
rate_ = rate;
}
void Envelope :: setTime(MY_FLOAT aTime)
void Envelope :: setTime(StkFloat time)
{
if (aTime < 0.0) {
printf("Envelope: negative times not allowed ... correcting!\n");
rate = 1.0 / (-aTime * Stk::sampleRate());
if (time < 0.0) {
errorString_ << "Envelope::setTime: negative times not allowed ... correcting!";
handleError( StkError::WARNING );
rate_ = 1.0 / (-time * Stk::sampleRate());
}
else
rate = 1.0 / (aTime * Stk::sampleRate());
rate_ = 1.0 / (time * Stk::sampleRate());
}
void Envelope :: setTarget(MY_FLOAT aTarget)
void Envelope :: setTarget(StkFloat target)
{
target = aTarget;
if (value != target) state = 1;
target_ = target;
if (value_ != target_) state_ = 1;
}
void Envelope :: setValue(MY_FLOAT aValue)
void Envelope :: setValue(StkFloat value)
{
state = 0;
target = aValue;
value = aValue;
state_ = 0;
target_ = value;
value_ = value;
}
int Envelope :: getState(void) const
{
return state;
return state_;
}
MY_FLOAT Envelope :: tick(void)
StkFloat Envelope :: tick(void)
{
if (state) {
if (target > value) {
value += rate;
if (value >= target) {
value = target;
state = 0;
if (state_) {
if (target_ > value_) {
value_ += rate_;
if (value_ >= target_) {
value_ = target_;
state_ = 0;
}
}
else {
value -= rate;
if (value <= target) {
value = target;
state = 0;
value_ -= rate_;
if (value_ <= target_) {
value_ = target_;
state_ = 0;
}
}
}
return value;
lastOutput_ = value_;
return value_;
}
MY_FLOAT *Envelope :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *Envelope :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick();
return vector;
return Generator::tick( vector, vectorSize );
}
MY_FLOAT Envelope :: lastOut(void) const
StkFrames& Envelope :: tick( StkFrames& frames, unsigned int channel )
{
return value;
return Generator::tick( frames, channel );
}

View File

@@ -19,200 +19,200 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "FM.h"
#include "SKINI.msg"
#include <stdlib.h>
FM :: FM(int operators)
: nOperators(operators)
FM :: FM( unsigned int operators )
: nOperators_(operators)
{
if ( nOperators <= 0 ) {
char msg[256];
sprintf(msg, "FM: Invalid number of operators (%d) argument to constructor!", operators);
handleError(msg, StkError::FUNCTION_ARGUMENT);
if ( nOperators_ == 0 ) {
errorString_ << "FM: Invalid number of operators (" << operators << ") argument to constructor!";
handleError( StkError::FUNCTION_ARGUMENT );
}
twozero = new TwoZero();
twozero->setB2( -1.0 );
twozero->setGain( 0.0 );
twozero_.setB2( -1.0 );
twozero_.setGain( 0.0 );
// Concatenate the STK rawwave path to the rawwave file
vibrato = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
vibrato->setFrequency(6.0);
vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
vibrato_->setFrequency( 6.0 );
int i;
ratios = (MY_FLOAT *) new MY_FLOAT[nOperators];
gains = (MY_FLOAT *) new MY_FLOAT[nOperators];
adsr = (ADSR **) calloc( nOperators, sizeof(ADSR *) );
waves = (WaveLoop **) calloc( nOperators, sizeof(WaveLoop *) );
for (i=0; i<nOperators; i++ ) {
ratios[i] = 1.0;
gains[i] = 1.0;
adsr[i] = new ADSR();
unsigned int j;
adsr_.resize( nOperators_ );
waves_.resize( nOperators_ );
for (j=0; j<nOperators_; j++ ) {
ratios_.push_back( 1.0 );
gains_.push_back( 1.0 );
adsr_[j] = new ADSR();
}
modDepth = (MY_FLOAT) 0.0;
control1 = (MY_FLOAT) 1.0;
control2 = (MY_FLOAT) 1.0;
baseFrequency = (MY_FLOAT) 440.0;
modDepth_ = 0.0;
control1_ = 1.0;
control2_ = 1.0;
baseFrequency_ = 440.0;
MY_FLOAT temp = 1.0;
int i;
StkFloat temp = 1.0;
for (i=99; i>=0; i--) {
__FM_gains[i] = temp;
fmGains_[i] = temp;
temp *= 0.933033;
}
temp = 1.0;
for (i=15; i>=0; i--) {
__FM_susLevels[i] = temp;
fmSusLevels_[i] = temp;
temp *= 0.707101;
}
temp = 8.498186;
for (i=0; i<32; i++) {
__FM_attTimes[i] = temp;
fmAttTimes_[i] = temp;
temp *= 0.707101;
}
}
FM :: ~FM()
{
delete vibrato;
delete twozero;
delete vibrato_;
delete [] ratios;
delete [] gains;
for (int i=0; i<nOperators; i++ ) {
delete adsr[i];
delete waves[i];
for (unsigned int i=0; i<nOperators_; i++ ) {
delete waves_[i];
delete adsr_[i];
}
free(adsr);
free(waves);
}
void FM :: loadWaves(const char **filenames )
{
for (int i=0; i<nOperators; i++ )
waves[i] = new WaveLoop( filenames[i], TRUE );
for (unsigned int i=0; i<nOperators_; i++ )
waves_[i] = new WaveLoop( filenames[i], true );
}
void FM :: setFrequency(MY_FLOAT frequency)
void FM :: setFrequency(StkFloat frequency)
{
baseFrequency = frequency;
baseFrequency_ = frequency;
for (int i=0; i<nOperators; i++ )
waves[i]->setFrequency( baseFrequency * ratios[i] );
for (unsigned int i=0; i<nOperators_; i++ )
waves_[i]->setFrequency( baseFrequency_ * ratios_[i] );
}
void FM :: setRatio(int waveIndex, MY_FLOAT ratio)
void FM :: setRatio(unsigned int waveIndex, StkFloat ratio)
{
if ( waveIndex < 0 ) {
std::cerr << "FM: setRatio waveIndex parameter is less than zero!" << std::endl;
errorString_ << "FM::setRatio: waveIndex parameter is less than zero!";
handleError( StkError::WARNING );
return;
}
else if ( waveIndex >= nOperators ) {
std::cerr << "FM: setRatio waveIndex parameter is greater than the number of operators!" << std::endl;
else if ( waveIndex >= nOperators_ ) {
errorString_ << "FM:setRatio: waveIndex parameter is greater than the number of operators!";
handleError( StkError::WARNING );
return;
}
ratios[waveIndex] = ratio;
ratios_[waveIndex] = ratio;
if (ratio > 0.0)
waves[waveIndex]->setFrequency(baseFrequency * ratio);
waves_[waveIndex]->setFrequency( baseFrequency_ * ratio );
else
waves[waveIndex]->setFrequency(ratio);
waves_[waveIndex]->setFrequency( ratio );
}
void FM :: setGain(int waveIndex, MY_FLOAT gain)
void FM :: setGain(unsigned int waveIndex, StkFloat gain)
{
if ( waveIndex < 0 ) {
std::cerr << "FM: setGain waveIndex parameter is less than zero!" << std::endl;
errorString_ << "FM::setGain: waveIndex parameter is less than zero!";
handleError( StkError::WARNING );
return;
}
else if ( waveIndex >= nOperators ) {
std::cerr << "FM: setGain waveIndex parameter is greater than the number of operators!" << std::endl;
else if ( waveIndex >= nOperators_ ) {
errorString_ << "FM::setGain: waveIndex parameter is greater than the number of operators!";
handleError( StkError::WARNING );
return;
}
gains[waveIndex] = gain;
gains_[waveIndex] = gain;
}
void FM :: setModulationSpeed(MY_FLOAT mSpeed)
void FM :: setModulationSpeed(StkFloat mSpeed)
{
vibrato->setFrequency(mSpeed);
vibrato_->setFrequency( mSpeed );
}
void FM :: setModulationDepth(MY_FLOAT mDepth)
void FM :: setModulationDepth(StkFloat mDepth)
{
modDepth = mDepth;
modDepth_ = mDepth;
}
void FM :: setControl1(MY_FLOAT cVal)
void FM :: setControl1(StkFloat cVal)
{
control1 = cVal * (MY_FLOAT) 2.0;
control1_ = cVal * 2.0;
}
void FM :: setControl2(MY_FLOAT cVal)
void FM :: setControl2(StkFloat cVal)
{
control2 = cVal * (MY_FLOAT) 2.0;
control2_ = cVal * 2.0;
}
void FM :: keyOn()
{
for (int i=0; i<nOperators; i++ )
adsr[i]->keyOn();
for (unsigned int i=0; i<nOperators_; i++ )
adsr_[i]->keyOn();
}
void FM :: keyOff()
{
for (int i=0; i<nOperators; i++ )
adsr[i]->keyOff();
for (unsigned int i=0; i<nOperators_; i++ )
adsr_[i]->keyOff();
}
void FM :: noteOff(MY_FLOAT amplitude)
void FM :: noteOff(StkFloat amplitude)
{
keyOff();
this->keyOff();
#if defined(_STK_DEBUG_)
std::cerr << "FM: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "FM::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void FM :: controlChange(int number, MY_FLOAT value)
void FM :: controlChange(int number, StkFloat value)
{
MY_FLOAT norm = value * ONE_OVER_128;
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "FM: Control value less than zero!" << std::endl;
errorString_ << "FM::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "FM: Control value greater than 128.0!" << std::endl;
errorString_ << "FM::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_Breath_) // 2
setControl1( norm );
this->setControl1( norm );
else if (number == __SK_FootControl_) // 4
setControl2( norm );
this->setControl2( norm );
else if (number == __SK_ModFrequency_) // 11
setModulationSpeed( norm * 12.0);
this->setModulationSpeed( norm * 12.0);
else if (number == __SK_ModWheel_) // 1
setModulationDepth( norm );
this->setModulationDepth( norm );
else if (number == __SK_AfterTouch_Cont_) { // 128
//adsr[0]->setTarget( norm );
adsr[1]->setTarget( norm );
//adsr[2]->setTarget( norm );
adsr[3]->setTarget( norm );
//adsr_[0]->setTarget( norm );
adsr_[1]->setTarget( norm );
//adsr_[2]->setTarget( norm );
adsr_[3]->setTarget( norm );
}
else {
errorString_ << "FM::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
else
std::cerr << "FM: Undefined Control Number (" << number << ")!!" << std::endl;
#if defined(_STK_DEBUG_)
std::cerr << "FM: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "FM::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -38,146 +38,163 @@ FMVoices :: FMVoices()
: FM()
{
// Concatenate the STK rawwave path to the rawwave files
for ( int i=0; i<3; i++ )
waves[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
waves[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), TRUE );
for ( unsigned int i=0; i<3; i++ )
waves_[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
waves_[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true );
this->setRatio(0, 2.00);
this->setRatio(1, 4.00);
this->setRatio(2, 12.0);
this->setRatio(3, 1.00);
gains[3] = __FM_gains[80];
gains_[3] = fmGains_[80];
adsr[0]->setAllTimes( 0.05, 0.05, __FM_susLevels[15], 0.05);
adsr[1]->setAllTimes( 0.05, 0.05, __FM_susLevels[15], 0.05);
adsr[2]->setAllTimes( 0.05, 0.05, __FM_susLevels[15], 0.05);
adsr[3]->setAllTimes( 0.01, 0.01, __FM_susLevels[15], 0.5);
adsr_[0]->setAllTimes( 0.05, 0.05, fmSusLevels_[15], 0.05);
adsr_[1]->setAllTimes( 0.05, 0.05, fmSusLevels_[15], 0.05);
adsr_[2]->setAllTimes( 0.05, 0.05, fmSusLevels_[15], 0.05);
adsr_[3]->setAllTimes( 0.01, 0.01, fmSusLevels_[15], 0.5);
twozero->setGain( 0.0 );
modDepth = (MY_FLOAT) 0.005;
currentVowel = 0;
tilt[0] = 1.0;
tilt[1] = 0.5;
tilt[2] = 0.2;
mods[0] = 1.0;
mods[1] = 1.1;
mods[2] = 1.1;
baseFrequency = 110.0;
setFrequency( 110.0 );
twozero_.setGain( 0.0 );
modDepth_ = (StkFloat) 0.005;
currentVowel_ = 0;
tilt_[0] = 1.0;
tilt_[1] = 0.5;
tilt_[2] = 0.2;
mods_[0] = 1.0;
mods_[1] = 1.1;
mods_[2] = 1.1;
baseFrequency_ = 110.0;
this->setFrequency( 110.0 );
}
FMVoices :: ~FMVoices()
{
}
void FMVoices :: setFrequency(MY_FLOAT frequency)
void FMVoices :: setFrequency(StkFloat frequency)
{
MY_FLOAT temp, temp2 = 0.0;
StkFloat temp, temp2 = 0.0;
int tempi = 0;
unsigned int i = 0;
if (currentVowel < 32) {
i = currentVowel;
temp2 = (MY_FLOAT) 0.9;
if (currentVowel_ < 32) {
i = currentVowel_;
temp2 = 0.9;
}
else if (currentVowel < 64) {
i = currentVowel - 32;
temp2 = (MY_FLOAT) 1.0;
else if (currentVowel_ < 64) {
i = currentVowel_ - 32;
temp2 = 1.0;
}
else if (currentVowel < 96) {
i = currentVowel - 64;
temp2 = (MY_FLOAT) 1.1;
else if (currentVowel_ < 96) {
i = currentVowel_ - 64;
temp2 = 1.1;
}
else if (currentVowel <= 128) {
i = currentVowel - 96;
temp2 = (MY_FLOAT) 1.2;
else if (currentVowel_ <= 128) {
i = currentVowel_ - 96;
temp2 = 1.2;
}
baseFrequency = frequency;
temp = (temp2 * Phonemes::formantFrequency(i, 0) / baseFrequency) + 0.5;
baseFrequency_ = frequency;
temp = (temp2 * Phonemes::formantFrequency(i, 0) / baseFrequency_) + 0.5;
tempi = (int) temp;
this->setRatio(0,(MY_FLOAT) tempi);
temp = (temp2 * Phonemes::formantFrequency(i, 1) / baseFrequency) + 0.5;
this->setRatio( 0, (StkFloat) tempi );
temp = (temp2 * Phonemes::formantFrequency(i, 1) / baseFrequency_) + 0.5;
tempi = (int) temp;
this->setRatio(1,(MY_FLOAT) tempi);
temp = (temp2 * Phonemes::formantFrequency(i, 2) / baseFrequency) + 0.5;
this->setRatio( 1, (StkFloat) tempi );
temp = (temp2 * Phonemes::formantFrequency(i, 2) / baseFrequency_) + 0.5;
tempi = (int) temp;
this->setRatio(2, (MY_FLOAT) tempi);
gains[0] = 1.0;
gains[1] = 1.0;
gains[2] = 1.0;
this->setRatio( 2, (StkFloat) tempi );
gains_[0] = 1.0;
gains_[1] = 1.0;
gains_[2] = 1.0;
}
void FMVoices :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void FMVoices :: noteOn(StkFloat frequency, StkFloat amplitude)
{
this->setFrequency(frequency);
tilt[0] = amplitude;
tilt[1] = amplitude * amplitude;
tilt[2] = tilt[1] * amplitude;
this->setFrequency( frequency );
tilt_[0] = amplitude;
tilt_[1] = amplitude * amplitude;
tilt_[2] = tilt_[1] * amplitude;
this->keyOn();
#if defined(_STK_DEBUG_)
std::cerr << "FMVoices: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "FMVoices::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT FMVoices :: tick()
StkFloat FMVoices :: tick()
{
register MY_FLOAT temp, temp2;
register StkFloat temp, temp2;
temp = gains[3] * adsr[3]->tick() * waves[3]->tick();
temp2 = vibrato->tick() * modDepth * (MY_FLOAT) 0.1;
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]->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();
return temp * 0.33;
waves_[0]->addPhaseOffset(temp * mods_[0]);
waves_[1]->addPhaseOffset(temp * mods_[1]);
waves_[2]->addPhaseOffset(temp * mods_[2]);
waves_[3]->addPhaseOffset( twozero_.lastOut() );
twozero_.tick( temp );
temp = gains_[0] * tilt_[0] * adsr_[0]->tick() * waves_[0]->tick();
temp += gains_[1] * tilt_[1] * adsr_[1]->tick() * waves_[1]->tick();
temp += gains_[2] * tilt_[2] * adsr_[2]->tick() * waves_[2]->tick();
lastOutput_ = temp * 0.33;
return lastOutput_;
}
void FMVoices :: controlChange(int number, MY_FLOAT value)
StkFloat *FMVoices :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& FMVoices :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void FMVoices :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "FMVoices: Control value less than zero!" << std::endl;
errorString_ << "FMVoices::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "FMVoices: Control value greater than 128.0!" << std::endl;
errorString_ << "FMVoices::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_Breath_) // 2
gains[3] = __FM_gains[(int) ( norm * 99.9 )];
gains_[3] = fmGains_[(int) ( norm * 99.9 )];
else if (number == __SK_FootControl_) { // 4
currentVowel = (int) (norm * 128.0);
this->setFrequency(baseFrequency);
currentVowel_ = (int) (norm * 128.0);
this->setFrequency(baseFrequency_);
}
else if (number == __SK_ModFrequency_) // 11
this->setModulationSpeed( norm * 12.0);
else if (number == __SK_ModWheel_) // 1
this->setModulationDepth( norm );
else if (number == __SK_AfterTouch_Cont_) { // 128
tilt[0] = norm;
tilt[1] = norm * norm;
tilt[2] = tilt[1] * norm;
tilt_[0] = norm;
tilt_[1] = norm * norm;
tilt_[2] = tilt_[1] * norm;
}
else {
errorString_ << "FMVoices::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
else
std::cerr << "FMVoices: Undefined Control Number (" << number << ")!!" << std::endl;
#if defined(_STK_DEBUG_)
std::cerr << "FMVoices: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "FMVoices::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -14,7 +14,7 @@
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
If a[0] is not equal to 1, the filter coefficients
are normalized by a[0].
The \e gain parameter is applied at the filter
@@ -23,7 +23,7 @@
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 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -33,212 +33,209 @@
Filter :: Filter()
{
// The default constructor should setup for pass-through.
gain = 1.0;
nB = 1;
nA = 1;
b = new MY_FLOAT[nB];
b[0] = 1.0;
a = new MY_FLOAT[nA];
a[0] = 1.0;
gain_ = 1.0;
b_.push_back( 1.0 );
a_.push_back( 1.0 );
inputs = new MY_FLOAT[nB];
outputs = new MY_FLOAT[nA];
this->clear();
inputs_.push_back( 0.0 );
outputs_.push_back( 0.0 );
}
Filter :: Filter(int nb, MY_FLOAT *bCoefficients, int na, MY_FLOAT *aCoefficients)
Filter :: Filter( std::vector<StkFloat> &bCoefficients, std::vector<StkFloat> &aCoefficients )
{
char message[256];
// Check the arguments.
if ( nb < 1 || na < 1 ) {
sprintf(message, "Filter: nb (%d) and na (%d) must be >= 1!", nb, na);
handleError( message, StkError::FUNCTION_ARGUMENT );
if ( bCoefficients.size() == 0 || aCoefficients.size() == 0 ) {
errorString_ << "Filter: a and b coefficient vectors must both have size > 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( aCoefficients[0] == 0.0 ) {
sprintf(message, "Filter: a[0] coefficient cannot == 0!");
handleError( message, StkError::FUNCTION_ARGUMENT );
errorString_ << "Filter: a[0] coefficient cannot == 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
gain = 1.0;
nB = nb;
nA = na;
b = new MY_FLOAT[nB];
a = new MY_FLOAT[nA];
gain_ = 1.0;
b_ = bCoefficients;
a_ = aCoefficients;
inputs = new MY_FLOAT[nB];
outputs = new MY_FLOAT[nA];
inputs_ = std::vector<StkFloat> ( b_.size() );
outputs_ = std::vector<StkFloat> ( a_.size() );
this->clear();
this->setCoefficients(nB, bCoefficients, nA, aCoefficients);
}
Filter :: ~Filter()
{
delete [] b;
delete [] a;
delete [] inputs;
delete [] outputs;
}
void Filter :: clear(void)
{
int i;
for (i=0; i<nB; i++)
inputs[i] = 0.0;
for (i=0; i<nA; i++)
outputs[i] = 0.0;
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;
}
void Filter :: setCoefficients(int nb, MY_FLOAT *bCoefficients, int na, MY_FLOAT *aCoefficients)
void Filter :: setCoefficients( std::vector<StkFloat> &bCoefficients, std::vector<StkFloat> &aCoefficients )
{
int i;
char message[256];
// Check the arguments.
if ( nb < 1 || na < 1 ) {
sprintf(message, "Filter: nb (%d) and na (%d) must be >= 1!", nb, na);
handleError( message, StkError::FUNCTION_ARGUMENT );
if ( bCoefficients.size() == 0 || aCoefficients.size() == 0 ) {
errorString_ << "Filter::setCoefficients: a and b coefficient vectors must both have size > 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( aCoefficients[0] == 0.0 ) {
sprintf(message, "Filter: a[0] coefficient cannot == 0!");
handleError( message, StkError::FUNCTION_ARGUMENT );
errorString_ << "Filter::setCoefficients: a[0] coefficient cannot == 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if (nb != nB) {
delete [] b;
delete [] inputs;
nB = nb;
b = new MY_FLOAT[nB];
inputs = new MY_FLOAT[nB];
for (i=0; i<nB; i++) inputs[i] = 0.0;
if ( b_.size() != bCoefficients.size() ) {
b_ = bCoefficients;
inputs_.clear();
inputs_ = std::vector<StkFloat> ( b_.size() );
}
else {
for ( unsigned int i=0; i<b_.size(); i++ ) b_[i] = bCoefficients[i];
}
if (na != nA) {
delete [] a;
delete [] outputs;
nA = na;
a = new MY_FLOAT[nA];
outputs = new MY_FLOAT[nA];
for (i=0; i<nA; i++) outputs[i] = 0.0;
if ( a_.size() != aCoefficients.size() ) {
a_ = aCoefficients;
outputs_.clear();
outputs_ = std::vector<StkFloat> ( a_.size() );
}
else {
for ( unsigned int i=0; i<a_.size(); i++ ) a_[i] = aCoefficients[i];
}
for (i=0; i<nB; i++)
b[i] = bCoefficients[i];
for (i=0; i<nA; i++)
a[i] = aCoefficients[i];
this->clear();
// scale coefficients by a[0] if necessary
if (a[0] != 1.0) {
for (i=0; i<nB; i++)
b[i] /= a[0];
for (i=0; i<nA; i++)
a[i] /= a[0];
// Scale coefficients by a[0] if necessary
if ( a_[0] != 1.0 ) {
unsigned int i;
for ( i=0; i<b_.size(); i++ ) b_[i] /= a_[0];
for ( i=1; i<a_.size(); i++ ) a_[i] /= a_[0];
}
}
void Filter :: setNumerator(int nb, MY_FLOAT *bCoefficients)
void Filter :: setNumerator( std::vector<StkFloat> &bCoefficients )
{
int i;
char message[256];
// Check the arguments.
if ( nb < 1 ) {
sprintf(message, "Filter: nb (%d) must be >= 1!", nb);
handleError( message, StkError::FUNCTION_ARGUMENT );
// Check the argument.
if ( bCoefficients.size() == 0 ) {
errorString_ << "Filter::setNumerator: coefficient vector must have size > 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if (nb != nB) {
delete [] b;
delete [] inputs;
nB = nb;
b = new MY_FLOAT[nB];
inputs = new MY_FLOAT[nB];
for (i=0; i<nB; i++) inputs[i] = 0.0;
if ( b_.size() != bCoefficients.size() ) {
b_ = bCoefficients;
inputs_.clear();
inputs_ = std::vector<StkFloat> ( b_.size() );
}
else {
for ( unsigned int i=0; i<b_.size(); i++ ) b_[i] = bCoefficients[i];
}
for (i=0; i<nB; i++)
b[i] = bCoefficients[i];
this->clear();
}
void Filter :: setDenominator(int na, MY_FLOAT *aCoefficients)
void Filter :: setDenominator( std::vector<StkFloat> &aCoefficients )
{
int i;
char message[256];
// Check the arguments.
if ( na < 1 ) {
sprintf(message, "Filter: na (%d) must be >= 1!", na);
handleError( message, StkError::FUNCTION_ARGUMENT );
// Check the argument.
if ( aCoefficients.size() == 0 ) {
errorString_ << "Filter::setDenominator: coefficient vector must have size > 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( aCoefficients[0] == 0.0 ) {
sprintf(message, "Filter: a[0] coefficient cannot == 0!");
handleError( message, StkError::FUNCTION_ARGUMENT );
errorString_ << "Filter::setDenominator: a[0] coefficient cannot == 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if (na != nA) {
delete [] a;
delete [] outputs;
nA = na;
a = new MY_FLOAT[nA];
outputs = new MY_FLOAT[nA];
for (i=0; i<nA; i++) outputs[i] = 0.0;
if ( a_.size() != aCoefficients.size() ) {
a_ = aCoefficients;
outputs_.clear();
outputs_ = std::vector<StkFloat> ( a_.size() );
}
else {
for ( unsigned int i=0; i<a_.size(); i++ ) a_[i] = aCoefficients[i];
}
for (i=0; i<nA; i++)
a[i] = aCoefficients[i];
this->clear();
// scale coefficients by a[0] if necessary
if (a[0] != 1.0) {
for (i=0; i<nB; i++)
b[i] /= a[0];
for (i=0; i<nA; i++)
a[i] /= a[0];
// Scale coefficients by a[0] if necessary
if ( a_[0] != 1.0 ) {
unsigned int i;
for ( i=0; i<b_.size(); i++ ) b_[i] /= a_[0];
for ( i=1; i<a_.size(); i++ ) a_[i] /= a_[0];
}
}
void Filter :: setGain(MY_FLOAT theGain)
void Filter :: setGain(StkFloat gain)
{
gain = theGain;
gain_ = gain;
}
MY_FLOAT Filter :: getGain(void) const
StkFloat Filter :: getGain(void) const
{
return gain;
return gain_;
}
MY_FLOAT Filter :: lastOut(void) const
StkFloat Filter :: lastOut(void) const
{
return outputs[0];
return outputs_[0];
}
MY_FLOAT Filter :: tick(MY_FLOAT sample)
StkFloat Filter :: tick(StkFloat sample)
{
int i;
unsigned int i;
outputs[0] = 0.0;
inputs[0] = gain * sample;
for (i=nB-1; i>0; i--) {
outputs[0] += b[i] * inputs[i];
inputs[i] = inputs[i-1];
outputs_[0] = 0.0;
inputs_[0] = gain_ * sample;
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];
outputs_[0] += b_[0] * inputs_[0];
for (i=nA-1; i>0; i--) {
outputs[0] += -a[i] * outputs[i];
outputs[i] = outputs[i-1];
for (i=a_.size()-1; i>0; i--) {
outputs_[0] += -a_[i] * outputs_[i];
outputs_[i] = outputs_[i-1];
}
return outputs[0];
return outputs_[0];
}
MY_FLOAT *Filter :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *Filter :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
}
StkFrames& Filter :: tick( StkFrames& frames, unsigned int channel )
{
if ( channel == 0 || frames.channels() < channel ) {
errorString_ << "Filter::tick(): channel argument (" << channel << ") is zero or > channels in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( frames.channels() == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[i] = tick( frames[i] );
}
else if ( frames.interleaved() ) {
unsigned int hop = frames.channels();
unsigned int index = channel - 1;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
frames[index] = tick( frames[index] );
index += hop;
}
}
else {
unsigned int iStart = (channel - 1) * frames.frames();
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[iStart + i] = tick( frames[iStart + i] );
}
return frames;
}

View File

@@ -18,183 +18,192 @@
- Vibrato Gain = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Flute.h"
#include "SKINI.msg"
Flute :: Flute(MY_FLOAT lowestFrequency)
Flute :: Flute(StkFloat lowestFrequency)
{
length = (long) (Stk::sampleRate() / lowestFrequency + 1);
boreDelay = new DelayL( 100.0, length );
length >>= 1;
jetDelay = new DelayL( 49.0, length );
jetTable = new JetTabl();
filter = new OnePole();
dcBlock = new PoleZero();
dcBlock->setBlockZero();
noise = new Noise();
adsr = new ADSR();
length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
boreDelay_.setMaximumDelay( length_ );
boreDelay_.setDelay( 100.0 );
length_ >>= 1;
jetDelay_.setMaximumDelay( length_ );
jetDelay_.setDelay( 49.0 );
// Concatenate the STK rawwave path to the rawwave file
vibrato = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
vibrato->setFrequency( 5.925 );
vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
vibrato_->setFrequency( 5.925 );
this->clear();
filter->setPole( 0.7 - ((MY_FLOAT) 0.1 * 22050.0 / Stk::sampleRate() ) );
filter->setGain( -1.0 );
adsr->setAllTimes( 0.005, 0.01, 0.8, 0.010);
endReflection = (MY_FLOAT) 0.5;
jetReflection = (MY_FLOAT) 0.5;
noiseGain = 0.15; // Breath pressure random component.
vibratoGain = (MY_FLOAT) 0.05; // Breath periodic vibrato component.
jetRatio = (MY_FLOAT) 0.32;
filter_.setPole( 0.7 - ((StkFloat) 0.1 * 22050.0 / Stk::sampleRate() ) );
filter_.setGain( -1.0 );
adsr_.setAllTimes( 0.005, 0.01, 0.8, 0.010);
endReflection_ = 0.5;
jetReflection_ = 0.5;
noiseGain_ = 0.15; // Breath pressure random component.
vibratoGain_ = 0.05; // Breath periodic vibrato component.
jetRatio_ = 0.32;
maxPressure = (MY_FLOAT) 0.0;
lastFrequency = 220.0;
maxPressure_ = 0.0;
lastFrequency_ = 220.0;
}
Flute :: ~Flute()
{
delete jetDelay;
delete boreDelay;
delete jetTable;
delete filter;
delete dcBlock;
delete noise;
delete adsr;
delete vibrato;
delete vibrato_;
}
void Flute :: clear()
{
jetDelay->clear();
boreDelay->clear();
filter->clear();
dcBlock->clear();
jetDelay_.clear();
boreDelay_.clear();
filter_.clear();
dcBlock_.clear();
}
void Flute :: setFrequency(MY_FLOAT frequency)
void Flute :: setFrequency(StkFloat frequency)
{
lastFrequency = frequency;
lastFrequency_ = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "Flute: setFrequency parameter is less than or equal to zero!" << std::endl;
lastFrequency = 220.0;
errorString_ << "Flute::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.
MY_FLOAT delay = Stk::sampleRate() / lastFrequency - (MY_FLOAT) 2.0;
if (delay <= 0.0) delay = 0.3;
else if (delay > length) delay = length;
lastFrequency_ *= 0.66666;
boreDelay->setDelay(delay);
jetDelay->setDelay(delay * jetRatio);
// 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 Flute :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate)
void Flute :: startBlowing(StkFloat amplitude, StkFloat rate)
{
adsr->setAttackRate(rate);
maxPressure = amplitude / (MY_FLOAT) 0.8;
adsr->keyOn();
adsr_.setAttackRate( rate );
maxPressure_ = amplitude / (StkFloat) 0.8;
adsr_.keyOn();
}
void Flute :: stopBlowing(MY_FLOAT rate)
void Flute :: stopBlowing(StkFloat rate)
{
adsr->setReleaseRate(rate);
adsr->keyOff();
adsr_.setReleaseRate( rate );
adsr_.keyOff();
}
void Flute :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Flute :: noteOn(StkFloat frequency, StkFloat amplitude)
{
setFrequency(frequency);
startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02);
outputGain = amplitude + 0.001;
this->setFrequency( frequency );
this->startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02 );
outputGain_ = amplitude + 0.001;
#if defined(_STK_DEBUG_)
std::cerr << "Flute: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Flute::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Flute :: noteOff(MY_FLOAT amplitude)
void Flute :: noteOff(StkFloat amplitude)
{
this->stopBlowing(amplitude * 0.02);
this->stopBlowing( amplitude * 0.02 );
#if defined(_STK_DEBUG_)
std::cerr << "Flute: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Flute::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Flute :: setJetReflection(MY_FLOAT coefficient)
void Flute :: setJetReflection(StkFloat coefficient)
{
jetReflection = coefficient;
jetReflection_ = coefficient;
}
void Flute :: setEndReflection(MY_FLOAT coefficient)
void Flute :: setEndReflection(StkFloat coefficient)
{
endReflection = coefficient;
endReflection_ = coefficient;
}
void Flute :: setJetDelay(MY_FLOAT aRatio)
void Flute :: setJetDelay(StkFloat aRatio)
{
// Delay = length - approximate filter delay.
MY_FLOAT temp = Stk::sampleRate() / lastFrequency - (MY_FLOAT) 2.0;
jetRatio = aRatio;
jetDelay->setDelay(temp * aRatio); // Scaled by ratio.
StkFloat temp = Stk::sampleRate() / lastFrequency_ - (StkFloat) 2.0;
jetRatio_ = aRatio;
jetDelay_.setDelay(temp * aRatio); // Scaled by ratio.
}
MY_FLOAT Flute :: tick()
StkFloat Flute :: tick()
{
MY_FLOAT pressureDiff;
MY_FLOAT breathPressure;
StkFloat pressureDiff;
StkFloat breathPressure;
// Calculate the breath pressure (envelope + noise + vibrato)
breathPressure = maxPressure * adsr->tick();
breathPressure += breathPressure * noiseGain * noise->tick();
breathPressure += breathPressure * vibratoGain * vibrato->tick();
breathPressure = maxPressure_ * adsr_.tick();
breathPressure += breathPressure * noiseGain_ * noise_.tick();
breathPressure += breathPressure * vibratoGain_ * vibrato_->tick();
MY_FLOAT temp = filter->tick( boreDelay->lastOut() );
temp = dcBlock->tick(temp); // Block DC on reflection.
StkFloat temp = filter_.tick( boreDelay_.lastOut() );
temp = dcBlock_.tick(temp); // Block DC on reflection.
pressureDiff = breathPressure - (jetReflection * temp);
pressureDiff = jetDelay->tick( pressureDiff );
pressureDiff = jetTable->tick( pressureDiff ) + (endReflection * temp);
lastOutput = (MY_FLOAT) 0.3 * boreDelay->tick( pressureDiff );
pressureDiff = breathPressure - (jetReflection_ * temp);
pressureDiff = jetDelay_.tick( pressureDiff );
pressureDiff = jetTable_.tick( pressureDiff ) + (endReflection_ * temp);
lastOutput_ = (StkFloat) 0.3 * boreDelay_.tick( pressureDiff );
lastOutput *= outputGain;
return lastOutput;
lastOutput_ *= outputGain_;
return lastOutput_;
}
void Flute :: controlChange(int number, MY_FLOAT value)
StkFloat *Flute :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Flute :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void Flute :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "Flute: Control value less than zero!" << std::endl;
errorString_ << "Flute::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "Flute: Control value greater than 128.0!" << std::endl;
errorString_ << "Flute::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_JetDelay_) // 2
this->setJetDelay( (MY_FLOAT) (0.08 + (0.48 * norm)) );
this->setJetDelay( (StkFloat) (0.08 + (0.48 * norm)) );
else if (number == __SK_NoiseLevel_) // 4
noiseGain = ( norm * 0.4);
noiseGain_ = ( norm * 0.4);
else if (number == __SK_ModFrequency_) // 11
vibrato->setFrequency( norm * 12.0);
vibrato_->setFrequency( norm * 12.0);
else if (number == __SK_ModWheel_) // 1
vibratoGain = ( norm * 0.4 );
vibratoGain_ = ( norm * 0.4 );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr->setTarget( norm );
else
std::cerr << "Flute: Undefined Control Number (" << number << ")!!" << std::endl;
adsr_.setTarget( norm );
else {
errorString_ << "Flute::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "Flute: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "Flute::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -8,7 +8,7 @@
It provides methods for controlling the sweep
rate and target frequency.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -16,17 +16,17 @@
FormSwep :: FormSwep() : BiQuad()
{
frequency = (MY_FLOAT) 0.0;
radius = (MY_FLOAT) 0.0;
targetGain = (MY_FLOAT) 1.0;
targetFrequency = (MY_FLOAT) 0.0;
targetRadius = (MY_FLOAT) 0.0;
deltaGain = (MY_FLOAT) 0.0;
deltaFrequency = (MY_FLOAT) 0.0;
deltaRadius = (MY_FLOAT) 0.0;
sweepState = (MY_FLOAT) 0.0;
sweepRate = (MY_FLOAT) 0.002;
dirty = false;
frequency_ = (StkFloat) 0.0;
radius_ = (StkFloat) 0.0;
targetGain_ = (StkFloat) 1.0;
targetFrequency_ = (StkFloat) 0.0;
targetRadius_ = (StkFloat) 0.0;
deltaGain_ = (StkFloat) 0.0;
deltaFrequency_ = (StkFloat) 0.0;
deltaRadius_ = (StkFloat) 0.0;
sweepState_ = (StkFloat) 0.0;
sweepRate_ = (StkFloat) 0.002;
dirty_ = false;
this->clear();
}
@@ -34,85 +34,87 @@ FormSwep :: ~FormSwep()
{
}
void FormSwep :: setResonance(MY_FLOAT aFrequency, MY_FLOAT aRadius)
void FormSwep :: setResonance(StkFloat frequency, StkFloat radius)
{
dirty = false;
radius = aRadius;
frequency = aFrequency;
dirty_ = false;
radius_ = radius;
frequency_ = frequency;
BiQuad::setResonance( frequency, radius, true );
BiQuad::setResonance( frequency_, radius_, true );
}
void FormSwep :: setStates(MY_FLOAT aFrequency, MY_FLOAT aRadius, MY_FLOAT aGain)
void FormSwep :: setStates(StkFloat frequency, StkFloat radius, StkFloat gain)
{
dirty = false;
dirty_ = false;
if ( frequency != aFrequency || radius != aRadius )
BiQuad::setResonance( aFrequency, aRadius, true );
if ( frequency_ != frequency || radius_ != radius )
BiQuad::setResonance( frequency, radius, true );
frequency = aFrequency;
radius = aRadius;
gain = aGain;
targetFrequency = aFrequency;
targetRadius = aRadius;
targetGain = aGain;
frequency_ = frequency;
radius_ = radius;
gain_ = gain;
targetFrequency_ = frequency;
targetRadius_ = radius;
targetGain_ = gain;
}
void FormSwep :: setTargets(MY_FLOAT aFrequency, MY_FLOAT aRadius, MY_FLOAT aGain)
void FormSwep :: setTargets(StkFloat frequency, StkFloat radius, StkFloat gain)
{
dirty = true;
startFrequency = frequency;
startRadius = radius;
startGain = gain;
targetFrequency = aFrequency;
targetRadius = aRadius;
targetGain = aGain;
deltaFrequency = aFrequency - frequency;
deltaRadius = aRadius - radius;
deltaGain = aGain - gain;
sweepState = (MY_FLOAT) 0.0;
dirty_ = true;
startFrequency_ = frequency_;
startRadius_ = radius_;
startGain_ = gain_;
targetFrequency_ = frequency;
targetRadius_ = radius;
targetGain_ = gain;
deltaFrequency_ = frequency - frequency_;
deltaRadius_ = radius - radius_;
deltaGain_ = gain - gain_;
sweepState_ = (StkFloat) 0.0;
}
void FormSwep :: setSweepRate(MY_FLOAT aRate)
void FormSwep :: setSweepRate(StkFloat rate)
{
sweepRate = aRate;
if ( sweepRate > 1.0 ) sweepRate = 1.0;
if ( sweepRate < 0.0 ) sweepRate = 0.0;
sweepRate_ = rate;
if ( sweepRate_ > 1.0 ) sweepRate_ = 1.0;
if ( sweepRate_ < 0.0 ) sweepRate_ = 0.0;
}
void FormSwep :: setSweepTime(MY_FLOAT aTime)
void FormSwep :: setSweepTime(StkFloat time)
{
sweepRate = 1.0 / ( aTime * Stk::sampleRate() );
if ( sweepRate > 1.0 ) sweepRate = 1.0;
if ( sweepRate < 0.0 ) sweepRate = 0.0;
sweepRate_ = 1.0 / ( time * Stk::sampleRate() );
if ( sweepRate_ > 1.0 ) sweepRate_ = 1.0;
if ( sweepRate_ < 0.0 ) sweepRate_ = 0.0;
}
MY_FLOAT FormSwep :: tick(MY_FLOAT sample)
StkFloat FormSwep :: tick(StkFloat sample)
{
if (dirty) {
sweepState += sweepRate;
if ( sweepState >= 1.0 ) {
sweepState = (MY_FLOAT) 1.0;
dirty = false;
radius = targetRadius;
frequency = targetFrequency;
gain = targetGain;
if (dirty_) {
sweepState_ += sweepRate_;
if ( sweepState_ >= 1.0 ) {
sweepState_ = (StkFloat) 1.0;
dirty_ = false;
radius_ = targetRadius_;
frequency_ = targetFrequency_;
gain_ = targetGain_;
}
else {
radius = startRadius + (deltaRadius * sweepState);
frequency = startFrequency + (deltaFrequency * sweepState);
gain = startGain + (deltaGain * sweepState);
radius_ = startRadius_ + (deltaRadius_ * sweepState_);
frequency_ = startFrequency_ + (deltaFrequency_ * sweepState_);
gain_ = startGain_ + (deltaGain_ * sweepState_);
}
BiQuad::setResonance( frequency, radius, true );
BiQuad::setResonance( frequency_, radius_, true );
}
return BiQuad::tick( sample );
}
MY_FLOAT *FormSwep :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *FormSwep :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Filter::tick( vector, vectorSize );
}
StkFrames& FormSwep :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
}

58
src/Function.cpp Normal file
View File

@@ -0,0 +1,58 @@
/***************************************************/
/*! \class Function
\brief STK abstract function parent class.
This class provides common functionality for STK classes which
implement tables or other types of input to output function
mappings.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Function.h"
Function :: Function() : Stk()
{
lastOutput_ = (StkFloat) 0.0;
}
Function :: ~Function()
{
}
StkFloat *Function :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick( vector[i] );
return vector;
}
StkFrames& Function :: tick( StkFrames& frames, unsigned int channel )
{
if ( channel == 0 || frames.channels() < channel ) {
errorString_ << "Function::tick(): channel argument (" << channel << ") is zero or > channels in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( frames.channels() == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[i] = tick( frames[i] );
}
else if ( frames.interleaved() ) {
unsigned int hop = frames.channels();
unsigned int index = channel - 1;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
frames[index] = tick( frames[index] );
index += hop;
}
}
else {
unsigned int iStart = (channel - 1) * frames.frames();
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[iStart + i] = tick( frames[iStart + i] );
}
return frames;
}

57
src/Generator.cpp Normal file
View File

@@ -0,0 +1,57 @@
/***************************************************/
/*! \class Generator
\brief STK abstract unit generator parent class.
This class provides common functionality for
STK unit generator source subclasses.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Generator.h"
Generator :: Generator() : Stk()
{
lastOutput_ = 0.0;
}
Generator :: ~Generator()
{
}
StkFloat *Generator :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick();
return vector;
}
StkFrames& Generator :: tick( StkFrames& frames, unsigned int channel )
{
if ( channel == 0 || frames.channels() < channel ) {
errorString_ << "Generator::tick(): channel argument (" << channel << ") is zero or > channels in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( frames.channels() == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[i] = tick();
}
else if ( frames.interleaved() ) {
unsigned int hop = frames.channels();
unsigned int index = channel - 1;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
frames[index] = tick();
index += hop;
}
}
else {
unsigned int iStart = (channel - 1) * frames.frames();
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[iStart + i] = tick();
}
return frames;
}

View File

@@ -22,7 +22,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -32,71 +32,83 @@ HevyMetl :: HevyMetl()
: FM()
{
// Concatenate the STK rawwave path to the rawwave files
for ( int i=0; i<3; i++ )
waves[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
waves[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), TRUE );
for ( unsigned int i=0; i<3; i++ )
waves_[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
waves_[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true );
this->setRatio(0, 1.0 * 1.000);
this->setRatio(1, 4.0 * 0.999);
this->setRatio(2, 3.0 * 1.001);
this->setRatio(3, 0.5 * 1.002);
gains[0] = __FM_gains[92];
gains[1] = __FM_gains[76];
gains[2] = __FM_gains[91];
gains[3] = __FM_gains[68];
gains_[0] = fmGains_[92];
gains_[1] = fmGains_[76];
gains_[2] = fmGains_[91];
gains_[3] = fmGains_[68];
adsr[0]->setAllTimes( 0.001, 0.001, 1.0, 0.01);
adsr[1]->setAllTimes( 0.001, 0.010, 1.0, 0.50);
adsr[2]->setAllTimes( 0.010, 0.005, 1.0, 0.20);
adsr[3]->setAllTimes( 0.030, 0.010, 0.2, 0.20);
adsr_[0]->setAllTimes( 0.001, 0.001, 1.0, 0.01);
adsr_[1]->setAllTimes( 0.001, 0.010, 1.0, 0.50);
adsr_[2]->setAllTimes( 0.010, 0.005, 1.0, 0.20);
adsr_[3]->setAllTimes( 0.030, 0.010, 0.2, 0.20);
twozero->setGain( 2.0 );
vibrato->setFrequency( 5.5 );
modDepth = 0.0;
twozero_.setGain( 2.0 );
vibrato_->setFrequency( 5.5 );
modDepth_ = 0.0;
}
HevyMetl :: ~HevyMetl()
{
}
void HevyMetl :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void HevyMetl :: noteOn(StkFloat frequency, StkFloat amplitude)
{
gains[0] = amplitude * __FM_gains[92];
gains[1] = amplitude * __FM_gains[76];
gains[2] = amplitude * __FM_gains[91];
gains[3] = amplitude * __FM_gains[68];
this->setFrequency(frequency);
gains_[0] = amplitude * fmGains_[92];
gains_[1] = amplitude * fmGains_[76];
gains_[2] = amplitude * fmGains_[91];
gains_[3] = amplitude * fmGains_[68];
this->setFrequency( frequency );
this->keyOn();
#if defined(_STK_DEBUG_)
cerr << "HevyMetl: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << endl;
errorString_ << "HevyMetl::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT HevyMetl :: tick()
StkFloat HevyMetl :: tick()
{
register MY_FLOAT temp;
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 = 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);
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);
waves_[3]->addPhaseOffset( twozero_.lastOut() );
temp = (1.0 - (control2_ * 0.5)) * gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
twozero_.tick(temp);
temp += control2 * (MY_FLOAT) 0.5 * gains[1] * adsr[1]->tick() * waves[1]->tick();
temp = temp * control1;
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();
waves_[0]->addPhaseOffset( temp );
temp = gains_[0] * adsr_[0]->tick() * waves_[0]->tick();
lastOutput = temp * 0.5;
return lastOutput;
lastOutput_ = temp * 0.5;
return lastOutput_;
}
StkFloat *HevyMetl :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& HevyMetl :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

View File

@@ -5,7 +5,7 @@
This class provides a common interface for
all STK instruments.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -19,28 +19,29 @@ Instrmnt :: ~Instrmnt()
{
}
void Instrmnt :: setFrequency(MY_FLOAT frequency)
void Instrmnt :: setFrequency(StkFloat frequency)
{
std::cerr << "Instrmnt: virtual setFrequency function call!" << std::endl;
errorString_ << "Instrmnt::setFrequency: virtual setFrequency function call!";
handleError( StkError::WARNING );
}
MY_FLOAT Instrmnt :: lastOut() const
StkFloat Instrmnt :: lastOut() const
{
return lastOutput;
return lastOutput_;
}
// Support for stereo output:
MY_FLOAT Instrmnt :: lastOutLeft(void) const
StkFloat Instrmnt :: lastOutLeft(void) const
{
return 0.5 * lastOutput;
return 0.5 * lastOutput_;
}
MY_FLOAT Instrmnt :: lastOutRight(void) const
StkFloat Instrmnt :: lastOutRight(void) const
{
return 0.5 * lastOutput;
return 0.5 * lastOutput_;
}
MY_FLOAT *Instrmnt :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *Instrmnt :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick();
@@ -48,6 +49,36 @@ MY_FLOAT *Instrmnt :: tick(MY_FLOAT *vector, unsigned int vectorSize)
return vector;
}
void Instrmnt :: controlChange(int number, MY_FLOAT value)
StkFrames& Instrmnt :: tick( StkFrames& frames, unsigned int channel )
{
if ( channel == 0 || frames.channels() < channel ) {
errorString_ << "Instrmnt::tick(): channel argument (" << channel << ") is zero or > channels in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( frames.channels() == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[i] = tick();
}
else if ( frames.interleaved() ) {
unsigned int hop = frames.channels();
unsigned int index = channel - 1;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
frames[index] = tick();
index += hop;
}
}
else {
unsigned int iStart = (channel - 1) * frames.frames();
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[iStart + i] = tick();
}
return frames;
}
void Instrmnt :: controlChange(int number, StkFloat value)
{
errorString_ << "Instrmnt::controlChange: virtual function call!";
handleError( StkError::WARNING );
}

View File

@@ -10,14 +10,14 @@
filters, and two decorrelation delay lines in
parallel at the output.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "JCRev.h"
#include <math.h>
JCRev :: JCRev(MY_FLOAT T60)
JCRev :: JCRev(StkFloat T60)
{
// Delay lengths for 44100 Hz sample rate.
int lengths[9] = {1777, 1847, 1993, 2137, 389, 127, 43, 211, 179};
@@ -33,89 +33,101 @@ JCRev :: JCRev(MY_FLOAT T60)
}
}
for (i=0; i<3; i++)
allpassDelays[i] = new Delay(lengths[i+4], lengths[i+4]);
for (i=0; i<4; i++) {
combDelays[i] = new Delay(lengths[i], lengths[i]);
combCoefficient[i] = pow(10.0,(-3 * lengths[i] / (T60 * Stk::sampleRate())));
for (i=0; i<3; i++) {
allpassDelays_[i].setMaximumDelay( lengths[i+4] );
allpassDelays_[i].setDelay( lengths[i+4] );
}
outLeftDelay = new Delay(lengths[7], lengths[7]);
outRightDelay = new Delay(lengths[8], lengths[8]);
allpassCoefficient = 0.7;
effectMix = 0.3;
for ( i=0; i<4; i++ ) {
combDelays_[i].setMaximumDelay( lengths[i] );
combDelays_[i].setDelay( lengths[i] );
}
this->setT60( T60 );
outLeftDelay_.setMaximumDelay( lengths[7] );
outLeftDelay_.setDelay( lengths[7] );
outRightDelay_.setMaximumDelay( lengths[8] );
outRightDelay_.setDelay( lengths[8] );
allpassCoefficient_ = 0.7;
effectMix_ = 0.3;
this->clear();
}
JCRev :: ~JCRev()
{
delete allpassDelays[0];
delete allpassDelays[1];
delete allpassDelays[2];
delete combDelays[0];
delete combDelays[1];
delete combDelays[2];
delete combDelays[3];
delete outLeftDelay;
delete outRightDelay;
}
void JCRev :: clear()
{
allpassDelays[0]->clear();
allpassDelays[1]->clear();
allpassDelays[2]->clear();
combDelays[0]->clear();
combDelays[1]->clear();
combDelays[2]->clear();
combDelays[3]->clear();
outRightDelay->clear();
outLeftDelay->clear();
lastOutput[0] = 0.0;
lastOutput[1] = 0.0;
allpassDelays_[0].clear();
allpassDelays_[1].clear();
allpassDelays_[2].clear();
combDelays_[0].clear();
combDelays_[1].clear();
combDelays_[2].clear();
combDelays_[3].clear();
outRightDelay_.clear();
outLeftDelay_.clear();
lastOutput_[0] = 0.0;
lastOutput_[1] = 0.0;
}
MY_FLOAT JCRev :: tick(MY_FLOAT input)
void JCRev :: setT60( StkFloat T60 )
{
MY_FLOAT temp, temp0, temp1, temp2, temp3, temp4, temp5, temp6;
MY_FLOAT filtout;
for ( int i=0; i<4; i++ )
combCoefficient_[i] = pow(10.0, (-3.0 * combDelays_[i].getDelay() / (T60 * Stk::sampleRate())));
}
temp = allpassDelays[0]->lastOut();
temp0 = allpassCoefficient * temp;
StkFloat JCRev :: tick(StkFloat input)
{
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;
allpassDelays_[0].tick(temp0);
temp0 = -(allpassCoefficient_ * temp0) + temp;
temp = allpassDelays[1]->lastOut();
temp1 = allpassCoefficient * temp;
temp = allpassDelays_[1].lastOut();
temp1 = allpassCoefficient_ * temp;
temp1 += temp0;
allpassDelays[1]->tick(temp1);
temp1 = -(allpassCoefficient * temp1) + temp;
allpassDelays_[1].tick(temp1);
temp1 = -(allpassCoefficient_ * temp1) + temp;
temp = allpassDelays[2]->lastOut();
temp2 = allpassCoefficient * temp;
temp = allpassDelays_[2].lastOut();
temp2 = allpassCoefficient_ * temp;
temp2 += temp1;
allpassDelays[2]->tick(temp2);
temp2 = -(allpassCoefficient * temp2) + temp;
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());
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);
combDelays_[0].tick(temp3);
combDelays_[1].tick(temp4);
combDelays_[2].tick(temp5);
combDelays_[3].tick(temp6);
filtout = temp3 + temp4 + temp5 + temp6;
lastOutput[0] = effectMix * (outLeftDelay->tick(filtout));
lastOutput[1] = effectMix * (outRightDelay->tick(filtout));
temp = (1.0 - effectMix) * input;
lastOutput[0] += temp;
lastOutput[1] += temp;
lastOutput_[0] = effectMix_ * (outLeftDelay_.tick(filtout));
lastOutput_[1] = effectMix_ * (outRightDelay_.tick(filtout));
temp = (1.0 - effectMix_) * input;
lastOutput_[0] += temp;
lastOutput_[1] += temp;
return (lastOutput[0] + lastOutput[1]) * 0.5;
return Effect::lastOut();
}
StkFloat *JCRev :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Effect::tick( vector, vectorSize );
}
StkFrames& JCRev :: tick( StkFrames& frames, unsigned int channel )
{
return Effect::tick( frames, channel );
}

View File

@@ -1,53 +0,0 @@
/***************************************************/
/*! \class JetTabl
\brief STK jet table class.
This class implements a flue jet non-linear
function, computed by a polynomial calculation.
Contrary to the name, this is not a "table".
Consult Fletcher and Rossing, Karjalainen,
Cook, and others for more information.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
*/
/***************************************************/
#include "JetTabl.h"
JetTabl :: JetTabl()
{
lastOutput = (MY_FLOAT) 0.0;
}
JetTabl :: ~JetTabl()
{
}
MY_FLOAT JetTabl :: lastOut() const
{
return lastOutput;
}
MY_FLOAT JetTabl :: tick( MY_FLOAT input )
{
// Perform "table lookup" using a polynomial
// calculation (x^3 - x), which approximates
// the jet sigmoid behavior.
lastOutput = input * (input * input - (MY_FLOAT) 1.0);
// Saturate at +/- 1.0.
if (lastOutput > 1.0)
lastOutput = (MY_FLOAT) 1.0;
if (lastOutput < -1.0)
lastOutput = (MY_FLOAT) -1.0;
return lastOutput;
}
MY_FLOAT *JetTabl :: tick(MY_FLOAT *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
}

49
src/JetTable.cpp Normal file
View File

@@ -0,0 +1,49 @@
/***************************************************/
/*! \class JetTable
\brief STK jet table class.
This class implements a flue jet non-linear
function, computed by a polynomial calculation.
Contrary to the name, this is not a "table".
Consult Fletcher and Rossing, Karjalainen,
Cook, and others for more information.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "JetTable.h"
JetTable :: JetTable() : Function()
{
}
JetTable :: ~JetTable()
{
}
StkFloat JetTable :: tick( StkFloat input )
{
// Perform "table lookup" using a polynomial
// calculation (x^3 - x), which approximates
// the jet sigmoid behavior.
lastOutput_ = input * (input * input - (StkFloat) 1.0);
// Saturate at +/- 1.0.
if (lastOutput_ > 1.0)
lastOutput_ = (StkFloat) 1.0;
if (lastOutput_ < -1.0)
lastOutput_ = (StkFloat) -1.0;
return lastOutput_;
}
StkFloat *JetTable :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Function::tick( vector, vectorSize );
}
StkFrames& JetTable :: tick( StkFrames& frames, unsigned int channel )
{
return Function::tick( frames, channel );
}

View File

@@ -6,15 +6,15 @@ RM = /bin/rm
OBJECT_PATH = @object_path@
vpath %.o $(OBJECT_PATH)
OBJECTS = Stk.o Noise.o SubNoise.o Envelope.o ADSR.o \
OBJECTS = Stk.o Generator.o Noise.o SubNoise.o \
Envelope.o ADSR.o Asymp.o Modulate.o SingWave.o \
WvIn.o WaveLoop.o WvOut.o \
Filter.o OneZero.o OnePole.o PoleZero.o TwoZero.o TwoPole.o \
BiQuad.o FormSwep.o Delay.o DelayL.o DelayA.o \
Reverb.o PRCRev.o JCRev.o NRev.o \
Effect.o PRCRev.o JCRev.o NRev.o \
Chorus.o Echo.o PitShift.o \
Table.o ReedTabl.o JetTabl.o BowTabl.o \
Modulate.o SingWave.o Voicer.o \
Vector3D.o Sphere.o \
Function.o Table.o ReedTable.o JetTable.o BowTable.o \
Voicer.o Vector3D.o Sphere.o \
\
Instrmnt.o Clarinet.o BlowHole.o Saxofony.o Flute.o Brass.o BlowBotl.o \
Bowed.o Plucked.o StifKarp.o Sitar.o PluckTwo.o Mandolin.o Mesh2D.o \
@@ -22,7 +22,7 @@ OBJECTS = Stk.o Noise.o SubNoise.o Envelope.o ADSR.o \
Sampler.o Moog.o Simple.o Drummer.o Shakers.o \
Modal.o ModalBar.o BandedWG.o Resonate.o VoicForm.o Phonemes.o Whistle.o \
\
Messager.o SKINI.o
Messager.o Skini.o MidiFileIn.o
INCLUDE = @include@
@@ -42,9 +42,8 @@ CFLAGS += @warn@ $(INCLUDE)
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
OBJECTS += RtMidi.o RtAudio.o RtWvOut.o RtWvIn.o RtDuplex.o TcpWvOut.o TcpWvIn.o Thread.o Socket.o
OBJECTS += RtMidi.o RtAudio.o RtWvOut.o RtWvIn.o RtDuplex.o TcpWvOut.o TcpWvIn.o Thread.o Mutex.o Socket.o
DEFS += @audio_apis@
DEFS += @midiator@
endif
RAWWAVES = @rawwaves@

View File

@@ -23,139 +23,155 @@
- String Detuning = 1
- Microphone Position = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Mandolin.h"
#include "SKINI.msg"
Mandolin :: Mandolin(MY_FLOAT lowestFrequency)
Mandolin :: Mandolin(StkFloat lowestFrequency)
: PluckTwo(lowestFrequency)
{
// Concatenate the STK rawwave path to the rawwave files
soundfile[0] = new WvIn( (Stk::rawwavePath() + "mand1.raw").c_str(), TRUE );
soundfile[1] = new WvIn( (Stk::rawwavePath() + "mand2.raw").c_str(), TRUE );
soundfile[2] = new WvIn( (Stk::rawwavePath() + "mand3.raw").c_str(), TRUE );
soundfile[3] = new WvIn( (Stk::rawwavePath() + "mand4.raw").c_str(), TRUE );
soundfile[4] = new WvIn( (Stk::rawwavePath() + "mand5.raw").c_str(), TRUE );
soundfile[5] = new WvIn( (Stk::rawwavePath() + "mand6.raw").c_str(), TRUE );
soundfile[6] = new WvIn( (Stk::rawwavePath() + "mand7.raw").c_str(), TRUE );
soundfile[7] = new WvIn( (Stk::rawwavePath() + "mand8.raw").c_str(), TRUE );
soundfile[8] = new WvIn( (Stk::rawwavePath() + "mand9.raw").c_str(), TRUE );
soundfile[9] = new WvIn( (Stk::rawwavePath() + "mand10.raw").c_str(), TRUE );
soundfile[10] = new WvIn( (Stk::rawwavePath() + "mand11.raw").c_str(), TRUE );
soundfile[11] = new WvIn( (Stk::rawwavePath() + "mand12.raw").c_str(), TRUE );
soundfile_[0] = new WvIn( (Stk::rawwavePath() + "mand1.raw").c_str(), true );
soundfile_[1] = new WvIn( (Stk::rawwavePath() + "mand2.raw").c_str(), true );
soundfile_[2] = new WvIn( (Stk::rawwavePath() + "mand3.raw").c_str(), true );
soundfile_[3] = new WvIn( (Stk::rawwavePath() + "mand4.raw").c_str(), true );
soundfile_[4] = new WvIn( (Stk::rawwavePath() + "mand5.raw").c_str(), true );
soundfile_[5] = new WvIn( (Stk::rawwavePath() + "mand6.raw").c_str(), true );
soundfile_[6] = new WvIn( (Stk::rawwavePath() + "mand7.raw").c_str(), true );
soundfile_[7] = new WvIn( (Stk::rawwavePath() + "mand8.raw").c_str(), true );
soundfile_[8] = new WvIn( (Stk::rawwavePath() + "mand9.raw").c_str(), true );
soundfile_[9] = new WvIn( (Stk::rawwavePath() + "mand10.raw").c_str(), true );
soundfile_[10] = new WvIn( (Stk::rawwavePath() + "mand11.raw").c_str(), true );
soundfile_[11] = new WvIn( (Stk::rawwavePath() + "mand12.raw").c_str(), true );
directBody = 1.0;
mic = 0;
dampTime = 0;
waveDone = soundfile[mic]->isFinished();
mic_ = 0;
dampTime_ = 0;
waveDone_ = soundfile_[mic_]->isFinished();
}
Mandolin :: ~Mandolin()
{
for ( int i=0; i<12; i++ )
delete soundfile[i];
delete soundfile_[i];
}
void Mandolin :: pluck(MY_FLOAT amplitude)
void Mandolin :: 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;
soundfile_[mic_]->reset();
waveDone_ = false;
pluckAmplitude_ = amplitude;
if ( amplitude < 0.0 ) {
std::cerr << "Mandolin: pluck amplitude parameter less than zero!" << std::endl;
pluckAmplitude = 0.0;
errorString_ << "Mandolin::pluck: amplitude parameter less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
pluckAmplitude_ = 0.0;
}
else if ( amplitude > 1.0 ) {
std::cerr << "Mandolin: pluck amplitude parameter greater than 1.0!" << std::endl;
pluckAmplitude = 1.0;
errorString_ << "Mandolin::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((MY_FLOAT) 0.5 * pluckPosition * lastLength);
dampTime = (long) lastLength; // See tick method below.
combDelay_.setDelay( 0.5 * pluckPosition_ * lastLength_ );
dampTime_ = (long) lastLength_; // See tick method below.
}
void Mandolin :: pluck(MY_FLOAT amplitude, MY_FLOAT position)
void Mandolin :: pluck(StkFloat amplitude, StkFloat position)
{
// Pluck position puts zeroes at position * length.
pluckPosition = position;
pluckPosition_ = position;
if ( position < 0.0 ) {
std::cerr << "Mandolin: pluck position parameter less than zero!" << std::endl;
pluckPosition = 0.0;
std::cerr << "Mandolin::pluck: position parameter less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
pluckPosition_ = 0.0;
}
else if ( position > 1.0 ) {
std::cerr << "Mandolin: pluck position parameter greater than 1.0!" << std::endl;
pluckPosition = 1.0;
errorString_ << "Mandolin::pluck: amplitude parameter greater than one ... setting to 1.0!";
handleError( StkError::WARNING );
pluckPosition_ = 1.0;
}
this->pluck(amplitude);
this->pluck( amplitude );
}
void Mandolin :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Mandolin :: noteOn(StkFloat frequency, StkFloat amplitude)
{
this->setFrequency(frequency);
this->pluck(amplitude);
this->setFrequency( frequency );
this->pluck( amplitude );
#if defined(_STK_DEBUG_)
std::cerr << "Mandolin: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Mandolin::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Mandolin :: setBodySize(MY_FLOAT size)
void Mandolin :: setBodySize(StkFloat size)
{
// Scale the commuted body response by its sample rate (22050).
MY_FLOAT rate = size * 22050.0 / Stk::sampleRate();
StkFloat rate = size * 22050.0 / Stk::sampleRate();
for ( int i=0; i<12; i++ )
soundfile[i]->setRate(rate);
soundfile_[i]->setRate( rate );
}
MY_FLOAT Mandolin :: tick()
StkFloat Mandolin :: tick()
{
MY_FLOAT temp = 0.0;
if ( !waveDone ) {
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();
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;
if ( dampTime_ >=0 ) {
dampTime_ -= 1;
// Calculate 1st delay filtered reflection plus pluck excitation.
lastOutput = delayLine->tick( filter->tick( temp + (delayLine->lastOut() * (MY_FLOAT) 0.7) ) );
lastOutput_ = delayLine_.tick( filter_.tick( temp + (delayLine_.lastOut() * 0.7) ) );
// Calculate 2nd delay just like the 1st.
lastOutput += delayLine2->tick( filter2->tick( temp + (delayLine2->lastOut() * (MY_FLOAT) 0.7) ) );
lastOutput_ += delayLine2_.tick( filter2_.tick( temp + (delayLine2_.lastOut() * 0.7) ) );
}
else { // No damping hack after 1 period.
// Calculate 1st delay filtered reflection plus pluck excitation.
lastOutput = delayLine->tick( filter->tick( temp + (delayLine->lastOut() * loopGain) ) );
lastOutput_ = delayLine_.tick( filter_.tick( temp + (delayLine_.lastOut() * loopGain_) ) );
// Calculate 2nd delay just like the 1st.
lastOutput += delayLine2->tick( filter2->tick( temp + (delayLine2->lastOut() * loopGain) ) );
lastOutput_ += delayLine2_.tick( filter2_.tick( temp + (delayLine2_.lastOut() * loopGain_) ) );
}
lastOutput *= (MY_FLOAT) 0.3;
return lastOutput;
lastOutput_ *= 0.3;
return lastOutput_;
}
void Mandolin :: controlChange(int number, MY_FLOAT value)
StkFloat *Mandolin :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Mandolin :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void Mandolin :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "Mandolin: Control value less than zero!" << std::endl;
errorString_ << "Mandolin::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "Mandolin: Control value greater than 128.0!" << std::endl;
errorString_ << "Mandolin::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_BodySize_) // 2
@@ -163,15 +179,18 @@ void Mandolin :: controlChange(int number, MY_FLOAT value)
else if (number == __SK_PickPosition_) // 4
this->setPluckPosition( norm );
else if (number == __SK_StringDamping_) // 11
this->setBaseLoopGain((MY_FLOAT) 0.97 + (norm * (MY_FLOAT) 0.03));
this->setBaseLoopGain( 0.97 + (norm * 0.03));
else if (number == __SK_StringDetune_) // 1
this->setDetune((MY_FLOAT) 1.0 - (norm * (MY_FLOAT) 0.1));
this->setDetune( 1.0 - (norm * 0.1) );
else if (number == __SK_AfterTouch_Cont_) // 128
mic = (int) (norm * 11.0);
else
std::cerr << "Mandolin: Undefined Control Number (" << number << ")!!" << std::endl;
mic_ = (int) (norm * 11.0);
else {
errorString_ << "Mandolin::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "Mandolin: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "Mandolin::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -26,41 +26,34 @@
#include "Mesh2D.h"
#include "SKINI.msg"
#include <stdlib.h>
Mesh2D :: Mesh2D(short nX, short nY)
{
this->setNX(nX);
this->setNY(nY);
MY_FLOAT pole = 0.05;
StkFloat pole = 0.05;
short i;
for (i=0; i<NYMAX; i++) {
filterY[i] = new OnePole(pole);
filterY[i]->setGain(0.99);
filterY_[i].setPole( pole );
filterY_[i].setGain( 0.99 );
}
for (i=0; i<NXMAX; i++) {
filterX[i] = new OnePole(pole);
filterX[i]->setGain(0.99);
filterX_[i].setPole( pole );
filterX_[i].setGain( 0.99 );
}
this->clearMesh();
counter=0;
xInput = 0;
yInput = 0;
counter_=0;
xInput_ = 0;
yInput_ = 0;
}
Mesh2D :: ~Mesh2D()
{
short i;
for (i=0; i<NYMAX; i++)
delete filterY[i];
for (i=0; i<NXMAX; i++)
delete filterX[i];
}
void Mesh2D :: clear()
@@ -68,13 +61,13 @@ void Mesh2D :: clear()
this->clearMesh();
short i;
for (i=0; i<NY; i++)
filterY[i]->clear();
for (i=0; i<NY_; i++)
filterY_[i].clear();
for (i=0; i<NX; i++)
filterX[i]->clear();
for (i=0; i<NX_; i++)
filterX_[i].clear();
counter=0;
counter_=0;
}
void Mesh2D :: clearMesh()
@@ -82,57 +75,57 @@ void Mesh2D :: clearMesh()
int x, y;
for (x=0; x<NXMAX-1; x++) {
for (y=0; y<NYMAX-1; y++) {
v[x][y] = 0;
v_[x][y] = 0;
}
}
for (x=0; x<NXMAX; x++) {
for (y=0; y<NYMAX; y++) {
vxp[x][y] = 0;
vxm[x][y] = 0;
vyp[x][y] = 0;
vym[x][y] = 0;
vxp_[x][y] = 0;
vxm_[x][y] = 0;
vyp_[x][y] = 0;
vym_[x][y] = 0;
vxp1[x][y] = 0;
vxm1[x][y] = 0;
vyp1[x][y] = 0;
vym1[x][y] = 0;
vxp1_[x][y] = 0;
vxm1_[x][y] = 0;
vyp1_[x][y] = 0;
vym1_[x][y] = 0;
}
}
}
MY_FLOAT Mesh2D :: energy()
StkFloat Mesh2D :: energy()
{
// Return total energy contained in wave variables Note that some
// energy is also contained in any filter delay elements.
int x, y;
MY_FLOAT t;
MY_FLOAT e = 0;
if ( counter & 1 ) { // Ready for Mesh2D::tick1() to be called.
for (x=0; x<NX; x++) {
for (y=0; y<NY; y++) {
t = vxp1[x][y];
StkFloat t;
StkFloat e = 0;
if ( counter_ & 1 ) { // Ready for Mesh2D::tick1() to be called.
for (x=0; x<NX_; x++) {
for (y=0; y<NY_; y++) {
t = vxp1_[x][y];
e += t*t;
t = vxm1[x][y];
t = vxm1_[x][y];
e += t*t;
t = vyp1[x][y];
t = vyp1_[x][y];
e += t*t;
t = vym1[x][y];
t = vym1_[x][y];
e += t*t;
}
}
}
else { // Ready for Mesh2D::tick0() to be called.
for (x=0; x<NX; x++) {
for (y=0; y<NY; y++) {
t = vxp[x][y];
for (x=0; x<NX_; x++) {
for (y=0; y<NY_; y++) {
t = vxp_[x][y];
e += t*t;
t = vxm[x][y];
t = vxm_[x][y];
e += t*t;
t = vyp[x][y];
t = vyp_[x][y];
e += t*t;
t = vym[x][y];
t = vym_[x][y];
e += t*t;
}
}
@@ -143,161 +136,173 @@ MY_FLOAT Mesh2D :: energy()
void Mesh2D :: setNX(short lenX)
{
NX = lenX;
NX_ = lenX;
if ( lenX < 2 ) {
std::cerr << "Mesh2D::setNX(" << lenX << "): Minimum length is 2!" << std::endl;
NX = 2;
errorString_ << "Mesh2D::setNX(" << lenX << "): Minimum length is 2!";
handleError( StkError::WARNING );
NX_ = 2;
}
else if ( lenX > NXMAX ) {
std::cerr << "Mesh2D::setNX(" << lenX << "): Maximum length is " << NXMAX << "!" << std::endl;
NX = NXMAX;
errorString_ << "Mesh2D::setNX(" << lenX << "): Maximum length is " << NXMAX << '!';;
handleError( StkError::WARNING );
NX_ = NXMAX;
}
}
void Mesh2D :: setNY(short lenY)
{
NY = lenY;
NY_ = lenY;
if ( lenY < 2 ) {
std::cerr << "Mesh2D::setNY(" << lenY << "): Minimum length is 2!" << std::endl;
NY = 2;
errorString_ << "Mesh2D::setNY(" << lenY << "): Minimum length is 2!";
handleError( StkError::WARNING );
NY_ = 2;
}
else if ( lenY > NYMAX ) {
std::cerr << "Mesh2D::setNY(" << lenY << "): Maximum length is " << NYMAX << "!" << std::endl;
NY = NYMAX;
errorString_ << "Mesh2D::setNY(" << lenY << "): Maximum length is " << NXMAX << '!';;
handleError( StkError::WARNING );
NY_ = NYMAX;
}
}
void Mesh2D :: setDecay(MY_FLOAT decayFactor)
void Mesh2D :: setDecay(StkFloat decayFactor)
{
MY_FLOAT gain = decayFactor;
StkFloat gain = decayFactor;
if ( decayFactor < 0.0 ) {
std::cerr << "Mesh2D::setDecay decayFactor value is less than 0.0!" << std::endl;
errorString_ << "Mesh2D::setDecay: decayFactor value is less than 0.0!";
handleError( StkError::WARNING );
gain = 0.0;
}
else if ( decayFactor > 1.0 ) {
std::cerr << "Mesh2D::setDecay decayFactor value is greater than 1.0!" << std::endl;
errorString_ << "Mesh2D::setDecay decayFactor value is greater than 1.0!";
handleError( StkError::WARNING );
gain = 1.0;
}
int i;
for (i=0; i<NYMAX; i++)
filterY[i]->setGain(gain);
filterY_[i].setGain( gain );
for (i=0; i<NXMAX; i++)
filterX[i]->setGain(gain);
filterX_[i].setGain( gain );
}
void Mesh2D :: setInputPosition(MY_FLOAT xFactor, MY_FLOAT yFactor)
void Mesh2D :: setInputPosition(StkFloat xFactor, StkFloat yFactor)
{
if ( xFactor < 0.0 ) {
std::cerr << "Mesh2D::setInputPosition xFactor value is less than 0.0!" << std::endl;
xInput = 0;
errorString_ << "Mesh2D::setInputPosition xFactor value is less than 0.0!";
handleError( StkError::WARNING );
xInput_ = 0;
}
else if ( xFactor > 1.0 ) {
std::cerr << "Mesh2D::setInputPosition xFactor value is greater than 1.0!" << std::endl;
xInput = NX - 1;
errorString_ << "Mesh2D::setInputPosition xFactor value is greater than 1.0!";
handleError( StkError::WARNING );
xInput_ = NX_ - 1;
}
else
xInput = (short) (xFactor * (NX - 1));
xInput_ = (short) (xFactor * (NX_ - 1));
if ( yFactor < 0.0 ) {
std::cerr << "Mesh2D::setInputPosition yFactor value is less than 0.0!" << std::endl;
yInput = 0;
errorString_ << "Mesh2D::setInputPosition yFactor value is less than 0.0!";
handleError( StkError::WARNING );
yInput_ = 0;
}
else if ( yFactor > 1.0 ) {
std::cerr << "Mesh2D::setInputPosition yFactor value is greater than 1.0!" << std::endl;
yInput = NY - 1;
errorString_ << "Mesh2D::setInputPosition yFactor value is greater than 1.0!";
handleError( StkError::WARNING );
yInput_ = NY_ - 1;
}
else
yInput = (short) (yFactor * (NY - 1));
yInput_ = (short) (yFactor * (NY_ - 1));
}
void Mesh2D :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Mesh2D :: noteOn(StkFloat frequency, StkFloat amplitude)
{
// Input at corner.
if ( counter & 1 ) {
vxp1[xInput][yInput] += amplitude;
vyp1[xInput][yInput] += amplitude;
if ( counter_ & 1 ) {
vxp1_[xInput_][yInput_] += amplitude;
vyp1_[xInput_][yInput_] += amplitude;
}
else {
vxp[xInput][yInput] += amplitude;
vyp[xInput][yInput] += amplitude;
vxp_[xInput_][yInput_] += amplitude;
vyp_[xInput_][yInput_] += amplitude;
}
#if defined(_STK_DEBUG_)
std::cerr << "Mesh2D: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Mesh2D::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Mesh2D :: noteOff(MY_FLOAT amplitude)
void Mesh2D :: noteOff(StkFloat amplitude)
{
#if defined(_STK_DEBUG_)
std::cerr << "Mesh2D: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Mesh2D::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT Mesh2D :: tick(MY_FLOAT input)
StkFloat Mesh2D :: tick(StkFloat input)
{
if ( counter & 1 ) {
vxp1[xInput][yInput] += input;
vyp1[xInput][yInput] += input;
lastOutput = tick1();
if ( counter_ & 1 ) {
vxp1_[xInput_][yInput_] += input;
vyp1_[xInput_][yInput_] += input;
lastOutput_ = tick1();
}
else {
vxp[xInput][yInput] += input;
vyp[xInput][yInput] += input;
lastOutput = tick0();
vxp_[xInput_][yInput_] += input;
vyp_[xInput_][yInput_] += input;
lastOutput_ = tick0();
}
counter++;
return lastOutput;
counter_++;
return lastOutput_;
}
MY_FLOAT Mesh2D :: tick()
StkFloat Mesh2D :: tick()
{
lastOutput = ((counter & 1) ? this->tick1() : this->tick0());
counter++;
return lastOutput;
lastOutput_ = ((counter_ & 1) ? this->tick1() : this->tick0());
counter_++;
return lastOutput_;
}
#define VSCALE ((MY_FLOAT) (0.5))
const StkFloat VSCALE = 0.5;
MY_FLOAT Mesh2D :: tick0()
StkFloat Mesh2D :: tick0()
{
int x, y;
MY_FLOAT outsamp = 0;
StkFloat outsamp = 0;
// Update junction velocities.
for (x=0; x<NX-1; x++) {
for (y=0; y<NY-1; y++) {
v[x][y] = ( vxp[x][y] + vxm[x+1][y] +
vyp[x][y] + vym[x][y+1] ) * VSCALE;
for (x=0; x<NX_-1; x++) {
for (y=0; y<NY_-1; y++) {
v_[x][y] = ( vxp_[x][y] + vxm_[x+1][y] +
vyp_[x][y] + vym_[x][y+1] ) * VSCALE;
}
}
// Update junction outgoing waves, using alternate wave-variable buffers.
for (x=0; x<NX-1; x++) {
for (y=0; y<NY-1; y++) {
MY_FLOAT vxy = v[x][y];
for (x=0; x<NX_-1; x++) {
for (y=0; y<NY_-1; y++) {
StkFloat vxy = v_[x][y];
// Update positive-going waves.
vxp1[x+1][y] = vxy - vxm[x+1][y];
vyp1[x][y+1] = vxy - vym[x][y+1];
vxp1_[x+1][y] = vxy - vxm_[x+1][y];
vyp1_[x][y+1] = vxy - vym_[x][y+1];
// Update minus-going waves.
vxm1[x][y] = vxy - vxp[x][y];
vym1[x][y] = vxy - vyp[x][y];
vxm1_[x][y] = vxy - vxp_[x][y];
vym1_[x][y] = vxy - vyp_[x][y];
}
}
// Loop over velocity-junction boundary faces, update edge
// reflections, with filtering. We're only filtering on one x and y
// edge here and even this could be made much sparser.
for (y=0; y<NY-1; y++) {
vxp1[0][y] = filterY[y]->tick(vxm[0][y]);
vxm1[NX-1][y] = vxp[NX-1][y];
for (y=0; y<NY_-1; y++) {
vxp1_[0][y] = filterY_[y].tick(vxm_[0][y]);
vxm1_[NX_-1][y] = vxp_[NX_-1][y];
}
for (x=0; x<NX-1; x++) {
vyp1[x][0] = filterX[x]->tick(vym[x][0]);
vym1[x][NY-1] = vyp[x][NY-1];
for (x=0; x<NX_-1; x++) {
vyp1_[x][0] = filterX_[x].tick(vym_[x][0]);
vym1_[x][NY_-1] = vyp_[x][NY_-1];
}
// Output = sum of outgoing waves at far corner. Note that the last
@@ -305,84 +310,97 @@ MY_FLOAT Mesh2D :: tick0()
// coordinate indices at their next-to-last values. This is because
// the "unit strings" attached to each velocity node to terminate
// the mesh are not themselves connected together.
outsamp = vxp[NX-1][NY-2] + vyp[NX-2][NY-1];
outsamp = vxp_[NX_-1][NY_-2] + vyp_[NX_-2][NY_-1];
return outsamp;
}
MY_FLOAT Mesh2D :: tick1()
StkFloat Mesh2D :: tick1()
{
int x, y;
MY_FLOAT outsamp = 0;
StkFloat outsamp = 0;
// Update junction velocities.
for (x=0; x<NX-1; x++) {
for (y=0; y<NY-1; y++) {
v[x][y] = ( vxp1[x][y] + vxm1[x+1][y] +
vyp1[x][y] + vym1[x][y+1] ) * VSCALE;
for (x=0; x<NX_-1; x++) {
for (y=0; y<NY_-1; y++) {
v_[x][y] = ( vxp1_[x][y] + vxm1_[x+1][y] +
vyp1_[x][y] + vym1_[x][y+1] ) * VSCALE;
}
}
// Update junction outgoing waves,
// using alternate wave-variable buffers.
for (x=0; x<NX-1; x++) {
for (y=0; y<NY-1; y++) {
MY_FLOAT vxy = v[x][y];
for (x=0; x<NX_-1; x++) {
for (y=0; y<NY_-1; y++) {
StkFloat vxy = v_[x][y];
// Update positive-going waves.
vxp[x+1][y] = vxy - vxm1[x+1][y];
vyp[x][y+1] = vxy - vym1[x][y+1];
vxp_[x+1][y] = vxy - vxm1_[x+1][y];
vyp_[x][y+1] = vxy - vym1_[x][y+1];
// Update minus-going waves.
vxm[x][y] = vxy - vxp1[x][y];
vym[x][y] = vxy - vyp1[x][y];
vxm_[x][y] = vxy - vxp1_[x][y];
vym_[x][y] = vxy - vyp1_[x][y];
}
}
// Loop over velocity-junction boundary faces, update edge
// reflections, with filtering. We're only filtering on one x and y
// edge here and even this could be made much sparser.
for (y=0; y<NY-1; y++) {
vxp[0][y] = filterY[y]->tick(vxm1[0][y]);
vxm[NX-1][y] = vxp1[NX-1][y];
for (y=0; y<NY_-1; y++) {
vxp_[0][y] = filterY_[y].tick(vxm1_[0][y]);
vxm_[NX_-1][y] = vxp1_[NX_-1][y];
}
for (x=0; x<NX-1; x++) {
vyp[x][0] = filterX[x]->tick(vym1[x][0]);
vym[x][NY-1] = vyp1[x][NY-1];
for (x=0; x<NX_-1; x++) {
vyp_[x][0] = filterX_[x].tick(vym1_[x][0]);
vym_[x][NY_-1] = vyp1_[x][NY_-1];
}
// Output = sum of outgoing waves at far corner.
outsamp = vxp1[NX-1][NY-2] + vyp1[NX-2][NY-1];
outsamp = vxp1_[NX_-1][NY_-2] + vyp1_[NX_-2][NY_-1];
return outsamp;
}
void Mesh2D :: controlChange(int number, MY_FLOAT value)
StkFloat *Mesh2D :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Mesh2D :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void Mesh2D :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "Mesh2D: Control value less than zero!" << std::endl;
errorString_ << "Mesh2D::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "Mesh2D: Control value greater than 128.0!" << std::endl;
errorString_ << "Mesh2D::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == 2) // 2
setNX( (short) (norm * (NXMAX-2) + 2) );
this->setNX( (short) (norm * (NXMAX-2) + 2) );
else if (number == 4) // 4
setNY( (short) (norm * (NYMAX-2) + 2) );
this->setNY( (short) (norm * (NYMAX-2) + 2) );
else if (number == 11) // 11
setDecay( 0.9 + (norm * 0.1) );
this->setDecay( 0.9 + (norm * 0.1) );
else if (number == __SK_ModWheel_) // 1
setInputPosition(norm, norm);
else if (number == __SK_AfterTouch_Cont_) // 128
;
else
std::cerr << "Mesh2D: Undefined Control Number (" << number << ")!!" << std::endl;
this->setInputPosition( norm, norm );
else {
errorString_ << "Mesh2D::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "Mesh2D: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "Mesh2D::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -2,393 +2,419 @@
/*! \class Messager
\brief STK input control message parser.
This class reads and parses control messages
from a variety of sources, such as a MIDI
port, scorefile, socket connection, or pipe.
MIDI messages are retrieved using the RtMidi
class. All other input sources (scorefile,
socket, or pipe) are assumed to provide SKINI
formatted messages.
This class reads and parses control messages from a variety of
sources, such as a scorefile, MIDI port, socket connection, or
stdin. MIDI messages are retrieved using the RtMidi class. All
other input sources (scorefile, socket, or stdin) are assumed to
provide SKINI formatted messages. This class can be compiled with
generic, non-realtime support, in which case only scorefile
reading is possible.
For each call to nextMessage(), the active
input sources are queried to see if a new
control message is available.
The various \e realtime message acquisition mechanisms (from MIDI,
socket, or stdin) take place asynchronously, filling the message
queue. A call to popMessage() will pop the next available control
message from the queue and return it via the referenced Message
structure. When a \e non-realtime scorefile is set, it is not
possible to start reading realtime input messages (from MIDI,
socket, or stdin). Likewise, it is not possible to read from a
scorefile when a realtime input mechanism is running.
This class is primarily for use in STK main()
event loops.
When MIDI input is started, input is also automatically read from
stdin. This allows for program termination via the terminal
window. An __SK_Exit_ message is pushed onto the stack whenever
an "exit" or "Exit" message is received from stdin or when all
socket connections close and no stdin thread is running.
One of the original goals in creating this
class was to simplify the message acquisition
process by removing all threads. If the
windoze select() function behaved just like
the unix one, that would have been possible.
Since it does not (it can't be used to poll
STDIN), I am using a thread to acquire
messages from STDIN, which sends these
messages via a socket connection to the
message socket server. Perhaps in the future,
it will be possible to simplify things.
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 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Messager.h"
#include <string.h>
#include <iostream>
#include "SKINI.msg"
int socket_port = 2001;
static const int STK_FILE = 0x1;
static const int STK_MIDI = 0x2;
static const int STK_STDIN = 0x4;
static const int STK_SOCKET = 0x8;
Messager :: Messager(int inputMask, int port)
Messager :: Messager()
{
sources = inputMask;
rtDelta = RT_BUFFER_SIZE;
messageIndex = 0;
nMessages = 0;
skini = new SKINI();
data_.sources = 0;
data_.queueLimit = DEFAULT_QUEUE_LIMIT;
#if defined(__STK_REALTIME__)
// If no input source is specified, we assume the input is coming
// from a SKINI scorefile. If any input source is specified, we
// will always check STDIN, even if STK_PIPE is not specified. This
// provides a means to exit cleanly when reading MIDI or in case a
// socket connection cannot be made after STK_SOCKET has been
// specified. The current means of polling STDIN is via a thread,
// which sends its data via a socket connection to the socket
// server.
if ( sources ) {
if ( sources & STK_MIDI ) {
// Attempt to open a MIDI device, but don't throw an exception
// if other input sources are specified.
try {
midi = new RtMidi();
}
catch (StkError &exception) {
if ( sources == STK_MIDI ) {
throw exception;
}
// Disable the MIDI input and keep going.
sources &= ~STK_MIDI;
}
}
// If STK_PIPE is not specified, let the users know they can exit
// the program via the console if necessary.
if ( !(sources & STK_PIPE) && sources )
std::cout << "\nType `Exit<cr>' to quit.\n" << std::endl;
sources |= STK_SOCKET;
socket_port = port;
soket = new Socket(port);
if (inputMask & STK_SOCKET)
printf("\nSocket server listening for connection(s) on port %d ...\n\n", port);
nSockets = 0;
maxfd = 0;
FD_ZERO(&mask);
int d = soket->socket();
FD_SET(d, &mask);
if (d > maxfd) maxfd = d;
// The fd array is used to hold the file descriptors for all
// connected sockets. This saves some time incrementing through
// file descriptors when using select().
for (int i=0; i<16; i++)
fd[i] = 0;
// Start the stdin input thread.
thread = new Thread();
if ( !thread->start( (THREAD_FUNCTION)&stdinHandler, NULL ) ) {
sprintf(error, "Messager: Unable to start stdin input thread!");
handleError( error, StkError::PROCESS_THREAD );
}
}
#endif // __STK_REALTIME__
data_.socket = 0;
data_.midi = 0;
#endif
}
Messager :: ~Messager()
{
delete skini;
// Clear the queue in case any thread is waiting on its limit.
#if defined(__STK_REALTIME__)
data_.mutex.lock();
#endif
while ( data_.queue.size() ) data_.queue.pop();
data_.sources = 0;
#if defined(__STK_REALTIME__)
data_.mutex.unlock();
if ( data_.socket ) {
socketThread_.wait();
delete data_.socket;
}
if ( data_.midi ) delete data_.midi;
#endif
}
bool Messager :: setScoreFile( const char* filename )
{
if ( data_.sources ) {
if ( data_.sources == STK_FILE ) {
errorString_ << "Messager::setScoreFile: already reading a scorefile!";
handleError( StkError::WARNING );
}
else {
errorString_ << "Messager::setScoreFile: already reading realtime control input ... cannot do scorefile input too!";
handleError( StkError::WARNING );
}
return false;
}
if ( !data_.skini.setFile( filename ) ) return false;
data_.sources = STK_FILE;
return true;
}
void Messager :: popMessage( Skini::Message& message )
{
if ( data_.sources == STK_FILE ) { // scorefile input
if ( !data_.skini.nextMessage( message ) )
message.type = __SK_Exit_;
return;
}
if ( data_.queue.size() == 0 ) {
// An empty (or invalid) message is indicated by a type = 0.
message.type = 0;
return;
}
// Copy queued message to the message pointer structure and then "pop" it.
#if defined(__STK_REALTIME__)
data_.mutex.lock();
#endif
message = data_.queue.front();
data_.queue.pop();
#if defined(__STK_REALTIME__)
data_.mutex.unlock();
#endif
}
void Messager :: pushMessage( Skini::Message& message )
{
#if defined(__STK_REALTIME__)
data_.mutex.lock();
#endif
data_.queue.push( message );
#if defined(__STK_REALTIME__)
data_.mutex.unlock();
#endif
}
#if defined(__STK_REALTIME__)
if ( sources & STK_MIDI )
delete midi;
if ( sources & STK_SOCKET ) {
delete soket;
delete thread;
}
#endif // __STK_REALTIME__
}
long Messager :: getType() const
bool Messager :: startStdInput()
{
return type;
}
MY_FLOAT Messager :: getByteTwo() const
{
return byte2;
}
MY_FLOAT Messager :: getByteThree() const
{
return byte3;
}
long Messager :: getChannel() const
{
return channel;
}
void Messager :: setRtDelta(long nSamples)
{
if ( nSamples > 0 )
rtDelta = nSamples;
else
std::cerr << "Messager: setRtDelta(" << nSamples << ") less than or equal to zero!" << std::endl;
}
long Messager :: getDelta() const
{
return delta;
}
long Messager :: nextMessage()
{
if (nMessages > 0 ) nMessages--;
type = 0;
if ( !sources ) {
// No realtime flags ... assuming scorefile input.
memset(message[messageIndex], 0, MESSAGE_LENGTH);
if ( fgets(message[messageIndex], MESSAGE_LENGTH, stdin) == 0 ) {
delta = 0;
return -1; // end of file
}
nMessages++;
}
#if defined(__STK_REALTIME__)
else if (nMessages == 0) {
if ( midiMessage() ) return type;
if ( !socketMessage() ) return type;
}
#endif
skini->parseThis(message[messageIndex++]);
if (messageIndex >= MAX_MESSAGES) messageIndex = 0;
type = skini->getType();
if (type <= 0) {
// Don't tick for comments or improperly formatted messages.
nMessages--;
delta = 0;
type = 0;
return type;
if ( data_.sources == STK_FILE ) {
errorString_ << "Messager::startStdInput: already reading a scorefile ... cannot do realtime control input too!";
handleError( StkError::WARNING );
return false;
}
channel = skini->getChannel();
byte2 = skini->getByteTwo();
byte3 = skini->getByteThree();
MY_FLOAT temp = skini->getDelta();
if ( temp >= 0.0 )
delta = (long) (temp * Stk::sampleRate());
else
// Ignore negative delta times (absolute time).
delta = rtDelta;
return type;
}
#if defined(__STK_REALTIME__)
bool Messager :: midiMessage( void )
{
if (sources & STK_MIDI) {
if ( midi->nextMessage() > 0 ) {
// get MIDI message info
type = midi->getType();
channel = midi->getChannel();
byte2 = midi->getByteTwo();
byte3 = midi->getByteThree();
nMessages++;
delta = rtDelta;
return true;
}
}
return false;
}
bool Messager :: socketMessage()
{
register fd_set rmask;
static struct timeval timeout = {0, 0};
rmask = mask;
if ( select(maxfd+1, &rmask, (fd_set *)0, (fd_set *)0, &timeout) ) {
// A file descriptor is set.
// Check if there's a new socket connection available.
if ( FD_ISSET(soket->socket(), &rmask) ) {
// Accept and service new connection.
int newfd = soket->accept();
if ( newfd < 0 ) {
sprintf(error, "Messager: Couldn't accept connection request!");
handleError(error, StkError::WARNING);
}
// We assume the first connection will occur for the stdin
// thread socket. Since this connection is "hidden" from
// the user, only print connected messages for subsequent
// connections.
if (nSockets == 0)
pipefd = newfd;
else
std::cout << "New socket connection made.\n" << std::endl;
// Set the socket to non-blocking mode.
Socket::setBlocking( newfd, false );
// Save the descriptor and update the masks.
fd[nSockets++] = newfd;
FD_SET(newfd, &mask);
if ( newfd > maxfd) maxfd = newfd;
FD_CLR(soket->socket(), &rmask);
}
// Check client socket connections.
unsigned int client = 0;
while ( client < nSockets ) {
if ( !FD_ISSET(fd[client], &rmask) )
client++;
else {
// This connection has data.
if ( !readSocket( fd[client] ) ) {
// The socket connection closed.
nSockets--;
if ( nSockets == 0 ) {
type = -1;
return false;
}
if ( nSockets == 1 && FD_ISSET(pipefd, &mask) ) {
// The "piping" socket is still running.
if (sources & STK_MIDI) {
std::cout << "MIDI input still running ... type 'Exit<cr>' to quit.\n" << std::endl;
}
else if (!(sources & STK_PIPE) ) {
// The user didn't specify this connection, so quit now.
type = -1;
return false;
}
}
if (client < nSockets) {
// Move descriptors down in the list.
for (unsigned int j=client; j<nSockets; j++)
fd[j] = fd[j+1];
}
delta = 0;
return false;
}
if ( !strncmp(message[messageIndex], "Exit", 4) || !strncmp(message[messageIndex], "exit", 4) ) {
// We have an "Exit" message ... don't try to parse it.
messageIndex++;
nMessages--;
delta = 0;
return false;
}
// Not an "Exit" message ... parse it.
return true;
}
}
if ( data_.sources & STK_STDIN ) {
errorString_ << "Messager::startStdInput: stdin input thread already started.";
handleError( StkError::WARNING );
return false;
}
// If we get here, we checked all devices but found no messages.
delta = rtDelta;
return false;
// Start the stdin input thread.
if ( !stdinThread_.start( (THREAD_FUNCTION)&stdinHandler, &data_ ) ) {
errorString_ << "Messager::startStdInput: unable to start stdin input thread!";
handleError( StkError::WARNING );
return false;
}
data_.sources |= STK_STDIN;
return true;
}
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
#include <errno.h>
#endif
bool Messager :: readSocket(int fd)
THREAD_RETURN THREAD_TYPE stdinHandler(void *ptr)
{
// This method will read all data available from a socket
// connection, filling the message buffer. This is necessary
// because the select() function triggers on socket activity, not on
// the presence of (buffered) data. So, whenever activity is
// indicated, we need to grab all available data.
char buffer[MESSAGE_LENGTH];
int index = 0, m = 0, bufferSize = 0;
int nextMessage;
Messager::MessagerData *data = (Messager::MessagerData *) ptr;
Skini::Message message;
nextMessage = (messageIndex + nMessages) % MAX_MESSAGES;
memset(message[nextMessage], 0, MESSAGE_LENGTH);
std::string line;
while ( !std::getline( std::cin, line).eof() ) {
if ( line.empty() ) continue;
if ( line.compare(0, 4, "Exit") == 0 || line.compare(0, 4, "exit") == 0 )
break;
#if ( defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__) )
errno = 0;
while (bufferSize != -1 && errno != EAGAIN) {
#elif defined(__OS_WINDOWS__)
while (bufferSize != SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) {
#endif
while (index < bufferSize) {
message[nextMessage][m++] = buffer[index];
if (buffer[index++] == '\n') {
m = 0;
nMessages++;
nextMessage = (messageIndex + nMessages) % MAX_MESSAGES;
memset(message[nextMessage], 0, MESSAGE_LENGTH);
}
}
index = 0;
data->mutex.lock();
if ( data->skini.parseString( line, message ) )
data->queue.push( message );
data->mutex.unlock();
// Receive a new socket buffer.
memset(buffer, 0, MESSAGE_LENGTH);
bufferSize = Socket::readBuffer(fd, buffer, MESSAGE_LENGTH, 0);
if (bufferSize == 0) {
FD_CLR(fd, &mask);
Socket::close( fd );
while ( data->queue.size() >= data->queueLimit ) Stk::sleep( 50 );
}
// We assume here that if someone types an "exit" message in the
// terminal window, all processing should stop.
message.type = __SK_Exit_;
data->queue.push( message );
data->sources &= ~STK_STDIN;
return NULL;
}
void midiHandler( double timeStamp, std::vector<unsigned char> *bytes, void *ptr )
{
if ( bytes->size() < 2 ) return;
// Parse the MIDI bytes ... only keep MIDI channel messages.
if ( bytes->at(0) > 239 ) return;
Messager::MessagerData *data = (Messager::MessagerData *) ptr;
Skini::Message message;
message.type = bytes->at(0) & 0xF0;
message.channel = bytes->at(0) & 0x0F;
message.time = 0.0; // realtime messages should have delta time = 0.0
message.intValues[0] = bytes->at(1);
message.floatValues[0] = (StkFloat) message.intValues[0];
if ( ( message.type != 0xC0 ) && ( message.type != 0xD0 ) ) {
if ( bytes->size() < 3 ) return;
message.intValues[1] = bytes->at(2);
message.floatValues[1] = (StkFloat) message.intValues[1];
}
while ( data->queue.size() >= data->queueLimit ) Stk::sleep( 50 );
data->mutex.lock();
data->queue.push( message );
data->mutex.unlock();
}
bool Messager :: startMidiInput( int port )
{
if ( data_.sources == STK_FILE ) {
errorString_ << "Messager::startMidiInput: already reading a scorefile ... cannot do realtime control input too!";
handleError( StkError::WARNING );
return false;
}
if ( data_.sources & STK_MIDI ) {
errorString_ << "Messager::startMidiInput: MIDI input already started.";
handleError( StkError::WARNING );
return false;
}
// First start the stdin input thread if it isn't already running
// (to allow the user to exit).
if ( !( data_.sources & STK_STDIN ) ) {
if ( this->startStdInput() == false ) {
errorString_ << "Messager::startMidiInput: unable to start input from stdin.";
handleError( StkError::WARNING );
return false;
}
}
try {
data_.midi = new RtMidiIn();
data_.midi->setCallback( &midiHandler, (void *) &data_ );
if ( port == -1 ) data_.midi->openVirtualPort();
else data_.midi->openPort( (unsigned int)port );
}
catch ( RtError &error ) {
errorString_ << "Messager::startMidiInput: error creating RtMidiIn instance (" << error.getMessage() << ").";
handleError( StkError::WARNING );
return false;
}
data_.sources |= STK_MIDI;
return true;
}
THREAD_RETURN THREAD_TYPE stdinHandler(void *)
bool Messager :: startSocketInput( int port )
{
char message[MESSAGE_LENGTH];
if ( data_.sources == STK_FILE ) {
errorString_ << "Messager::startSocketInput: already reading a scorefile ... cannot do realtime control input too!";
handleError( StkError::WARNING );
return false;
}
Socket *s;
if ( data_.sources & STK_SOCKET ) {
errorString_ << "Messager::startSocketInput: socket input thread already started.";
handleError( StkError::WARNING );
return false;
}
// Create the socket server.
try {
s = new Socket( socket_port, "localhost" );
data_.socket = new Socket( port );
}
catch (StkError &) {
fprintf(stderr, "Messager: Couldn't create stdin input thread!\n");
return NULL;
catch ( StkError& ) {
return false;
}
for (;;) {
memset(message, 0, MESSAGE_LENGTH);
if ( fgets(message, MESSAGE_LENGTH, stdin) == 0 )
break;
errorString_ << "Socket server listening for connection(s) on port " << port << "...";
handleError( StkError::STATUS );
// Check for an "Exit" message.
if ( !strncmp(message, "Exit", 4) || !strncmp(message, "exit", 4) )
break;
// Initialize socket descriptor information.
FD_ZERO(&data_.mask);
int fd = data_.socket->id();
FD_SET( fd, &data_.mask );
data_.fd.push_back( fd );
if ( s->writeBuffer( (void *)message, strlen(message), 0) < 0 ) {
fprintf(stderr, "Messager: stdin thread connection to socket server failed!\n");
break;
// Start the socket thread.
if ( !socketThread_.start( (THREAD_FUNCTION)&socketHandler, &data_ ) ) {
errorString_ << "Messager::startSocketInput: unable to start socket input thread!";
handleError( StkError::WARNING );
return false;
}
data_.sources |= STK_SOCKET;
return true;
}
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOS__))
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#endif
THREAD_RETURN THREAD_TYPE socketHandler(void *ptr)
{
Messager::MessagerData *data = (Messager::MessagerData *) ptr;
Skini::Message message;
std::vector<int>& fd = data->fd;
struct timeval timeout;
fd_set rmask;
int newfd;
unsigned int i;
const int bufferSize = 1024;
char buffer[bufferSize];
int index = 0, bytesRead = 0;
std::string line;
std::vector<int> fdclose;
while ( data->sources & STK_SOCKET ) {
// Use select function to periodically poll socket desriptors.
rmask = data->mask;
timeout.tv_sec = 0; timeout.tv_usec = 50000; // 50 milliseconds
if ( select( fd.back()+1, &rmask, (fd_set *)0, (fd_set *)0, &timeout ) <= 0 ) continue;
// A file descriptor is set. Check if there's a new socket connection available.
if ( FD_ISSET( data->socket->id(), &rmask ) ) {
// Accept and service new connection.
newfd = data->socket->accept();
if ( newfd >= 0 ) {
std::cout << "New socket connection made.\n" << std::endl;
// Set the socket to non-blocking mode.
Socket::setBlocking( newfd, false );
// Save the descriptor and update the masks.
fd.push_back( newfd );
std::sort( fd.begin(), data->fd.end() );
FD_SET( newfd, &data->mask );
FD_CLR( data->socket->id(), &rmask );
}
else
std::cerr << "Messager: Couldn't accept connection request!\n";
}
// Check the other descriptors.
for ( i=0; i<fd.size(); i++ ) {
if ( !FD_ISSET( fd[i], &rmask ) ) continue;
// This connection has data. Read and parse it.
bytesRead = 0;
index = 0;
#if ( defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__) )
errno = 0;
while (bytesRead != -1 && errno != EAGAIN) {
#elif defined(__OS_WINDOWS__)
while (bytesRead != SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) {
#endif
while ( index < bytesRead ) {
line += buffer[index];
if ( buffer[index++] == '\n' ) {
data->mutex.lock();
if ( line.compare(0, 4, "Exit") == 0 || line.compare(0, 4, "exit") == 0 ) {
// Ignore this line and assume the connection will be
// closed on a subsequent read call.
;
}
else if ( data->skini.parseString( line, message ) )
data->queue.push( message );
data->mutex.unlock();
line.erase();
}
}
index = 0;
bytesRead = Socket::readBuffer(fd[i], buffer, bufferSize, 0);
if (bytesRead == 0) {
// This socket connection closed.
FD_CLR( fd[i], &data->mask );
Socket::close( fd[i] );
fdclose.push_back( fd[i] );
}
}
}
// Now remove descriptors for closed connections.
for ( i=0; i<fdclose.size(); i++ ) {
for ( unsigned int j=0; j<fd.size(); j++ ) {
if ( fd[j] == fdclose[i] ) {
fd.erase( fd.begin() + j );
break;
}
}
// Check to see whether all connections are closed. Note that
// the server descriptor will always remain.
if ( fd.size() == 1 ) {
data->sources &= ~STK_SOCKET;
if ( data->sources & STK_MIDI )
std::cout << "MIDI input still running ... type 'exit<cr>' to quit.\n" << std::endl;
else if ( !(data->sources & STK_STDIN) ) {
// No stdin thread running, so quit now.
message.type = __SK_Exit_;
data->queue.push( message );
}
}
fdclose.clear();
}
// Wait until we're below the queue limit.
while ( data->queue.size() >= data->queueLimit ) Stk::sleep( 50 );
}
delete s;
return NULL;
}
#endif // __STK_REALTIME__
#endif

359
src/MidiFileIn.cpp Normal file
View File

@@ -0,0 +1,359 @@
/**********************************************************************/
/*! \class MidiFileIn
\brief A standard MIDI file reading/parsing class.
This class can be used to read events from a standard MIDI file.
Event bytes are copied to a C++ vector and must be subsequently
interpreted by the user. The function getNextMidiEvent() skips
meta and sysex events, returning only MIDI channel messages.
Event delta-times are returned in the form of "ticks" and a
function is provided to determine the current "seconds per tick".
Tempo changes are internally tracked by the class and reflected in
the values returned by the function getTickSeconds().
by Gary P. Scavone, 2003.
*/
/**********************************************************************/
#include "MidiFileIn.h"
#include <iostream>
MidiFileIn :: MidiFileIn( std::string fileName )
{
// Attempt to open the file.
file_.open( fileName.c_str(), std::ios::in );
if ( !file_ ) {
errorString_ << "MidiFileIn: error opening or finding file (" << fileName << ").";
handleError( StkError::FILE_NOT_FOUND );
}
// Parse header info.
char chunkType[4];
char buffer[4];
SINT32 *length;
if ( !file_.read( chunkType, 4 ) ) goto error;
if ( !file_.read( buffer, 4 ) ) goto error;
#ifdef __LITTLE_ENDIAN__
swap32((unsigned char *)&buffer);
#endif
length = (SINT32 *) &buffer;
if ( strncmp( chunkType, "MThd", 4 ) || ( *length != 6 ) ) {
errorString_ << "MidiFileIn: file (" << fileName << ") does not appear to be a MIDI file!";
handleError( StkError::FILE_UNKNOWN_FORMAT );
}
// Read the MIDI file format.
SINT16 *data;
if ( !file_.read( buffer, 2 ) ) goto error;
#ifdef __LITTLE_ENDIAN__
swap16((unsigned char *)&buffer);
#endif
data = (SINT16 *) &buffer;
if ( *data < 0 || *data > 2 ) {
errorString_ << "MidiFileIn: the file (" << fileName << ") format is invalid!";
handleError( StkError::FILE_ERROR );
}
format_ = *data;
// Read the number of tracks.
if ( !file_.read( buffer, 2 ) ) goto error;
#ifdef __LITTLE_ENDIAN__
swap16((unsigned char *)&buffer);
#endif
if ( format_ == 0 && *data != 1 ) {
errorString_ << "MidiFileIn: invalid number of tracks (>1) for a file format = 0!";
handleError( StkError::FILE_ERROR );
}
nTracks_ = *data;
// Read the beat division.
if ( !file_.read( buffer, 2 ) ) goto error;
#ifdef __LITTLE_ENDIAN__
swap16((unsigned char *)&buffer);
#endif
division_ = (int) *data;
double tickrate;
usingTimeCode_ = false;
if ( *data & 0x8000 ) {
// Determine ticks per second from time-code formats.
tickrate = (double) -(*data & 0x7F00);
// If frames per second value is 29, it really should be 29.97.
if ( tickrate == 29.0 ) tickrate = 29.97;
tickrate *= (*data & 0x00FF);
usingTimeCode_ = true;
}
else {
tickrate = (double) (*data & 0x7FFF); // ticks per quarter note
}
// Now locate the track offsets and lengths. If not using time
// code, we can initialize the "tick time" using a default tempo of
// 120 beats per minute. We will then check for tempo meta-events
// afterward.
for ( unsigned int i=0; i<nTracks_; i++ ) {
if ( !file_.read( chunkType, 4 ) ) goto error;
if ( strncmp( chunkType, "MTrk", 4 ) ) goto error;
if ( !file_.read( buffer, 4 ) ) goto error;
#ifdef __LITTLE_ENDIAN__
swap32((unsigned char *)&buffer);
#endif
length = (SINT32 *) &buffer;
trackLengths_.push_back( *length );
trackOffsets_.push_back( (long) file_.tellg() );
trackPointers_.push_back( (long) file_.tellg() );
trackStatus_.push_back( 0 );
file_.seekg( *length, std::ios_base::cur );
if ( usingTimeCode_ ) tickSeconds_.push_back( (double) (1.0 / tickrate) );
else tickSeconds_.push_back( (double) (0.5 / tickrate) );
}
// Save the initial tickSeconds parameter.
TempoChange tempoEvent;
tempoEvent.count = 0;
tempoEvent.tickSeconds = tickSeconds_[0];
tempoEvents_.push_back( tempoEvent );
// If format 1 and not using time code, parse and save the tempo map
// on track 0.
if ( format_ == 1 && !usingTimeCode_ ) {
std::vector<unsigned char> event;
unsigned long value, count;
// We need to temporarily change the usingTimeCode_ value here so
// that the getNextEvent() function doesn't try to check the tempo
// map (which we're creating here).
usingTimeCode_ = true;
count = getNextEvent( &event, 0 );
while ( event.size() ) {
if ( ( event.size() == 6 ) && ( event[0] == 0xff ) &&
( event[1] == 0x51 ) && ( event[2] == 0x03 ) ) {
tempoEvent.count = count;
value = ( event[3] << 16 ) + ( event[4] << 8 ) + event[5];
tempoEvent.tickSeconds = (double) (0.000001 * value / tickrate);
if ( count > tempoEvents_.back().count )
tempoEvents_.push_back( tempoEvent );
else
tempoEvents_.back() = tempoEvent;
}
count += getNextEvent( &event, 0 );
}
rewindTrack( 0 );
for ( unsigned int i=0; i<nTracks_; i++ ) {
trackCounters_.push_back( 0 );
trackTempoIndex_.push_back( 0 );
}
// Change the time code flag back!
usingTimeCode_ = false;
}
return;
error:
errorString_ << "MidiFileIn: error reading from file (" << fileName << ").";
handleError( StkError::FILE_ERROR );
}
MidiFileIn :: ~MidiFileIn()
{
// An ifstream object implicitly closes itself during destruction
// but we'll make an explicit call to "close" anyway.
file_.close();
}
int MidiFileIn :: getFileFormat() const
{
return format_;
}
unsigned int MidiFileIn :: getNumberOfTracks() const
{
return nTracks_;
}
int MidiFileIn :: getDivision() const
{
return division_;
}
void MidiFileIn :: rewindTrack( unsigned int track )
{
if ( track >= nTracks_ ) {
errorString_ << "MidiFileIn::getNextEvent: invalid track argument (" << track << ").";
handleError( StkError::FUNCTION_ARGUMENT );
}
trackPointers_[track] = trackOffsets_[track];
trackStatus_[track] = 0;
tickSeconds_[track] = tempoEvents_[0].tickSeconds;
}
double MidiFileIn :: getTickSeconds( unsigned int track )
{
// Return the current tick value in seconds for the given track.
if ( track >= nTracks_ ) {
errorString_ << "MidiFileIn::getTickSeconds: invalid track argument (" << track << ").";
handleError( StkError::FUNCTION_ARGUMENT );
}
return tickSeconds_[track];
}
unsigned long MidiFileIn :: getNextEvent( std::vector<unsigned char> *event, unsigned int track )
{
// Fill the user-provided vector with the next event in the
// specified track (default = 0) and return the event delta time in
// ticks. This function assumes that the stored track pointer is
// positioned at the start of a track event. If the track has
// reached its end, the event vector size will be zero.
//
// If we have a format 0 or 2 file and we're not using timecode, we
// should check every meta-event for tempo changes and make
// appropriate updates to the tickSeconds_ parameter if so.
//
// If we have a format 1 file and we're not using timecode, keep a
// running sum of ticks for each track and update the tickSeconds_
// parameter as needed based on the stored tempo map.
if ( track >= nTracks_ ) {
errorString_ << "MidiFileIn::getNextEvent: invalid track argument (" << track << ").";
handleError( StkError::FUNCTION_ARGUMENT );
}
event->clear();
// Check for the end of the track.
if ( (trackPointers_[track] - trackOffsets_[track]) >= trackLengths_[track] )
return 0;
unsigned long ticks = 0, bytes = 0;
bool isTempoEvent = false;
// Read the event delta time.
file_.seekg( trackPointers_[track], std::ios_base::beg );
if ( !readVariableLength( &ticks ) ) goto error;
// Parse the event stream to determine the event length.
unsigned char c;
if ( !file_.read( (char *)&c, 1 ) ) goto error;
switch ( c ) {
case 0xFF: // A Meta-Event
unsigned long position;
trackStatus_[track] = 0;
event->push_back( c );
if ( !file_.read( (char *)&c, 1 ) ) goto error;
event->push_back( c );
if ( format_ != 1 && ( c == 0x51 ) ) isTempoEvent = true;
position = file_.tellg();
if ( !readVariableLength( &bytes ) ) goto error;
bytes += ( (unsigned long)file_.tellg() - position );
file_.seekg( position, std::ios_base::beg );
break;
case 0xF0 || 0xF7: // The start or continuation of a Sysex event
trackStatus_[track] = 0;
event->push_back( c );
position = file_.tellg();
if ( !readVariableLength( &bytes ) ) goto error;
bytes += ( (unsigned long)file_.tellg() - position );
file_.seekg( position, std::ios_base::beg );
break;
default: // Should be a MIDI channel event
if ( c & 0x80 ) { // MIDI status byte
if ( c > 0xF0 ) goto error;
trackStatus_[track] = c;
event->push_back( c );
c &= 0xF0;
if ( (c == 0xC0) || (c == 0xD0) ) bytes = 1;
else bytes = 2;
}
else if ( trackStatus_[track] & 0x80 ) { // Running status
event->push_back( trackStatus_[track] );
event->push_back( c );
c = trackStatus_[track] & 0xF0;
if ( (c != 0xC0) && (c != 0xD0) ) bytes = 1;
}
else goto error;
}
// Read the rest of the event into the event vector.
for ( unsigned long i=0; i<bytes; i++ ) {
if ( !file_.read( (char *)&c, 1 ) ) goto error;
event->push_back( c );
}
if ( !usingTimeCode_ ) {
if ( isTempoEvent ) {
// Parse the tempo event and update tickSeconds_[track].
double tickrate = (double) (division_ & 0x7FFF);
unsigned long value = ( event->at(3) << 16 ) + ( event->at(4) << 8 ) + event->at(5);
tickSeconds_[track] = (double) (0.000001 * value / tickrate);
}
if ( format_ == 1 ) {
// Update track counter and check the tempo map.
trackCounters_[track] += ticks;
TempoChange tempoEvent = tempoEvents_[ trackTempoIndex_[track] ];
if ( trackCounters_[track] >= tempoEvent.count ) {
trackTempoIndex_[track]++;
tickSeconds_[track] = tempoEvent.tickSeconds;
}
}
}
// Save the current track pointer value.
trackPointers_[track] = file_.tellg();
return ticks;
error:
errorString_ << "MidiFileIn::getNextEvent: file read error!";
handleError( StkError::FILE_ERROR );
return 0;
}
unsigned long MidiFileIn :: getNextMidiEvent( std::vector<unsigned char> *midiEvent, unsigned int track )
{
// Fill the user-provided vector with the next MIDI event in the
// specified track (default = 0) and return the event delta time in
// ticks. Meta-Events preceeding this event are skipped and ignored.
if ( track >= nTracks_ ) {
errorString_ << "MidiFileIn::getNextMidiEvent: invalid track argument (" << track << ").";
handleError( StkError::FUNCTION_ARGUMENT );
}
unsigned long ticks = getNextEvent( midiEvent, track );
while ( midiEvent->size() && ( midiEvent->at(0) >= 0xF0 ) ) {
//for ( unsigned int i=0; i<midiEvent->size(); i++ )
//std::cout << "event byte = " << i << ", value = " << (int)midiEvent->at(i) << std::endl;
ticks = getNextEvent( midiEvent, track );
}
//for ( unsigned int i=0; i<midiEvent->size(); i++ )
//std::cout << "event byte = " << i << ", value = " << (int)midiEvent->at(i) << std::endl;
return ticks;
}
bool MidiFileIn :: readVariableLength( unsigned long *value )
{
// It is assumed that this function is called with the file read
// pointer positioned at the start of a variable-length value. The
// function returns "true" if the value is successfully parsed and
// "false" otherwise.
*value = 0;
char c;
if ( !file_.read( &c, 1 ) ) return false;
*value = (unsigned long) c;
if ( *value & 0x80 ) {
*value &= 0x7f;
do {
if ( !file_.read( &c, 1 ) ) return false;
*value = ( *value << 7 ) + ( c & 0x7f );
} while ( c & 0x80 );
}
return true;
}

View File

@@ -7,216 +7,216 @@
(non-sweeping BiQuad filters), where N is set
during instantiation.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Modal.h"
#include <stdlib.h>
Modal :: Modal(int modes)
: nModes(modes)
Modal :: Modal(unsigned int modes)
: nModes_(modes)
{
if ( nModes <= 0 ) {
char msg[256];
sprintf(msg, "Modal: Invalid number of modes (%d) argument to constructor!", modes);
handleError(msg, StkError::FUNCTION_ARGUMENT);
if ( nModes_ == 0 ) {
errorString_ << "Modal: 'modes' argument to constructor is zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
// We don't make the excitation wave here yet, because we don't know
// what it's going to be.
ratios = (MY_FLOAT *) new MY_FLOAT[nModes];
radii = (MY_FLOAT *) new MY_FLOAT[nModes];
filters = (BiQuad **) calloc( nModes, sizeof(BiQuad *) );
for (int i=0; i<nModes; i++ ) {
filters[i] = new BiQuad;
filters[i]->setEqualGainZeroes();
ratios_.resize( nModes_ );
radii_.resize( nModes_ );
filters_ = (BiQuad **) calloc( nModes_, sizeof(BiQuad *) );
for (unsigned int i=0; i<nModes_; i++ ) {
filters_[i] = new BiQuad;
filters_[i]->setEqualGainZeroes();
}
envelope = new Envelope;
onepole = new OnePole;
// Concatenate the STK rawwave path to the rawwave file
vibrato = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
vibrato_ = new WaveLoop( Stk::rawwavePath() + "sinewave.raw", true );
// Set some default values.
vibrato->setFrequency( 6.0 );
vibratoGain = 0.0;
directGain = 0.0;
masterGain = 1.0;
baseFrequency = 440.0;
vibrato_->setFrequency( 6.0 );
vibratoGain_ = 0.0;
directGain_ = 0.0;
masterGain_ = 1.0;
baseFrequency_ = 440.0;
this->clear();
stickHardness = 0.5;
strikePosition = 0.561;
stickHardness_ = 0.5;
strikePosition_ = 0.561;
}
Modal :: ~Modal()
{
delete envelope;
delete onepole;
delete vibrato;
delete vibrato_;
delete [] ratios;
delete [] radii;
for (int i=0; i<nModes; i++ ) {
delete filters[i];
for (unsigned int i=0; i<nModes_; i++ ) {
delete filters_[i];
}
free(filters);
free(filters_);
}
void Modal :: clear()
{
onepole->clear();
for (int i=0; i<nModes; i++ )
filters[i]->clear();
onepole_.clear();
for (unsigned int i=0; i<nModes_; i++ )
filters_[i]->clear();
}
void Modal :: setFrequency(MY_FLOAT frequency)
void Modal :: setFrequency(StkFloat frequency)
{
baseFrequency = frequency;
for (int i=0; i<nModes; i++ )
this->setRatioAndRadius(i, ratios[i], radii[i]);
baseFrequency_ = frequency;
for (unsigned int i=0; i<nModes_; i++ )
this->setRatioAndRadius( i, ratios_[i], radii_[i] );
}
void Modal :: setRatioAndRadius(int modeIndex, MY_FLOAT ratio, MY_FLOAT radius)
void Modal :: setRatioAndRadius(unsigned int modeIndex, StkFloat ratio, StkFloat radius)
{
if ( modeIndex < 0 ) {
std::cerr << "Modal: setRatioAndRadius modeIndex parameter is less than zero!" << std::endl;
return;
}
else if ( modeIndex >= nModes ) {
std::cerr << "Modal: setRatioAndRadius modeIndex parameter is greater than the number of operators!" << std::endl;
if ( modeIndex >= nModes_ ) {
errorString_ << "Modal::setRatioAndRadius: modeIndex parameter is greater than number of modes!";
handleError( StkError::WARNING );
return;
}
MY_FLOAT nyquist = Stk::sampleRate() / 2.0;
MY_FLOAT temp;
StkFloat nyquist = Stk::sampleRate() / 2.0;
StkFloat temp;
if (ratio * baseFrequency < nyquist) {
ratios[modeIndex] = ratio;
if ( ratio * baseFrequency_ < nyquist ) {
ratios_[modeIndex] = ratio;
}
else {
temp = ratio;
while (temp * baseFrequency > nyquist) temp *= (MY_FLOAT) 0.5;
ratios[modeIndex] = temp;
while (temp * baseFrequency_ > nyquist) temp *= 0.5;
ratios_[modeIndex] = temp;
#if defined(_STK_DEBUG_)
std::cerr << "Modal : Aliasing would occur here ... correcting." << std::endl;
errorString_ << "Modal::setRatioAndRadius: aliasing would occur here ... correcting.";
handleError( StkError::DEBUG_WARNING );
#endif
}
radii[modeIndex] = radius;
radii_[modeIndex] = radius;
if (ratio < 0)
temp = -ratio;
else
temp = ratio*baseFrequency;
temp = ratio * baseFrequency_;
filters[modeIndex]->setResonance(temp, radius);
filters_[modeIndex]->setResonance(temp, radius);
}
void Modal :: setMasterGain(MY_FLOAT aGain)
void Modal :: setMasterGain(StkFloat aGain)
{
masterGain = aGain;
masterGain_ = aGain;
}
void Modal :: setDirectGain(MY_FLOAT aGain)
void Modal :: setDirectGain(StkFloat aGain)
{
directGain = aGain;
directGain_ = aGain;
}
void Modal :: setModeGain(int modeIndex, MY_FLOAT gain)
void Modal :: setModeGain(unsigned int modeIndex, StkFloat gain)
{
if ( modeIndex < 0 ) {
std::cerr << "Modal: setModeGain modeIndex parameter is less than zero!" << std::endl;
return;
}
else if ( modeIndex >= nModes ) {
std::cerr << "Modal: setModeGain modeIndex parameter is greater than the number of operators!" << std::endl;
if ( modeIndex >= nModes_ ) {
errorString_ << "Modal::setModeGain: modeIndex parameter is greater than number of modes!";
handleError( StkError::WARNING );
return;
}
filters[modeIndex]->setGain(gain);
filters_[modeIndex]->setGain(gain);
}
void Modal :: strike(MY_FLOAT amplitude)
void Modal :: strike(StkFloat amplitude)
{
MY_FLOAT gain = amplitude;
StkFloat gain = amplitude;
if ( amplitude < 0.0 ) {
std::cerr << "Modal: strike amplitude is less than zero!" << std::endl;
errorString_ << "Modal::strike: amplitude is less than zero ... setting to zero!";
handleError( StkError::WARNING );
gain = 0.0;
}
else if ( amplitude > 1.0 ) {
std::cerr << "Modal: strike amplitude is greater than 1.0!" << std::endl;
errorString_ << "Modal::strike: amplitude is greater than one ... setting to 1.0!";
handleError( StkError::WARNING );
gain = 1.0;
}
envelope->setRate(1.0);
envelope->setTarget(gain);
onepole->setPole(1.0 - gain);
envelope->tick();
wave->reset();
envelope_.setRate( 1.0 );
envelope_.setTarget( gain );
onepole_.setPole( 1.0 - gain );
envelope_.tick();
wave_->reset();
MY_FLOAT temp;
for (int i=0; i<nModes; i++) {
if (ratios[i] < 0)
temp = -ratios[i];
StkFloat temp;
for (unsigned int i=0; i<nModes_; i++) {
if (ratios_[i] < 0)
temp = -ratios_[i];
else
temp = ratios[i] * baseFrequency;
filters[i]->setResonance(temp, radii[i]);
temp = ratios_[i] * baseFrequency_;
filters_[i]->setResonance(temp, radii_[i]);
}
}
void Modal :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Modal :: noteOn(StkFloat frequency, StkFloat amplitude)
{
this->strike(amplitude);
this->setFrequency(frequency);
#if defined(_STK_DEBUG_)
std::cerr << "Modal: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Modal::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Modal :: noteOff(MY_FLOAT amplitude)
void Modal :: noteOff(StkFloat amplitude)
{
// This calls damp, but inverts the meaning of amplitude (high
// amplitude means fast damping).
this->damp(1.0 - (amplitude * 0.03));
this->damp( 1.0 - (amplitude * 0.03) );
#if defined(_STK_DEBUG_)
std::cerr << "Modal: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Modal::NoteOff: amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Modal :: damp(MY_FLOAT amplitude)
void Modal :: damp(StkFloat amplitude)
{
MY_FLOAT temp;
for (int i=0; i<nModes; i++) {
if (ratios[i] < 0)
temp = -ratios[i];
StkFloat temp;
for (unsigned int i=0; i<nModes_; i++) {
if (ratios_[i] < 0)
temp = -ratios_[i];
else
temp = ratios[i] * baseFrequency;
filters[i]->setResonance(temp, radii[i]*amplitude);
temp = ratios_[i] * baseFrequency_;
filters_[i]->setResonance(temp, radii_[i]*amplitude);
}
}
MY_FLOAT Modal :: tick()
StkFloat Modal :: tick()
{
MY_FLOAT temp = masterGain * onepole->tick(wave->tick() * envelope->tick());
StkFloat temp = masterGain_ * onepole_.tick( wave_->tick() * envelope_.tick() );
MY_FLOAT temp2 = 0.0;
for (int i=0; i<nModes; i++)
temp2 += filters[i]->tick(temp);
StkFloat temp2 = 0.0;
for (unsigned int i=0; i<nModes_; i++)
temp2 += filters_[i]->tick(temp);
temp2 -= temp2 * directGain;
temp2 += directGain * temp;
temp2 -= temp2 * directGain_;
temp2 += directGain_ * temp;
if (vibratoGain != 0.0) {
if (vibratoGain_ != 0.0) {
// Calculate AM and apply to master out
temp = 1.0 + (vibrato->tick() * vibratoGain);
temp = 1.0 + (vibrato_->tick() * vibratoGain_);
temp2 = temp * temp2;
}
lastOutput = temp2;
return lastOutput;
lastOutput_ = temp2;
return lastOutput_;
}
StkFloat *Modal :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Modal :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

View File

@@ -9,9 +9,9 @@
Control Change Numbers:
- Stick Hardness = 2
- Stick Position = 4
- Vibrato Gain = 11
- Vibrato Frequency = 7
- Direct Stick Mix = 1
- Vibrato Gain = 1
- Vibrato Frequency = 11
- Direct Stick Mix = 8
- Volume = 128
- Modal Presets = 16
- Marimba = 0
@@ -24,7 +24,7 @@
- Two Fixed = 7
- Clump = 8
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -36,56 +36,60 @@ ModalBar :: ModalBar()
: Modal()
{
// Concatenate the STK rawwave path to the rawwave file
wave = new WvIn( (Stk::rawwavePath() + "marmstk1.raw").c_str(), TRUE );
wave->setRate((MY_FLOAT) 0.5 * 22050.0 / Stk::sampleRate() );
wave_ = new WvIn( (Stk::rawwavePath() + "marmstk1.raw").c_str(), true );
wave_->setRate( 0.5 * 22050.0 / Stk::sampleRate() );
// Set the resonances for preset 0 (marimba).
setPreset( 0 );
this->setPreset( 0 );
}
ModalBar :: ~ModalBar()
{
delete wave;
delete wave_;
}
void ModalBar :: setStickHardness(MY_FLOAT hardness)
void ModalBar :: setStickHardness(StkFloat hardness)
{
stickHardness = hardness;
stickHardness_ = hardness;
if ( hardness < 0.0 ) {
std::cerr << "ModalBar: setStickHardness parameter is less than zero!" << std::endl;
stickHardness = 0.0;
errorString_ << "ModalBar::setStickHardness: parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
stickHardness_ = 0.0;
}
else if ( hardness > 1.0 ) {
std::cerr << "ModalBar: setStickHarness parameter is greater than 1.0!" << std::endl;
stickHardness = 1.0;
errorString_ << "ModalBar::setStickHarness: parameter is greater than one ... setting to 1.0!";
handleError( StkError::WARNING );
stickHardness_ = 1.0;
}
wave->setRate( (0.25 * (MY_FLOAT) pow(4.0, stickHardness)) );
masterGain = 0.1 + (1.8 * stickHardness);
wave_->setRate( (0.25 * pow(4.0, stickHardness_) ) );
masterGain_ = 0.1 + (1.8 * stickHardness_);
}
void ModalBar :: setStrikePosition(MY_FLOAT position)
void ModalBar :: setStrikePosition(StkFloat position)
{
strikePosition = position;
strikePosition_ = position;
if ( position < 0.0 ) {
std::cerr << "ModalBar: setStrikePositions parameter is less than zero!" << std::endl;
strikePosition = 0.0;
errorString_ << "ModalBar::setStrikePosition: parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
strikePosition_ = 0.0;
}
else if ( position > 1.0 ) {
std::cerr << "ModalBar: setStrikePosition parameter is greater than 1.0!" << std::endl;
strikePosition = 1.0;
errorString_ << "ModalBar::setStrikePosition: parameter is greater than one ... setting to 1.0!";
handleError( StkError::WARNING );
strikePosition_ = 1.0;
}
// Hack only first three modes.
MY_FLOAT temp2 = position * PI;
MY_FLOAT temp = sin(temp2);
StkFloat temp2 = position * PI;
StkFloat temp = sin(temp2);
this->setModeGain(0, 0.12 * temp);
temp = sin(0.05 + (3.9 * temp2));
this->setModeGain(1,(MY_FLOAT) -0.03 * temp);
this->setModeGain(1, -0.03 * temp);
temp = (MY_FLOAT) sin(-0.05 + (11 * temp2));
this->setModeGain(2,(MY_FLOAT) 0.11 * temp);
temp = sin(-0.05 + (11 * temp2));
this->setModeGain(2, 0.11 * temp);
}
void ModalBar :: setPreset(int preset)
@@ -97,7 +101,7 @@ void ModalBar :: setPreset(int preset)
// Third line: mode volumes
// Fourth line: stickHardness, strikePosition, and direct stick
// gain (mixed directly into the output
static MY_FLOAT presets[9][4][4] = {
static StkFloat presets[9][4][4] = {
{{1.0, 3.99, 10.65, -2443}, // Marimba
{0.9996, 0.9994, 0.9994, 0.999},
{0.04, 0.01, 0.01, 0.008},
@@ -137,31 +141,33 @@ void ModalBar :: setPreset(int preset)
};
int temp = (preset % 9);
for (int i=0; i<nModes; i++) {
for (unsigned int i=0; i<nModes_; i++) {
this->setRatioAndRadius(i, presets[temp][0][i], presets[temp][1][i]);
this->setModeGain(i, presets[temp][2][i]);
}
this->setStickHardness(presets[temp][3][0]);
this->setStrikePosition(presets[temp][3][1]);
directGain = presets[temp][3][2];
directGain_ = presets[temp][3][2];
if (temp == 1) // vibraphone
vibratoGain = 0.2;
vibratoGain_ = 0.2;
else
vibratoGain = 0.0;
vibratoGain_ = 0.0;
}
void ModalBar :: controlChange(int number, MY_FLOAT value)
void ModalBar :: controlChange(int number, StkFloat value)
{
MY_FLOAT norm = value * ONE_OVER_128;
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "ModalBar: Control value less than zero!" << std::endl;
errorString_ << "ModalBar::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "ModalBar: Control value greater than 128.0!" << std::endl;
errorString_ << "ModalBar::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_StickHardness_) // 2
@@ -170,18 +176,21 @@ void ModalBar :: controlChange(int number, MY_FLOAT value)
this->setStrikePosition( norm );
else if (number == __SK_ProphesyRibbon_) // 16
this->setPreset((int) value);
else if (number == __SK_Balance_) // 8
directGain_ = norm;
else if (number == __SK_ModWheel_) // 1
directGain = norm;
else if (number == 11) // 11
vibratoGain = norm * 0.3;
else if (number == __SK_ModFrequency_) // 7
vibrato->setFrequency( norm * 12.0 );
vibratoGain_ = norm * 0.3;
else if (number == __SK_ModFrequency_) // 11
vibrato_->setFrequency( norm * 12.0 );
else if (number == __SK_AfterTouch_Cont_) // 128
envelope->setTarget( norm );
else
std::cerr << "ModalBar: Undefined Control Number (" << number << ")!!" << std::endl;
envelope_.setTarget( norm );
else {
errorString_ << "ModalBar::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "ModalBar: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "ModalBar::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -6,7 +6,7 @@
modulations to give a nice, natural human
modulation function.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -15,62 +15,58 @@
Modulate :: Modulate()
{
// Concatenate the STK rawwave path to the rawwave file
vibrato = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
vibrato->setFrequency( 6.0 );
vibratoGain = 0.04;
vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
vibrato_->setFrequency( 6.0 );
vibratoGain_ = 0.04;
noise = new SubNoise(330);
randomGain = 0.05;
noise_.setRate( 330 );
randomGain_ = 0.05;
filter = new OnePole( 0.999 );
filter->setGain( randomGain );
filter_.setPole( 0.999 );
filter_.setGain( randomGain_ );
}
Modulate :: ~Modulate()
{
delete vibrato;
delete noise;
delete filter;
delete vibrato_;
}
void Modulate :: reset()
{
lastOutput = (MY_FLOAT) 0.0;
lastOutput_ = (StkFloat) 0.0;
}
void Modulate :: setVibratoRate(MY_FLOAT aRate)
void Modulate :: setVibratoRate(StkFloat rate)
{
vibrato->setFrequency( aRate );
vibrato_->setFrequency( rate );
}
void Modulate :: setVibratoGain(MY_FLOAT aGain)
void Modulate :: setVibratoGain(StkFloat gain)
{
vibratoGain = aGain;
vibratoGain_ = gain;
}
void Modulate :: setRandomGain(MY_FLOAT aGain)
void Modulate :: setRandomGain(StkFloat gain)
{
randomGain = aGain;
filter->setGain( randomGain );
randomGain_ = gain;
filter_.setGain( randomGain_ );
}
MY_FLOAT Modulate :: tick()
StkFloat Modulate :: tick()
{
// Compute periodic and random modulations.
lastOutput = vibratoGain * vibrato->tick();
lastOutput += filter->tick( noise->tick() );
return lastOutput;
lastOutput_ = vibratoGain_ * vibrato_->tick();
lastOutput_ += filter_.tick( noise_.tick() );
return lastOutput_;
}
MY_FLOAT *Modulate :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *Modulate :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick();
return vector;
return Generator::tick( vector, vectorSize );
}
MY_FLOAT Modulate :: lastOut() const
StkFrames& Modulate :: tick( StkFrames& frames, unsigned int channel )
{
return lastOutput;
return Generator::tick( frames, channel );
}

View File

@@ -14,7 +14,7 @@
- Vibrato Gain = 1
- Gain = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -24,124 +24,133 @@
Moog :: Moog()
{
// Concatenate the STK rawwave path to the rawwave file
attacks[0] = new WvIn( (Stk::rawwavePath() + "mandpluk.raw").c_str(), TRUE );
loops[0] = new WaveLoop( (Stk::rawwavePath() + "impuls20.raw").c_str(), TRUE );
loops[1] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE ); // vibrato
loops[1]->setFrequency((MY_FLOAT) 6.122);
attacks_.push_back( new WvIn( (Stk::rawwavePath() + "mandpluk.raw").c_str(), true ) );
loops_.push_back ( new WaveLoop( (Stk::rawwavePath() + "impuls20.raw").c_str(), true ) );
loops_.push_back ( new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true ) ); // vibrato
loops_[1]->setFrequency( 6.122 );
filters[0] = new FormSwep();
filters[0]->setTargets( 0.0, 0.7 );
filters_[0].setTargets( 0.0, 0.7 );
filters_[1].setTargets( 0.0, 0.7 );
filters[1] = new FormSwep();
filters[1]->setTargets( 0.0, 0.7 );
adsr->setAllTimes((MY_FLOAT) 0.001,(MY_FLOAT) 1.5,(MY_FLOAT) 0.6,(MY_FLOAT) 0.250);
filterQ = (MY_FLOAT) 0.85;
filterRate = (MY_FLOAT) 0.0001;
modDepth = (MY_FLOAT) 0.0;
adsr_.setAllTimes( 0.001, 1.5, 0.6, 0.250 );
filterQ_ = 0.85;
filterRate_ = 0.0001;
modDepth_ = 0.0;
}
Moog :: ~Moog()
{
delete attacks[0];
delete loops[0];
delete loops[1];
delete filters[0];
delete filters[1];
}
void Moog :: setFrequency(MY_FLOAT frequency)
void Moog :: setFrequency(StkFloat frequency)
{
baseFrequency = frequency;
baseFrequency_ = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "Moog: setFrequency parameter is less than or equal to zero!" << std::endl;
baseFrequency = 220.0;
errorString_ << "Moog::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
baseFrequency_ = 220.0;
}
MY_FLOAT rate = attacks[0]->getSize() * 0.01 * baseFrequency / sampleRate();
attacks[0]->setRate( rate );
loops[0]->setFrequency(baseFrequency);
StkFloat rate = attacks_[0]->getSize() * 0.01 * baseFrequency_ / Stk::sampleRate();
attacks_[0]->setRate( rate );
loops_[0]->setFrequency( baseFrequency_ );
}
void Moog :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Moog :: noteOn(StkFloat frequency, StkFloat amplitude)
{
MY_FLOAT temp;
StkFloat temp;
this->setFrequency( frequency );
this->keyOn();
attackGain = amplitude * (MY_FLOAT) 0.5;
loopGain = amplitude;
attackGain_ = amplitude * 0.5;
loopGain_ = amplitude;
temp = filterQ + (MY_FLOAT) 0.05;
filters[0]->setStates( 2000.0, temp );
filters[1]->setStates( 2000.0, temp );
temp = filterQ_ + 0.05;
filters_[0].setStates( 2000.0, temp );
filters_[1].setStates( 2000.0, temp );
temp = filterQ + (MY_FLOAT) 0.099;
filters[0]->setTargets( frequency, temp );
filters[1]->setTargets( frequency, temp );
temp = filterQ_ + 0.099;
filters_[0].setTargets( frequency, temp );
filters_[1].setTargets( frequency, temp );
filters[0]->setSweepRate( filterRate * 22050.0 / Stk::sampleRate() );
filters[1]->setSweepRate( filterRate * 22050.0 / Stk::sampleRate() );
filters_[0].setSweepRate( filterRate_ * 22050.0 / Stk::sampleRate() );
filters_[1].setSweepRate( filterRate_ * 22050.0 / Stk::sampleRate() );
#if defined(_STK_DEBUG_)
std::cerr << "Moog: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Moog::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Moog :: setModulationSpeed(MY_FLOAT mSpeed)
void Moog :: setModulationSpeed(StkFloat mSpeed)
{
loops[1]->setFrequency(mSpeed);
loops_[1]->setFrequency( mSpeed );
}
void Moog :: setModulationDepth(MY_FLOAT mDepth)
void Moog :: setModulationDepth(StkFloat mDepth)
{
modDepth = mDepth * (MY_FLOAT) 0.5;
modDepth_ = mDepth * 0.5;
}
MY_FLOAT Moog :: tick()
StkFloat Moog :: tick()
{
MY_FLOAT temp;
StkFloat temp;
if ( modDepth != 0.0 ) {
temp = loops[1]->tick() * modDepth;
loops[0]->setFrequency( baseFrequency * (1.0 + temp) );
if ( modDepth_ != 0.0 ) {
temp = loops_[1]->tick() * modDepth_;
loops_[0]->setFrequency( baseFrequency_ * (1.0 + temp) );
}
temp = Sampler::tick();
temp = filters[0]->tick( temp );
lastOutput = filters[1]->tick( temp );
return lastOutput * 3.0;
temp = attackGain_ * attacks_[0]->tick();
temp += loopGain_ * loops_[0]->tick();
temp = filter_.tick( temp );
temp *= adsr_.tick();
temp = filters_[0].tick( temp );
lastOutput_ = filters_[1].tick( temp );
return lastOutput_ * 3.0;
}
void Moog :: controlChange(int number, MY_FLOAT value)
StkFloat *Moog :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Moog :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void Moog :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "Moog: Control value less than zero!" << std::endl;
errorString_ << "Moog::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "Moog: Control value greater than 128.0!" << std::endl;
errorString_ << "Moog::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_FilterQ_) // 2
filterQ = 0.80 + ( 0.1 * norm );
filterQ_ = 0.80 + ( 0.1 * norm );
else if (number == __SK_FilterSweepRate_) // 4
filterRate = norm * 0.0002;
filterRate_ = norm * 0.0002;
else if (number == __SK_ModFrequency_) // 11
this->setModulationSpeed( norm * 12.0 );
else if (number == __SK_ModWheel_) // 1
this->setModulationDepth( norm );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr->setTarget( norm );
else
std::cerr << "Moog: Undefined Control Number (" << number << ")!!" << std::endl;
adsr_.setTarget( norm );
else {
errorString_ << "Moog::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "Moog: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "Moog::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

100
src/Mutex.cpp Normal file
View File

@@ -0,0 +1,100 @@
/***************************************************/
/*! \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 - 2004.
*/
/***************************************************/
#include "Mutex.h"
Mutex :: Mutex()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
pthread_mutex_init(&mutex_, NULL);
pthread_cond_init(&condition_, NULL);
#elif defined(__OS_WINDOWS__)
InitializeCriticalSection(&mutex_);
condition_ = CreateEvent(NULL, // no security
true, // manual-reset
false, // non-signaled initially
NULL); // unnamed
#endif
}
Mutex :: ~Mutex()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
pthread_mutex_destroy(&mutex_);
pthread_cond_destroy(&condition_);
#elif defined(__OS_WINDOWS__)
DeleteCriticalSection(&mutex_);
CloseHandle( condition_ );
#endif
}
void Mutex :: lock()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
pthread_mutex_lock(&mutex_);
#elif defined(__OS_WINDOWS__)
EnterCriticalSection(&mutex_);
#endif
}
void Mutex :: unlock()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
pthread_mutex_unlock(&mutex_);
#elif defined(__OS_WINDOWS__)
LeaveCriticalSection(&mutex_);
#endif
}
void Mutex :: wait()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
pthread_cond_wait(&condition_, &mutex_);
#elif defined(__OS_WINDOWS__)
WaitForMultipleObjects(1, &condition_, false, INFINITE);
#endif
}
void Mutex :: signal()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
pthread_cond_signal(&condition_);
#elif defined(__OS_WINDOWS__)
SetEvent( condition_ );
#endif
}

View File

@@ -12,14 +12,14 @@
filters in parallel with corresponding right
and left outputs.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "NRev.h"
#include <math.h>
NRev :: NRev(MY_FLOAT T60)
NRev :: NRev(StkFloat T60)
{
int lengths[15] = {1433, 1601, 1867, 2053, 2251, 2399, 347, 113, 37, 59, 53, 43, 37, 29, 19};
double scaler = Stk::sampleRate() / 25641.0;
@@ -33,77 +33,94 @@ NRev :: NRev(MY_FLOAT T60)
}
for (i=0; i<6; i++) {
combDelays[i] = new Delay( lengths[i], lengths[i]);
combCoefficient[i] = pow(10.0, (-3 * lengths[i] / (T60 * Stk::sampleRate())));
combDelays_[i].setMaximumDelay( lengths[i] );
combDelays_[i].setDelay( lengths[i] );
combCoefficient_[i] = pow(10.0, (-3 * lengths[i] / (T60 * Stk::sampleRate())));
}
for (i=0; i<8; i++)
allpassDelays[i] = new Delay(lengths[i+6], lengths[i+6]);
for (i=0; i<8; i++) {
allpassDelays_[i].setMaximumDelay( lengths[i+6] );
allpassDelays_[i].setDelay( lengths[i+6] );
}
allpassCoefficient = 0.7;
effectMix = 0.3;
this->setT60( T60 );
allpassCoefficient_ = 0.7;
effectMix_ = 0.3;
this->clear();
}
NRev :: ~NRev()
{
int i;
for (i=0; i<6; i++) delete combDelays[i];
for (i=0; i<8; i++) delete allpassDelays[i];
}
void NRev :: clear()
{
int i;
for (i=0; i<6; i++) combDelays[i]->clear();
for (i=0; i<8; i++) allpassDelays[i]->clear();
lastOutput[0] = 0.0;
lastOutput[1] = 0.0;
lowpassState = 0.0;
for (i=0; i<6; i++) combDelays_[i].clear();
for (i=0; i<8; i++) allpassDelays_[i].clear();
lastOutput_[0] = 0.0;
lastOutput_[1] = 0.0;
lowpassState_ = 0.0;
}
MY_FLOAT NRev :: tick(MY_FLOAT input)
void NRev :: setT60( StkFloat T60 )
{
MY_FLOAT temp, temp0, temp1, temp2, temp3;
for ( int i=0; i<6; i++ )
combCoefficient_[i] = pow(10.0, (-3.0 * combDelays_[i].getDelay() / (T60 * Stk::sampleRate())));
}
StkFloat NRev :: tick(StkFloat input)
{
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);
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;
temp = allpassDelays_[i].lastOut();
temp1 = allpassCoefficient_ * temp;
temp1 += temp0;
allpassDelays[i]->tick(temp1);
temp0 = -(allpassCoefficient * temp1) + temp;
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;
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;
temp = allpassDelays_[4].lastOut();
temp2 = allpassCoefficient_ * temp;
temp2 += temp1;
allpassDelays[4]->tick(temp2);
lastOutput[0] = effectMix*(-(allpassCoefficient * temp2) + temp);
allpassDelays_[4].tick(temp2);
lastOutput_[0] = effectMix_*(-(allpassCoefficient_ * temp2) + temp);
temp = allpassDelays[5]->lastOut();
temp3 = allpassCoefficient * temp;
temp = allpassDelays_[5].lastOut();
temp3 = allpassCoefficient_ * temp;
temp3 += temp1;
allpassDelays[5]->tick(temp3);
lastOutput[1] = effectMix*(-(allpassCoefficient * temp3) + temp);
allpassDelays_[5].tick(temp3);
lastOutput_[1] = effectMix_*(-(allpassCoefficient_ * temp3) + temp);
temp = (1.0 - effectMix) * input;
lastOutput[0] += temp;
lastOutput[1] += temp;
temp = (1.0 - effectMix_) * input;
lastOutput_[0] += temp;
lastOutput_[1] += temp;
return (lastOutput[0] + lastOutput[1]) * 0.5;
return Effect::lastOut();
}
StkFloat *NRev :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Effect::tick( vector, vectorSize );
}
StkFrames& NRev :: tick( StkFrames& frames, unsigned int channel )
{
return Effect::tick( frames, channel );
}

View File

@@ -6,7 +6,7 @@
C rand() function. The quality of the rand()
function varies from one OS to another.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -14,18 +14,18 @@
#include <stdlib.h>
#include <time.h>
Noise :: Noise() : Stk()
Noise :: Noise() : Generator()
{
// Seed the random number generator with system time.
this->setSeed( 0 );
lastOutput = (MY_FLOAT) 0.0;
lastOutput_ = (StkFloat) 0.0;
}
Noise :: Noise( unsigned int seed ) : Stk()
Noise :: Noise( unsigned int seed ) : Generator()
{
// Seed the random number generator
this->setSeed( seed );
lastOutput = (MY_FLOAT) 0.0;
lastOutput_ = (StkFloat) 0.0;
}
Noise :: ~Noise()
@@ -40,23 +40,20 @@ void Noise :: setSeed( unsigned int seed )
srand( seed );
}
MY_FLOAT Noise :: tick()
StkFloat Noise :: tick()
{
lastOutput = (MY_FLOAT) (2.0 * rand() / (RAND_MAX + 1.0) );
lastOutput -= 1.0;
return lastOutput;
lastOutput_ = (StkFloat) (2.0 * rand() / (RAND_MAX + 1.0) );
lastOutput_ -= 1.0;
return lastOutput_;
}
MY_FLOAT *Noise :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *Noise :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick();
return vector;
return Generator::tick( vector, vectorSize );
}
MY_FLOAT Noise :: lastOut() const
StkFrames& Noise :: tick( StkFrames& frames, unsigned int channel )
{
return lastOutput;
return Generator::tick( frames, channel );
}

View File

@@ -8,7 +8,7 @@
the real axis of the z-plane while maintaining
a constant peak filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -16,24 +16,25 @@
OnePole :: OnePole() : Filter()
{
MY_FLOAT B = 0.1;
MY_FLOAT A[2] = {1.0, -0.9};
Filter::setCoefficients( 1, &B, 2, A );
std::vector<StkFloat> b(1, 0.1);
std::vector<StkFloat> a(2, 1.0);
a[1] = -0.9;
Filter::setCoefficients( b, a );
}
OnePole :: OnePole(MY_FLOAT thePole) : Filter()
OnePole :: OnePole(StkFloat thePole) : Filter()
{
MY_FLOAT B;
MY_FLOAT A[2] = {1.0, -0.9};
std::vector<StkFloat> b(1);
std::vector<StkFloat> a(2, 1.0);
a[1] = -thePole;
// Normalize coefficients for peak unity gain.
if (thePole > 0.0)
B = (MY_FLOAT) (1.0 - thePole);
b[0] = (StkFloat) (1.0 - thePole);
else
B = (MY_FLOAT) (1.0 + thePole);
b[0] = (StkFloat) (1.0 + thePole);
A[1] = -thePole;
Filter::setCoefficients( 1, &B, 2, A );
Filter::setCoefficients( b, a );
}
OnePole :: ~OnePole()
@@ -45,55 +46,57 @@ void OnePole :: clear(void)
Filter::clear();
}
void OnePole :: setB0(MY_FLOAT b0)
void OnePole :: setB0(StkFloat b0)
{
b[0] = b0;
b_[0] = b0;
}
void OnePole :: setA1(MY_FLOAT a1)
void OnePole :: setA1(StkFloat a1)
{
a[1] = a1;
a_[1] = a1;
}
void OnePole :: setPole(MY_FLOAT thePole)
void OnePole :: setPole(StkFloat thePole)
{
// Normalize coefficients for peak unity gain.
if (thePole > 0.0)
b[0] = (MY_FLOAT) (1.0 - thePole);
b_[0] = (StkFloat) (1.0 - thePole);
else
b[0] = (MY_FLOAT) (1.0 + thePole);
b_[0] = (StkFloat) (1.0 + thePole);
a[1] = -thePole;
a_[1] = -thePole;
}
void OnePole :: setGain(MY_FLOAT theGain)
void OnePole :: setGain(StkFloat gain)
{
Filter::setGain(theGain);
Filter::setGain(gain);
}
MY_FLOAT OnePole :: getGain(void) const
StkFloat OnePole :: getGain(void) const
{
return Filter::getGain();
}
MY_FLOAT OnePole :: lastOut(void) const
StkFloat OnePole :: lastOut(void) const
{
return Filter::lastOut();
}
MY_FLOAT OnePole :: tick(MY_FLOAT sample)
StkFloat OnePole :: tick(StkFloat sample)
{
inputs[0] = gain * sample;
outputs[0] = b[0] * inputs[0] - a[1] * outputs[1];
outputs[1] = outputs[0];
inputs_[0] = gain_ * sample;
outputs_[0] = b_[0] * inputs_[0] - a_[1] * outputs_[1];
outputs_[1] = outputs_[0];
return outputs[0];
return outputs_[0];
}
MY_FLOAT *OnePole :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *OnePole :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Filter::tick( vector, vectorSize );
}
StkFrames& OnePole :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
}

View File

@@ -8,7 +8,7 @@
along the real axis of the z-plane while
maintaining a constant filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -16,24 +16,24 @@
OneZero :: OneZero() : Filter()
{
MY_FLOAT B[2] = {0.5, 0.5};
MY_FLOAT A = 1.0;
Filter::setCoefficients( 2, B, 1, &A );
std::vector<StkFloat> b(2, 0.5);
std::vector<StkFloat> a(1, 1.0);
Filter::setCoefficients( b, a );
}
OneZero :: OneZero(MY_FLOAT theZero) : Filter()
OneZero :: OneZero(StkFloat theZero) : Filter()
{
MY_FLOAT B[2];
MY_FLOAT A = 1.0;
std::vector<StkFloat> b(2);
std::vector<StkFloat> a(1, 1.0);
// Normalize coefficients for unity gain.
if (theZero > 0.0)
B[0] = 1.0 / ((MY_FLOAT) 1.0 + theZero);
b[0] = 1.0 / ((StkFloat) 1.0 + theZero);
else
B[0] = 1.0 / ((MY_FLOAT) 1.0 - theZero);
b[0] = 1.0 / ((StkFloat) 1.0 - theZero);
B[1] = -theZero * B[0];
Filter::setCoefficients( 2, B, 1, &A );
b[1] = -theZero * b[0];
Filter::setCoefficients( b, a );
}
OneZero :: ~OneZero(void)
@@ -45,55 +45,57 @@ void OneZero :: clear(void)
Filter::clear();
}
void OneZero :: setB0(MY_FLOAT b0)
void OneZero :: setB0(StkFloat b0)
{
b[0] = b0;
b_[0] = b0;
}
void OneZero :: setB1(MY_FLOAT b1)
void OneZero :: setB1(StkFloat b1)
{
b[1] = b1;
b_[1] = b1;
}
void OneZero :: setZero(MY_FLOAT theZero)
void OneZero :: setZero(StkFloat theZero)
{
// Normalize coefficients for unity gain.
if (theZero > 0.0)
b[0] = 1.0 / ((MY_FLOAT) 1.0 + theZero);
b_[0] = 1.0 / ((StkFloat) 1.0 + theZero);
else
b[0] = 1.0 / ((MY_FLOAT) 1.0 - theZero);
b_[0] = 1.0 / ((StkFloat) 1.0 - theZero);
b[1] = -theZero * b[0];
b_[1] = -theZero * b_[0];
}
void OneZero :: setGain(MY_FLOAT theGain)
void OneZero :: setGain(StkFloat gain)
{
Filter::setGain(theGain);
Filter::setGain(gain);
}
MY_FLOAT OneZero :: getGain(void) const
StkFloat OneZero :: getGain(void) const
{
return Filter::getGain();
}
MY_FLOAT OneZero :: lastOut(void) const
StkFloat OneZero :: lastOut(void) const
{
return Filter::lastOut();
}
MY_FLOAT OneZero :: tick(MY_FLOAT sample)
StkFloat OneZero :: tick(StkFloat sample)
{
inputs[0] = gain * sample;
outputs[0] = b[1] * inputs[1] + b[0] * inputs[0];
inputs[1] = inputs[0];
inputs_[0] = gain_ * sample;
outputs_[0] = b_[1] * inputs_[1] + b_[0] * inputs_[0];
inputs_[1] = inputs_[0];
return outputs[0];
return outputs_[0];
}
MY_FLOAT *OneZero :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *OneZero :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Filter::tick( vector, vectorSize );
}
StkFrames& OneZero :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
}

View File

@@ -10,14 +10,14 @@
two series allpass units and two parallel comb
filters.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "PRCRev.h"
#include <math.h>
PRCRev :: PRCRev(MY_FLOAT T60)
PRCRev :: PRCRev(StkFloat T60)
{
// Delay lengths for 44100 Hz sample rate.
int lengths[4]= {353, 1097, 1777, 2137};
@@ -35,59 +35,74 @@ PRCRev :: PRCRev(MY_FLOAT T60)
}
for (i=0; i<2; i++) {
allpassDelays[i] = new Delay( lengths[i], lengths[i] );
combDelays[i] = new Delay( lengths[i+2], lengths[i+2] );
combCoefficient[i] = pow(10.0,(-3 * lengths[i+2] / (T60 * Stk::sampleRate())));
allpassDelays_[i].setMaximumDelay( lengths[i] );
allpassDelays_[i].setDelay( lengths[i] );
combDelays_[i].setMaximumDelay( lengths[i+2] );
combDelays_[i].setDelay( lengths[i+2] );
}
allpassCoefficient = 0.7;
effectMix = 0.5;
this->setT60( T60 );
allpassCoefficient_ = 0.7;
effectMix_ = 0.5;
this->clear();
}
PRCRev :: ~PRCRev()
{
delete allpassDelays[0];
delete allpassDelays[1];
delete combDelays[0];
delete combDelays[1];
}
void PRCRev :: clear()
{
allpassDelays[0]->clear();
allpassDelays[1]->clear();
combDelays[0]->clear();
combDelays[1]->clear();
lastOutput[0] = 0.0;
lastOutput[1] = 0.0;
allpassDelays_[0].clear();
allpassDelays_[1].clear();
combDelays_[0].clear();
combDelays_[1].clear();
lastOutput_[0] = 0.0;
lastOutput_[1] = 0.0;
}
MY_FLOAT PRCRev :: tick(MY_FLOAT input)
void PRCRev :: setT60( StkFloat T60 )
{
MY_FLOAT temp, temp0, temp1, temp2, temp3;
combCoefficient_[0] = pow(10.0, (-3.0 * combDelays_[0].getDelay() / (T60 * Stk::sampleRate())));
combCoefficient_[1] = pow(10.0, (-3.0 * combDelays_[1].getDelay() / (T60 * Stk::sampleRate())));
}
temp = allpassDelays[0]->lastOut();
temp0 = allpassCoefficient * temp;
StkFloat PRCRev :: tick(StkFloat input)
{
StkFloat temp, temp0, temp1, temp2, temp3;
temp = allpassDelays_[0].lastOut();
temp0 = allpassCoefficient_ * temp;
temp0 += input;
allpassDelays[0]->tick(temp0);
temp0 = -(allpassCoefficient * temp0) + temp;
allpassDelays_[0].tick(temp0);
temp0 = -(allpassCoefficient_ * temp0) + temp;
temp = allpassDelays[1]->lastOut();
temp1 = allpassCoefficient * temp;
temp = allpassDelays_[1].lastOut();
temp1 = allpassCoefficient_ * temp;
temp1 += temp0;
allpassDelays[1]->tick(temp1);
temp1 = -(allpassCoefficient * temp1) + temp;
allpassDelays_[1].tick(temp1);
temp1 = -(allpassCoefficient_ * temp1) + temp;
temp2 = temp1 + (combCoefficient[0] * combDelays[0]->lastOut());
temp3 = temp1 + (combCoefficient[1] * combDelays[1]->lastOut());
temp2 = temp1 + (combCoefficient_[0] * combDelays_[0].lastOut());
temp3 = temp1 + (combCoefficient_[1] * combDelays_[1].lastOut());
lastOutput[0] = effectMix * (combDelays[0]->tick(temp2));
lastOutput[1] = effectMix * (combDelays[1]->tick(temp3));
temp = (MY_FLOAT) (1.0 - effectMix) * input;
lastOutput[0] += temp;
lastOutput[1] += temp;
lastOutput_[0] = effectMix_ * (combDelays_[0].tick(temp2));
lastOutput_[1] = effectMix_ * (combDelays_[1].tick(temp3));
temp = (1.0 - effectMix_) * input;
lastOutput_[0] += temp;
lastOutput_[1] += temp;
return (lastOutput[0] + lastOutput[1]) * (MY_FLOAT) 0.5;
return Effect::lastOut();
}
StkFloat *PRCRev :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Effect::tick( vector, vectorSize );
}
StkFrames& PRCRev :: tick( StkFrames& frames, unsigned int channel )
{
return Effect::tick( frames, channel );
}

View File

@@ -22,7 +22,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -32,74 +32,85 @@ PercFlut :: PercFlut()
: FM()
{
// Concatenate the STK rawwave path to the rawwave files
for ( int i=0; i<3; i++ )
waves[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
waves[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), TRUE );
for ( unsigned int i=0; i<3; i++ )
waves_[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
waves_[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true );
this->setRatio(0, 1.50 * 1.000);
this->setRatio(1, 3.00 * 0.995);
this->setRatio(2, 2.99 * 1.005);
this->setRatio(3, 6.00 * 0.997);
gains[0] = __FM_gains[99];
gains[1] = __FM_gains[71];
gains[2] = __FM_gains[93];
gains[3] = __FM_gains[85];
gains_[0] = fmGains_[99];
gains_[1] = fmGains_[71];
gains_[2] = fmGains_[93];
gains_[3] = fmGains_[85];
adsr[0]->setAllTimes( 0.05, 0.05, __FM_susLevels[14], 0.05);
adsr[1]->setAllTimes( 0.02, 0.50, __FM_susLevels[13], 0.5);
adsr[2]->setAllTimes( 0.02, 0.30, __FM_susLevels[11], 0.05);
adsr[3]->setAllTimes( 0.02, 0.05, __FM_susLevels[13], 0.01);
adsr_[0]->setAllTimes( 0.05, 0.05, fmSusLevels_[14], 0.05);
adsr_[1]->setAllTimes( 0.02, 0.50, fmSusLevels_[13], 0.5);
adsr_[2]->setAllTimes( 0.02, 0.30, fmSusLevels_[11], 0.05);
adsr_[3]->setAllTimes( 0.02, 0.05, fmSusLevels_[13], 0.01);
twozero->setGain( 0.0 );
modDepth = 0.005;
twozero_.setGain( 0.0 );
modDepth_ = 0.005;
}
PercFlut :: ~PercFlut()
{
}
void PercFlut :: setFrequency(MY_FLOAT frequency)
void PercFlut :: setFrequency(StkFloat frequency)
{
baseFrequency = frequency;
baseFrequency_ = frequency;
}
void PercFlut :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void PercFlut :: noteOn(StkFloat frequency, StkFloat amplitude)
{
gains[0] = amplitude * __FM_gains[99] * 0.5;
gains[1] = amplitude * __FM_gains[71] * 0.5;
gains[2] = amplitude * __FM_gains[93] * 0.5;
gains[3] = amplitude * __FM_gains[85] * 0.5;
this->setFrequency(frequency);
gains_[0] = amplitude * fmGains_[99] * 0.5;
gains_[1] = amplitude * fmGains_[71] * 0.5;
gains_[2] = amplitude * fmGains_[93] * 0.5;
gains_[3] = amplitude * fmGains_[85] * 0.5;
this->setFrequency( frequency );
this->keyOn();
#if defined(_STK_DEBUG_)
cerr << "PercFlut: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << endl;
errorString_ << "PercFlut::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT PercFlut :: tick()
StkFloat PercFlut :: tick()
{
register MY_FLOAT temp;
register StkFloat temp;
temp = vibrato->tick() * modDepth * (MY_FLOAT) 0.2;
waves[0]->setFrequency(baseFrequency * ((MY_FLOAT) 1.0 + temp) * ratios[0]);
waves[1]->setFrequency(baseFrequency * ((MY_FLOAT) 1.0 + temp) * ratios[1]);
waves[2]->setFrequency(baseFrequency * ((MY_FLOAT) 1.0 + temp) * ratios[2]);
waves[3]->setFrequency(baseFrequency * ((MY_FLOAT) 1.0 + temp) * ratios[3]);
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();
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();
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;
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();
waves_[0]->addPhaseOffset(temp);
temp = gains_[0] * adsr_[0]->tick() * waves_[0]->tick();
lastOutput = temp * (MY_FLOAT) 0.5;
return lastOutput;
lastOutput_ = temp * 0.5;
return lastOutput_;
}
StkFloat *PercFlut :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& PercFlut :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

View File

@@ -6,7 +6,7 @@
set of 32 static phoneme formant parameters
and provide access to those values.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -24,7 +24,7 @@ const char Phonemes :: phonemeNames[32][4] =
"vvv", "zzz", "thz", "zhh"
};
const MY_FLOAT Phonemes :: phonemeGains[32][2] =
const StkFloat Phonemes :: phonemeGains[32][2] =
{{1.0, 0.0}, // eee
{1.0, 0.0}, // ihh
{1.0, 0.0}, // ehh
@@ -66,7 +66,7 @@ const MY_FLOAT Phonemes :: phonemeGains[32][2] =
{1.0, 1.0} // zhh
};
const MY_FLOAT Phonemes :: phonemeParameters[32][4][3] =
const StkFloat Phonemes :: phonemeParameters[32][4][3] =
{{ { 273, 0.996, 10}, // eee (beet)
{2086, 0.945, -16},
{2754, 0.979, -12},
@@ -215,64 +215,79 @@ Phonemes :: ~Phonemes(void)
const char *Phonemes :: name( unsigned int index )
{
if ( index > 31 ) {
std::cerr << "Phonemes: name index is greater than 31!" << std::endl;
std::ostringstream error;
error << "Phonemes::name: index is greater than 31!";
handleError( error.str(), StkError::WARNING );
return 0;
}
return phonemeNames[index];
}
MY_FLOAT Phonemes :: voiceGain( unsigned int index )
StkFloat Phonemes :: voiceGain( unsigned int index )
{
if ( index > 31 ) {
std::cerr << "Phonemes: voiceGain index is greater than 31!" << std::endl;
std::ostringstream error;
error << "Phonemes::voiceGain: index is greater than 31!";
handleError( error.str(), StkError::WARNING );
return 0.0;
}
return phonemeGains[index][0];
}
MY_FLOAT Phonemes :: noiseGain( unsigned int index )
StkFloat Phonemes :: noiseGain( unsigned int index )
{
if ( index > 31 ) {
std::cerr << "Phonemes: noiseGain index is greater than 31!" << std::endl;
std::ostringstream error;
error << "Phonemes::noiseGain: index is greater than 31!";
handleError( error.str(), StkError::WARNING );
return 0.0;
}
return phonemeGains[index][1];
}
MY_FLOAT Phonemes :: formantFrequency( unsigned int index, unsigned int partial )
StkFloat Phonemes :: formantFrequency( unsigned int index, unsigned int partial )
{
std::ostringstream error;
if ( index > 31 ) {
std::cerr << "Phonemes: formantFrequency index is greater than 31!" << std::endl;
error << "Phonemes::formantFrequency: index is greater than 31!";
handleError( error.str(), StkError::WARNING );
return 0.0;
}
if ( partial > 3 ) {
std::cerr << "Phonemes: formantFrequency partial is greater than 3!" << std::endl;
error << "Phonemes::formantFrequency: partial is greater than 3!";
handleError( error.str(), StkError::WARNING );
return 0.0;
}
return phonemeParameters[index][partial][0];
}
MY_FLOAT Phonemes :: formantRadius( unsigned int index, unsigned int partial )
StkFloat Phonemes :: formantRadius( unsigned int index, unsigned int partial )
{
std::ostringstream error;
if ( index > 31 ) {
std::cerr << "Phonemes: formantRadius index is greater than 31!" << std::endl;
error << "Phonemes::formantRadius: index is greater than 31!";
handleError( error.str(), StkError::WARNING );
return 0.0;
}
if ( partial > 3 ) {
std::cerr << "Phonemes: formantRadius partial is greater than 3!" << std::endl;
error << "Phonemes::formantRadius: partial is greater than 3!";
handleError( error.str(), StkError::WARNING );
return 0.0;
}
return phonemeParameters[index][partial][1];
}
MY_FLOAT Phonemes :: formantGain( unsigned int index, unsigned int partial )
StkFloat Phonemes :: formantGain( unsigned int index, unsigned int partial )
{
std::ostringstream error;
if ( index > 31 ) {
std::cerr << "Phonemes: formantGain index is greater than 31!" << std::endl;
error << "Phonemes::formantGain: index is greater than 31!";
handleError( error.str(), StkError::WARNING );
return 0.0;
}
if ( partial > 3 ) {
std::cerr << "Phonemes: formantGain partial is greater than 3!" << std::endl;
error << "Phonemes::formantGain: partial is greater than 3!";
handleError( error.str(), StkError::WARNING );
return 0.0;
}
return phonemeParameters[index][partial][2];

View File

@@ -5,93 +5,93 @@
This class implements a simple pitch shifter
using delay lines.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "PitShift.h"
#include <iostream>
#include <math.h>
const int maxDelay = 5024;
PitShift :: PitShift()
{
delay[0] = 12;
delay[1] = 512;
delayLine[0] = new DelayL(delay[0], (long) 1024);
delayLine[1] = new DelayL(delay[1], (long) 1024);
effectMix = (MY_FLOAT) 0.5;
rate = 1.0;
delayLength = maxDelay - 24;
halfLength = delayLength / 2;
delay_[0] = 12;
delay_[1] = maxDelay / 2;
delayLine_[0].setMaximumDelay( maxDelay );
delayLine_[0].setDelay( delay_[0] );
delayLine_[1].setMaximumDelay( maxDelay );
delayLine_[1].setDelay( delay_[1] );
effectMix_ = 0.5;
rate_ = 1.0;
}
PitShift :: ~PitShift()
{
delete delayLine[0];
delete delayLine[1];
}
void PitShift :: clear()
{
delayLine[0]->clear();
delayLine[1]->clear();
lastOutput = 0.0;
delayLine_[0].clear();
delayLine_[1].clear();
lastOutput_[0] = 0.0;
lastOutput_[1] = 0.0;
}
void PitShift :: setEffectMix(MY_FLOAT mix)
void PitShift :: setShift(StkFloat shift)
{
effectMix = mix;
if ( mix < 0.0 ) {
std::cerr << "PitShift: setEffectMix parameter is less than zero!" << std::endl;
effectMix = 0.0;
if (shift < 1.0) {
rate_ = 1.0 - shift;
}
else if ( mix > 1.0 ) {
std::cerr << "PitShift: setEffectMix parameter is greater than 1.0!" << std::endl;
effectMix = 1.0;
}
}
void PitShift :: setShift(MY_FLOAT shift)
{
if (shift < 1.0) {
rate = 1.0 - shift;
}
else if (shift > 1.0) {
rate = 1.0 - shift;
else if (shift > 1.0) {
rate_ = 1.0 - shift;
}
else {
rate = 0.0;
delay[0] = 512;
rate_ = 0.0;
delay_[0] = halfLength+12;
}
}
MY_FLOAT PitShift :: lastOut() const
StkFloat PitShift :: tick(StkFloat input)
{
return lastOutput;
// 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((long)delay_[0]);
delayLine_[1].setDelay((long)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.
lastOutput_[0] = env_[0] * delayLine_[0].tick(input);
lastOutput_[0] += env_[1] * delayLine_[1].tick(input);
// Compute effect mix and output.
lastOutput_[0] *= effectMix_;
lastOutput_[0] += (1.0 - effectMix_) * input;
lastOutput_[1] = lastOutput_[0];
return lastOutput_[0];
}
MY_FLOAT PitShift :: tick(MY_FLOAT input)
StkFloat *PitShift :: tick(StkFloat *vector, unsigned int vectorSize)
{
delay[0] = delay[0] + rate;
while (delay[0] > 1012) delay[0] -= 1000;
while (delay[0] < 12) delay[0] += 1000;
delay[1] = delay[0] + 500;
while (delay[1] > 1012) delay[1] -= 1000;
while (delay[1] < 12) delay[1] += 1000;
delayLine[0]->setDelay((long)delay[0]);
delayLine[1]->setDelay((long)delay[1]);
env[1] = fabs(delay[0] - 512) * 0.002;
env[0] = 1.0 - env[1];
lastOutput = env[0] * delayLine[0]->tick(input);
lastOutput += env[1] * delayLine[1]->tick(input);
lastOutput *= effectMix;
lastOutput += (1.0 - effectMix) * input;
return lastOutput;
return Effect::tick( vector, vectorSize );
}
MY_FLOAT *PitShift :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFrames& PitShift :: tick( StkFrames& frames, unsigned int channel )
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Effect::tick( frames, channel );
}

View File

@@ -14,114 +14,117 @@
use possibly subject to patents held by
Stanford University, Yamaha, and others.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "PluckTwo.h"
PluckTwo :: PluckTwo(MY_FLOAT lowestFrequency)
PluckTwo :: PluckTwo(StkFloat lowestFrequency)
{
length = (long) (Stk::sampleRate() / lowestFrequency + 1);
baseLoopGain = (MY_FLOAT) 0.995;
loopGain = (MY_FLOAT) 0.999;
delayLine = new DelayA((MY_FLOAT)(length / 2.0), length);
delayLine2 = new DelayA((MY_FLOAT)(length / 2.0), length);
combDelay = new DelayL((MY_FLOAT)(length / 2.0), length);
filter = new OneZero;
filter2 = new OneZero;
pluckAmplitude = (MY_FLOAT) 0.3;
pluckPosition = (MY_FLOAT) 0.4;
detuning = (MY_FLOAT) 0.995;
lastFrequency = lowestFrequency * (MY_FLOAT) 2.0;
lastLength = length * (MY_FLOAT) 0.5;
length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
lastLength_ = length_ * 0.5;
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( lastLength_ );
delayLine2_.setMaximumDelay( length_ );
delayLine2_.setDelay( lastLength_ );
combDelay_.setMaximumDelay( length_ );
combDelay_.setDelay( lastLength_ );
baseLoopGain_ = 0.995;
loopGain_ = 0.999;
pluckAmplitude_ = 0.3;
pluckPosition_ = 0.4;
detuning_ = 0.995;
lastFrequency_ = lowestFrequency * 2.0;
}
PluckTwo :: ~PluckTwo()
{
delete delayLine;
delete delayLine2;
delete combDelay;
delete filter;
delete filter2;
}
void PluckTwo :: clear()
{
delayLine->clear();
delayLine2->clear();
combDelay->clear();
filter->clear();
filter2->clear();
delayLine_.clear();
delayLine2_.clear();
combDelay_.clear();
filter_.clear();
filter2_.clear();
}
void PluckTwo :: setFrequency(MY_FLOAT frequency)
void PluckTwo :: setFrequency(StkFloat frequency)
{
lastFrequency = frequency;
if ( lastFrequency <= 0.0 ) {
std::cerr << "PluckTwo: setFrequency parameter less than or equal to zero!" << std::endl;
lastFrequency = 220.0;
lastFrequency_ = frequency;
if ( lastFrequency_ <= 0.0 ) {
errorString_ << "Clarinet::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
lastFrequency_ = 220.0;
}
// Delay = length - approximate filter delay.
lastLength = ( Stk::sampleRate() / lastFrequency);
MY_FLOAT delay = (lastLength / detuning) - (MY_FLOAT) 0.5;
lastLength_ = Stk::sampleRate() / lastFrequency_;
StkFloat delay = (lastLength_ / detuning_) - 0.5;
if ( delay <= 0.0 ) delay = 0.3;
else if ( delay > length ) delay = length;
delayLine->setDelay( delay );
else if ( delay > length_ ) delay = length_;
delayLine_.setDelay( delay );
delay = (lastLength * detuning) - (MY_FLOAT) 0.5;
delay = (lastLength_ * detuning_) - 0.5;
if ( delay <= 0.0 ) delay = 0.3;
else if ( delay > length ) delay = length;
delayLine2->setDelay( delay );
else if ( delay > length_ ) delay = length_;
delayLine2_.setDelay( delay );
loopGain = baseLoopGain + (frequency * (MY_FLOAT) 0.000005);
if ( loopGain > 1.0 ) loopGain = (MY_FLOAT) 0.99999;
loopGain_ = baseLoopGain_ + (frequency * 0.000005);
if ( loopGain_ > 1.0 ) loopGain_ = 0.99999;
}
void PluckTwo :: setDetune(MY_FLOAT detune)
void PluckTwo :: setDetune(StkFloat detune)
{
detuning = detune;
if ( detuning <= 0.0 ) {
std::cerr << "PluckTwo: setDetune parameter less than or equal to zero!" << std::endl;
detuning = 0.1;
detuning_ = detune;
if ( detuning_ <= 0.0 ) {
errorString_ << "Clarinet::setDeturn: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
detuning_ = 0.1;
}
delayLine->setDelay(( lastLength / detuning) - (MY_FLOAT) 0.5);
delayLine2->setDelay( (lastLength * detuning) - (MY_FLOAT) 0.5);
delayLine_.setDelay(( lastLength_ / detuning_) - 0.5);
delayLine2_.setDelay( (lastLength_ * detuning_) - 0.5);
}
void PluckTwo :: setFreqAndDetune(MY_FLOAT frequency, MY_FLOAT detune)
void PluckTwo :: setFreqAndDetune(StkFloat frequency, StkFloat detune)
{
detuning = detune;
this->setFrequency(frequency);
detuning_ = detune;
this->setFrequency( frequency );
}
void PluckTwo :: setPluckPosition(MY_FLOAT position)
void PluckTwo :: setPluckPosition(StkFloat position)
{
pluckPosition = position;
pluckPosition_ = position;
if ( position < 0.0 ) {
std::cerr << "PluckTwo: setPluckPosition parameter is less than zero!" << std::endl;
pluckPosition = 0.0;
errorString_ << "PluckTwo::setPluckPosition: parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
pluckPosition_ = 0.0;
}
else if ( position > 1.0 ) {
std::cerr << "PluckTwo: setPluckPosition parameter is greater than 1.0!" << std::endl;
pluckPosition = 1.0;
errorString_ << "PluckTwo::setPluckPosition: parameter is greater than one ... setting to 1.0!";
handleError( StkError::WARNING );
pluckPosition_ = 1.0;
}
}
void PluckTwo :: setBaseLoopGain(MY_FLOAT aGain)
void PluckTwo :: setBaseLoopGain(StkFloat aGain)
{
baseLoopGain = aGain;
loopGain = baseLoopGain + (lastFrequency * (MY_FLOAT) 0.000005);
if ( loopGain > 0.99999 ) loopGain = (MY_FLOAT) 0.99999;
baseLoopGain_ = aGain;
loopGain_ = baseLoopGain_ + (lastFrequency_ * 0.000005);
if ( loopGain_ > 0.99999 ) loopGain_ = 0.99999;
}
void PluckTwo :: noteOff(MY_FLOAT amplitude)
void PluckTwo :: noteOff(StkFloat amplitude)
{
loopGain = ((MY_FLOAT) 1.0 - amplitude) * (MY_FLOAT) 0.5;
loopGain_ = (1.0 - amplitude) * 0.5;
#if defined(_STK_DEBUG_)
std::cerr << "PluckTwo: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "PluckTwo::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -13,105 +13,119 @@
Stanford, bearing the names of Karplus and/or
Strong.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Plucked.h"
Plucked :: Plucked(MY_FLOAT lowestFrequency)
Plucked :: Plucked(StkFloat lowestFrequency)
{
length = (long) (Stk::sampleRate() / lowestFrequency + 1);
loopGain = (MY_FLOAT) 0.999;
delayLine = new DelayA( (MY_FLOAT)(length / 2.0), length );
loopFilter = new OneZero;
pickFilter = new OnePole;
noise = new Noise;
length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
loopGain_ = 0.999;
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( 0.5 * length_ );
this->clear();
}
Plucked :: ~Plucked()
{
delete delayLine;
delete loopFilter;
delete pickFilter;
delete noise;
}
void Plucked :: clear()
{
delayLine->clear();
loopFilter->clear();
pickFilter->clear();
delayLine_.clear();
loopFilter_.clear();
pickFilter_.clear();
}
void Plucked :: setFrequency(MY_FLOAT frequency)
void Plucked :: setFrequency(StkFloat frequency)
{
MY_FLOAT freakency = frequency;
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "Plucked: setFrequency parameter is less than or equal to zero!" << std::endl;
errorString_ << "Plucked::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
}
// Delay = length - approximate filter delay.
MY_FLOAT delay = (Stk::sampleRate() / freakency) - (MY_FLOAT) 0.5;
if (delay <= 0.0) delay = 0.3;
else if (delay > length) delay = length;
delayLine->setDelay(delay);
loopGain = 0.995 + (freakency * 0.000005);
if ( loopGain >= 1.0 ) loopGain = (MY_FLOAT) 0.99999;
StkFloat delay = (Stk::sampleRate() / freakency) - 0.5;
if ( delay <= 0.0 )
delay = 0.3;
else if ( delay > length_ )
delay = length_;
delayLine_.setDelay( delay );
loopGain_ = 0.995 + (freakency * 0.000005);
if ( loopGain_ >= 1.0 ) loopGain_ = 0.99999;
}
void Plucked :: pluck(MY_FLOAT amplitude)
void Plucked :: pluck(StkFloat amplitude)
{
MY_FLOAT gain = amplitude;
StkFloat gain = amplitude;
if ( gain > 1.0 ) {
std::cerr << "Plucked: pluck amplitude greater than 1.0!" << std::endl;
errorString_ << "Plucked::pluck: amplitude is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
gain = 1.0;
}
else if ( gain < 0.0 ) {
std::cerr << "Plucked: pluck amplitude less than zero!" << std::endl;
errorString_ << "Plucked::pluck: amplitude is < 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
gain = 0.0;
}
pickFilter->setPole((MY_FLOAT) 0.999 - (gain * (MY_FLOAT) 0.15));
pickFilter->setGain(gain * (MY_FLOAT) 0.5);
for (long i=0; i<length; i++)
pickFilter_.setPole( 0.999 - (gain * 0.15) );
pickFilter_.setGain( gain * 0.5 );
for (unsigned long i=0; i<length_; i++)
// Fill delay with noise additively with current contents.
delayLine->tick( 0.6 * delayLine->lastOut() + pickFilter->tick( noise->tick() ) );
delayLine_.tick( 0.6 * delayLine_.lastOut() + pickFilter_.tick( noise_.tick() ) );
}
void Plucked :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Plucked :: noteOn(StkFloat frequency, StkFloat amplitude)
{
this->setFrequency(frequency);
this->pluck(amplitude);
this->setFrequency( frequency );
this->pluck( amplitude );
#if defined(_STK_DEBUG_)
std::cerr << "Plucked: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Plucked::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Plucked :: noteOff(MY_FLOAT amplitude)
void Plucked :: noteOff(StkFloat amplitude)
{
loopGain = (MY_FLOAT) 1.0 - amplitude;
if ( loopGain < 0.0 ) {
std::cerr << "Plucked: noteOff amplitude greater than 1.0!" << std::endl;
loopGain = 0.0;
loopGain_ = 1.0 - amplitude;
if ( loopGain_ < 0.0 ) {
errorString_ << "Plucked::noteOff: amplitude is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
loopGain_ = 0.0;
}
else if ( loopGain > 1.0 ) {
std::cerr << "Plucked: noteOff amplitude less than or zero!" << std::endl;
loopGain = (MY_FLOAT) 0.99999;
else if ( loopGain_ > 1.0 ) {
errorString_ << "Plucked::noteOff: amplitude is < 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
loopGain_ = (StkFloat) 0.99999;
}
#if defined(_STK_DEBUG_)
std::cerr << "Plucked: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Plucked::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT Plucked :: tick()
StkFloat Plucked :: tick()
{
// Here's the whole inner loop of the instrument!!
lastOutput = delayLine->tick( loopFilter->tick( delayLine->lastOut() * loopGain ) );
lastOutput *= (MY_FLOAT) 3.0;
return lastOutput;
lastOutput_ = delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ ) );
lastOutput_ *= 3.0;
return lastOutput_;
}
StkFloat *Plucked :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Plucked :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

View File

@@ -8,7 +8,7 @@
filter with a given coefficient. Another
method is provided to create a DC blocking filter.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -17,9 +17,11 @@
PoleZero :: PoleZero() : Filter()
{
// Default setting for pass-through.
MY_FLOAT B[2] = {1.0, 0.0};
MY_FLOAT A[2] = {1.0, 0.0};
Filter::setCoefficients( 2, B, 2, A );
std::vector<StkFloat> b(2, 0.0);
std::vector<StkFloat> a(2, 0.0);
b[0] = 1.0;
a[0] = 1.0;
Filter::setCoefficients( b, a );
}
PoleZero :: ~PoleZero()
@@ -31,67 +33,68 @@ void PoleZero :: clear(void)
Filter::clear();
}
void PoleZero :: setB0(MY_FLOAT b0)
void PoleZero :: setB0(StkFloat b0)
{
b[0] = b0;
b_[0] = b0;
}
void PoleZero :: setB1(MY_FLOAT b1)
void PoleZero :: setB1(StkFloat b1)
{
b[1] = b1;
b_[1] = b1;
}
void PoleZero :: setA1(MY_FLOAT a1)
void PoleZero :: setA1(StkFloat a1)
{
a[1] = a1;
a_[1] = a1;
}
void PoleZero :: setAllpass(MY_FLOAT coefficient)
void PoleZero :: setAllpass(StkFloat coefficient)
{
b[0] = coefficient;
b[1] = 1.0;
a[0] = 1.0; // just in case
a[1] = coefficient;
b_[0] = coefficient;
b_[1] = 1.0;
a_[0] = 1.0; // just in case
a_[1] = coefficient;
}
void PoleZero :: setBlockZero(MY_FLOAT thePole)
void PoleZero :: setBlockZero(StkFloat thePole)
{
b[0] = 1.0;
b[1] = -1.0;
a[0] = 1.0; // just in case
a[1] = -thePole;
b_[0] = 1.0;
b_[1] = -1.0;
a_[0] = 1.0; // just in case
a_[1] = -thePole;
}
void PoleZero :: setGain(MY_FLOAT theGain)
void PoleZero :: setGain(StkFloat gain)
{
Filter::setGain(theGain);
Filter::setGain(gain);
}
MY_FLOAT PoleZero :: getGain(void) const
StkFloat PoleZero :: getGain(void) const
{
return Filter::getGain();
}
MY_FLOAT PoleZero :: lastOut(void) const
StkFloat PoleZero :: lastOut(void) const
{
return Filter::lastOut();
}
MY_FLOAT PoleZero :: tick(MY_FLOAT sample)
StkFloat PoleZero :: tick(StkFloat sample)
{
inputs[0] = gain * sample;
outputs[0] = b[0] * inputs[0] + b[1] * inputs[1] - a[1] * outputs[1];
inputs[1] = inputs[0];
outputs[1] = outputs[0];
inputs_[0] = gain_ * sample;
outputs_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] - a_[1] * outputs_[1];
inputs_[1] = inputs_[0];
outputs_[1] = outputs_[0];
return outputs[0];
return outputs_[0];
}
MY_FLOAT *PoleZero :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *PoleZero :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Filter::tick( vector, vectorSize );
}
StkFrames& PoleZero :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
}

View File

@@ -1,5 +1,5 @@
/***************************************************/
/*! \class ReedTabl
/*! \class ReedTable
\brief STK reed table class.
This class implements a simple one breakpoint,
@@ -13,59 +13,54 @@
Smith (1986), Hirschman, Cook, Scavone, and
others for more information.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "ReedTabl.h"
#include "ReedTable.h"
ReedTabl :: ReedTabl()
ReedTable :: ReedTable()
{
offSet = (MY_FLOAT) 0.6; // Offset is a bias, related to reed rest position.
slope = (MY_FLOAT) -0.8; // Slope corresponds loosely to reed stiffness.
offset_ = (StkFloat) 0.6; // Offset is a bias, related to reed rest position.
slope_ = (StkFloat) -0.8; // Slope corresponds loosely to reed stiffness.
}
ReedTabl :: ~ReedTabl()
ReedTable :: ~ReedTable()
{
}
void ReedTabl :: setOffset(MY_FLOAT aValue)
void ReedTable :: setOffset(StkFloat offset)
{
offSet = aValue;
offset_ = offset;
}
void ReedTabl :: setSlope(MY_FLOAT aValue)
void ReedTable :: setSlope(StkFloat slope)
{
slope = aValue;
slope_ = slope;
}
MY_FLOAT ReedTabl :: lastOut() const
{
return lastOutput;
}
MY_FLOAT ReedTabl :: tick(MY_FLOAT input)
StkFloat ReedTable :: tick(StkFloat input)
{
// The input is differential pressure across the reed.
lastOutput = offSet + (slope * input);
lastOutput_ = offset_ + (slope_ * input);
// If output is > 1, the reed has slammed shut and the
// reflection function value saturates at 1.0.
if (lastOutput > 1.0) lastOutput = (MY_FLOAT) 1.0;
if (lastOutput_ > 1.0) lastOutput_ = (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 (lastOutput < -1.0) lastOutput = (MY_FLOAT) -1.0;
return lastOutput;
if (lastOutput_ < -1.0) lastOutput_ = (StkFloat) -1.0;
return lastOutput_;
}
MY_FLOAT *ReedTabl :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *ReedTable :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Function::tick( vector, vectorSize );
}
StkFrames& ReedTable :: tick( StkFrames& frames, unsigned int channel )
{
return Function::tick( frames, channel );
}

View File

@@ -13,7 +13,7 @@
- Zero Radii = 1
- Envelope Gain = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -22,129 +22,144 @@
Resonate :: Resonate()
{
adsr = new ADSR;
noise = new Noise;
filter = new BiQuad;
poleFrequency = 4000.0;
poleRadius = 0.95;
poleFrequency_ = 4000.0;
poleRadius_ = 0.95;
// Set the filter parameters.
filter->setResonance( poleFrequency, poleRadius, TRUE );
zeroFrequency = 0.0;
zeroRadius = 0.0;
filter_.setResonance( poleFrequency_, poleRadius_, true );
zeroFrequency_ = 0.0;
zeroRadius_ = 0.0;
}
Resonate :: ~Resonate()
{
delete adsr;
delete filter;
delete noise;
}
void Resonate :: keyOn()
{
adsr->keyOn();
adsr_.keyOn();
}
void Resonate :: keyOff()
{
adsr->keyOff();
adsr_.keyOff();
}
void Resonate :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Resonate :: noteOn(StkFloat frequency, StkFloat amplitude)
{
adsr->setTarget( amplitude );
adsr_.setTarget( amplitude );
this->keyOn();
this->setResonance(frequency, poleRadius);
this->setResonance( frequency, poleRadius_ );
#if defined(_STK_DEBUG_)
std::cerr << "Resonate: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Resonate::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Resonate :: noteOff(MY_FLOAT amplitude)
void Resonate :: noteOff(StkFloat amplitude)
{
this->keyOff();
#if defined(_STK_DEBUG_)
std::cerr << "Resonate: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Resonate::NoteOff: amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Resonate :: setResonance(MY_FLOAT frequency, MY_FLOAT radius)
void Resonate :: setResonance( StkFloat frequency, StkFloat radius )
{
poleFrequency = frequency;
poleFrequency_ = frequency;
if ( frequency < 0.0 ) {
std::cerr << "Resonate: setResonance frequency parameter is less than zero!" << std::endl;
poleFrequency = 0.0;
errorString_ << "Resonate::setResonance: frequency parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
poleFrequency_ = 0.0;
}
poleRadius = radius;
poleRadius_ = radius;
if ( radius < 0.0 ) {
std::cerr << "Resonate: setResonance radius parameter is less than 0.0!" << std::endl;
poleRadius = 0.0;
std::cerr << "Resonate::setResonance: radius parameter is less than 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
poleRadius_ = 0.0;
}
else if ( radius >= 1.0 ) {
std::cerr << "Resonate: setResonance radius parameter is greater than or equal to 1.0, which is unstable!" << std::endl;
poleRadius = 0.9999;
errorString_ << "Resonate::setResonance: radius parameter is greater than or equal to 1.0, which is unstable ... correcting!";
handleError( StkError::WARNING );
poleRadius_ = 0.9999;
}
filter->setResonance( poleFrequency, poleRadius, TRUE );
filter_.setResonance( poleFrequency_, poleRadius_, true );
}
void Resonate :: setNotch(MY_FLOAT frequency, MY_FLOAT radius)
void Resonate :: setNotch(StkFloat frequency, StkFloat radius)
{
zeroFrequency = frequency;
zeroFrequency_ = frequency;
if ( frequency < 0.0 ) {
std::cerr << "Resonate: setNotch frequency parameter is less than zero!" << std::endl;
zeroFrequency = 0.0;
errorString_ << "Resonate::setNotch: frequency parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
zeroFrequency_ = 0.0;
}
zeroRadius = radius;
zeroRadius_ = radius;
if ( radius < 0.0 ) {
std::cerr << "Resonate: setNotch radius parameter is less than 0.0!" << std::endl;
zeroRadius = 0.0;
errorString_ << "Resonate::setNotch: radius parameter is less than 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
zeroRadius_ = 0.0;
}
filter->setNotch( zeroFrequency, zeroRadius );
filter_.setNotch( zeroFrequency_, zeroRadius_ );
}
void Resonate :: setEqualGainZeroes()
{
filter->setEqualGainZeroes();
filter_.setEqualGainZeroes();
}
MY_FLOAT Resonate :: tick()
StkFloat Resonate :: tick()
{
lastOutput = filter->tick(noise->tick());
lastOutput *= adsr->tick();
return lastOutput;
lastOutput_ = filter_.tick( noise_.tick() );
lastOutput_ *= adsr_.tick();
return lastOutput_;
}
void Resonate :: controlChange(int number, MY_FLOAT value)
StkFloat *Resonate :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Resonate :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void Resonate :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "Resonate: Control value less than zero!" << std::endl;
errorString_ << "Resonate::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "Resonate: Control value greater than 128.0!" << std::endl;
errorString_ << "Resonate::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == 2) // 2
setResonance( norm * Stk::sampleRate() * 0.5, poleRadius );
setResonance( norm * Stk::sampleRate() * 0.5, poleRadius_ );
else if (number == 4) // 4
setResonance( poleFrequency, norm*0.9999 );
setResonance( poleFrequency_, norm*0.9999 );
else if (number == 11) // 11
this->setNotch( norm * Stk::sampleRate() * 0.5, zeroRadius );
this->setNotch( norm * Stk::sampleRate() * 0.5, zeroRadius_ );
else if (number == 1)
this->setNotch( zeroFrequency, norm );
this->setNotch( zeroFrequency_, norm );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr->setTarget( norm );
else
std::cerr << "Resonate: Undefined Control Number (" << number << ")!!" << std::endl;
adsr_.setTarget( norm );
else {
errorString_ << "Resonate::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "Resonate: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "Resonate::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -1,60 +0,0 @@
/***************************************************/
/*! \class Reverb
\brief STK abstract reverberator parent class.
This class provides common functionality for
STK reverberator subclasses.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
*/
/***************************************************/
#include "Reverb.h"
#include <math.h>
Reverb :: Reverb()
{
}
Reverb :: ~Reverb()
{
}
void Reverb :: setEffectMix(MY_FLOAT mix)
{
effectMix = mix;
}
MY_FLOAT Reverb :: lastOut() const
{
return (lastOutput[0] + lastOutput[1]) * 0.5;
}
MY_FLOAT Reverb :: lastOutLeft() const
{
return lastOutput[0];
}
MY_FLOAT Reverb :: lastOutRight() const
{
return lastOutput[1];
}
MY_FLOAT *Reverb :: tick(MY_FLOAT *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
}
bool Reverb :: isPrime(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 */
}

View File

@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -36,74 +36,85 @@ Rhodey :: Rhodey()
: FM()
{
// Concatenate the STK rawwave path to the rawwave files
for ( int i=0; i<3; i++ )
waves[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
waves[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), TRUE );
for ( unsigned int i=0; i<3; i++ )
waves_[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
waves_[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true );
this->setRatio(0, 1.0);
this->setRatio(1, 0.5);
this->setRatio(2, 1.0);
this->setRatio(3, 15.0);
gains[0] = __FM_gains[99];
gains[1] = __FM_gains[90];
gains[2] = __FM_gains[99];
gains[3] = __FM_gains[67];
gains_[0] = fmGains_[99];
gains_[1] = fmGains_[90];
gains_[2] = fmGains_[99];
gains_[3] = fmGains_[67];
adsr[0]->setAllTimes( 0.001, 1.50, 0.0, 0.04);
adsr[1]->setAllTimes( 0.001, 1.50, 0.0, 0.04);
adsr[2]->setAllTimes( 0.001, 1.00, 0.0, 0.04);
adsr[3]->setAllTimes( 0.001, 0.25, 0.0, 0.04);
adsr_[0]->setAllTimes( 0.001, 1.50, 0.0, 0.04);
adsr_[1]->setAllTimes( 0.001, 1.50, 0.0, 0.04);
adsr_[2]->setAllTimes( 0.001, 1.00, 0.0, 0.04);
adsr_[3]->setAllTimes( 0.001, 0.25, 0.0, 0.04);
twozero->setGain((MY_FLOAT) 1.0);
twozero_.setGain( 1.0 );
}
Rhodey :: ~Rhodey()
{
}
void Rhodey :: setFrequency(MY_FLOAT frequency)
void Rhodey :: setFrequency(StkFloat frequency)
{
baseFrequency = frequency * (MY_FLOAT) 2.0;
baseFrequency_ = frequency * 2.0;
for (int i=0; i<nOperators; i++ )
waves[i]->setFrequency( baseFrequency * ratios[i] );
for (unsigned int i=0; i<nOperators_; i++ )
waves_[i]->setFrequency( baseFrequency_ * ratios_[i] );
}
void Rhodey :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Rhodey :: noteOn(StkFloat frequency, StkFloat amplitude)
{
gains[0] = amplitude * __FM_gains[99];
gains[1] = amplitude * __FM_gains[90];
gains[2] = amplitude * __FM_gains[99];
gains[3] = amplitude * __FM_gains[67];
this->setFrequency(frequency);
gains_[0] = amplitude * fmGains_[99];
gains_[1] = amplitude * fmGains_[90];
gains_[2] = amplitude * fmGains_[99];
gains_[3] = amplitude * fmGains_[67];
this->setFrequency( frequency );
this->keyOn();
#if defined(_STK_DEBUG_)
cerr << "Rhodey: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << endl;
errorString_ << "Rhodey::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT Rhodey :: tick()
StkFloat Rhodey :: tick()
{
MY_FLOAT temp, temp2;
StkFloat temp, temp2;
temp = gains[1] * adsr[1]->tick() * waves[1]->tick();
temp = temp * control1;
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_[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();
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;
temp2 = vibrato_->tick() * modDepth_;
temp = temp * (1.0 + temp2);
lastOutput = temp * 0.5;
return lastOutput;
lastOutput_ = temp * 0.5;
return lastOutput_;
}
StkFloat *Rhodey :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Rhodey :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,33 +1,40 @@
/***************************************************/
/*! \class RtDuplex
\brief STK realtime audio input/output class.
\brief STK realtime audio (blocking) input/output class.
This class provides a simplified interface to
RtAudio for realtime audio input/output. It
is also possible to achieve duplex operation
using separate RtWvIn and RtWvOut classes, but
this class ensures better input/output
syncronization.
may also be possible to achieve duplex
operation using separate RtWvIn and RtWvOut
classes, but this class ensures better
input/output synchronization.
Because this class makes use of RtAudio's
blocking input/output routines, its
performance is less robust on systems where
the audio API is callback-based (Macintosh
CoreAudio and Windows ASIO).
RtDuplex 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
and return samples produced by averaging across
sample frames, from the tickFrame() methods, which
take/return pointers to multi-channel sample frames.
single samples to all channels in a sample
frame and return samples produced by averaging
across sample frames, from the tickFrame()
methods, which take/return pointers to
multi-channel sample frames.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "RtDuplex.h"
RtDuplex :: RtDuplex(int nChannels, MY_FLOAT sampleRate, int device, int bufferFrames, int nBuffers )
RtDuplex :: RtDuplex(int nChannels, StkFloat sampleRate, int device, int bufferFrames, int nBuffers )
{
channels_ = nChannels;
bufferSize_ = bufferFrames;
RtAudioFormat format = ( sizeof(MY_FLOAT) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
audio_ = 0;
try {
@@ -41,13 +48,13 @@ RtDuplex :: RtDuplex(int nChannels, MY_FLOAT sampleRate, int device, int bufferF
try {
audio_->openStream(device, channels_, device, channels_, format,
(int)sampleRate, &bufferSize_, nBuffers);
data_ = (MY_FLOAT *) audio_->getStreamBuffer();
data_ = (StkFloat *) audio_->getStreamBuffer();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
lastOutput_ = (MY_FLOAT *) new MY_FLOAT[channels_];
lastOutput_ = (StkFloat *) new StkFloat[channels_];
for (unsigned int i=0; i<channels_; i++) lastOutput_[i] = 0.0;
counter_ = 0;
stopped_ = true;
@@ -78,19 +85,19 @@ void RtDuplex :: stop()
}
}
MY_FLOAT RtDuplex :: lastOut(void) const
StkFloat RtDuplex :: lastOut(void) const
{
if ( channels_ == 1 )
return *lastOutput_;
MY_FLOAT output = 0.0;
StkFloat output = 0.0;
for (unsigned int i=0; i<channels_; i++ ) {
output += lastOutput_[i];
}
return output / channels_;
}
MY_FLOAT RtDuplex :: tick(const MY_FLOAT sample)
StkFloat RtDuplex :: tick(const StkFloat sample)
{
if ( stopped_ )
start();
@@ -117,7 +124,7 @@ MY_FLOAT RtDuplex :: tick(const MY_FLOAT sample)
return lastOut();
}
MY_FLOAT *RtDuplex :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *RtDuplex :: tick(StkFloat *vector, unsigned int vectorSize)
{
for ( unsigned int i=0; i<vectorSize; i++ )
vector[i] = tick(vector[i]);
@@ -125,12 +132,40 @@ MY_FLOAT *RtDuplex :: tick(MY_FLOAT *vector, unsigned int vectorSize)
return vector;
}
const MY_FLOAT *RtDuplex :: lastFrame() const
StkFrames& RtDuplex :: tick( StkFrames& frames, unsigned int channel )
{
if ( channel == 0 || frames.channels() < channel ) {
errorString_ << "RtDuplex::tick(): channel argument (" << channel << ") is zero or > channels in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( frames.channels() == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[i] = tick( frames[i] );
}
else if ( frames.interleaved() ) {
unsigned int hop = frames.channels();
unsigned int index = channel - 1;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
frames[index] = tick( frames[index] );
index += hop;
}
}
else {
unsigned int iStart = (channel - 1) * frames.frames();
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[iStart + i] = tick( frames[iStart + i] );
}
return frames;
}
const StkFloat *RtDuplex :: lastFrame() const
{
return lastOutput_;
}
MY_FLOAT *RtDuplex :: tickFrame(MY_FLOAT *frameVector, unsigned int frames)
StkFloat *RtDuplex :: tickFrame(StkFloat *frameVector, unsigned int frames)
{
if ( stopped_ )
start();
@@ -161,3 +196,50 @@ MY_FLOAT *RtDuplex :: tickFrame(MY_FLOAT *frameVector, unsigned int frames)
return frameVector;
}
StkFrames& RtDuplex :: tickFrame( StkFrames& frames )
{
if ( channels_ != frames.channels() ) {
errorString_ << "RtDuplex::tickFrame(): incompatible channel value in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( stopped_ )
start();
unsigned long j, index = 0;
unsigned long k, hop = frames.frames();
for (unsigned int i=0; i<frames.frames(); i++ ) {
if (counter_ == 0) {
try {
audio_->tickStream();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
}
if ( channels_ > 1 && frames.interleaved() == false ) {
k = i;
for (j=0; j<channels_; j++) {
lastOutput_[j] = data_[index];
data_[index++] = frames[k];
frames[k] = lastOutput_[j];
k += hop;
}
}
else {
for (j=0; j<channels_; j++) {
lastOutput_[j] = data_[index];
data_[index] = frames[index];
frames[index++] = lastOutput_[j];
}
}
counter_++;
if (counter_ >= (long) bufferSize_)
counter_ = 0;
}
return frames;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/***************************************************/
/*! \class RtWvIn
\brief STK realtime audio input class.
\brief STK realtime audio (blocking) input class.
This class provides a simplified interface to
RtAudio for realtime audio input. It is a
@@ -15,17 +15,17 @@
For single-channel data, these methods return
equivalent values.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "RtWvIn.h"
RtWvIn :: RtWvIn(int nChannels, MY_FLOAT sampleRate, int device, int bufferFrames, int nBuffers )
RtWvIn :: RtWvIn(int nChannels, StkFloat sampleRate, int device, int bufferFrames, int nBuffers )
{
channels = nChannels;
channels_ = nChannels;
int size = bufferFrames;
RtAudioFormat format = ( sizeof(MY_FLOAT) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
audio_ = 0;
try {
@@ -37,17 +37,17 @@ RtWvIn :: RtWvIn(int nChannels, MY_FLOAT sampleRate, int device, int bufferFrame
// Now open a stream and get the buffer pointer.
try {
audio_->openStream(0, 0, device, channels, format,
audio_->openStream(0, 0, device, channels_, format,
(int)sampleRate, &size, nBuffers);
data = (MY_FLOAT *) audio_->getStreamBuffer();
data_ = (StkFloat *) audio_->getStreamBuffer();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
bufferSize = size;
lastOutput = (MY_FLOAT *) new MY_FLOAT[channels];
for (unsigned int i=0; i<channels; i++) lastOutput[i] = 0.0;
bufferSize_ = size;
lastOutputs_ = (StkFloat *) new StkFloat[channels_];
for (unsigned int i=0; i<channels_; i++) lastOutputs_[i] = 0.0;
counter_ = 0;
stopped_ = true;
}
@@ -57,7 +57,7 @@ RtWvIn :: ~RtWvIn()
if ( !stopped_ )
audio_->stopStream();
delete audio_;
data = 0; // RtAudio deletes the buffer itself.
data_ = 0; // RtAudio deletes the buffer itself.
}
void RtWvIn :: start()
@@ -76,34 +76,36 @@ void RtWvIn :: stop()
}
}
MY_FLOAT RtWvIn :: lastOut(void) const
StkFloat RtWvIn :: lastOut(void) const
{
return WvIn::lastOut();
}
MY_FLOAT RtWvIn :: tick(void)
StkFloat RtWvIn :: tick(void)
{
tickFrame();
this->tickFrame();
return lastOut();
}
MY_FLOAT *RtWvIn :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *RtWvIn :: tick(StkFloat *vector, unsigned int vectorSize)
{
for ( unsigned int i=0; i<vectorSize; i++ )
vector[i] = tick();
return vector;
return WvIn::tick( vector, vectorSize );
}
const MY_FLOAT *RtWvIn :: lastFrame() const
StkFrames& RtWvIn :: tick( StkFrames& frames, unsigned int channel )
{
return lastOutput;
return WvIn::tick( frames, channel );
}
const MY_FLOAT *RtWvIn :: tickFrame(void)
const StkFloat *RtWvIn :: lastFrame() const
{
return lastOutputs_;
}
const StkFloat *RtWvIn :: tickFrame(void)
{
if ( stopped_ )
start();
this->start();
if (counter_ == 0) {
try {
@@ -114,18 +116,23 @@ const MY_FLOAT *RtWvIn :: tickFrame(void)
}
}
long temp = counter_ * channels;
for (unsigned int i=0; i<channels; i++)
lastOutput[i] = data[temp++];
long temp = counter_ * channels_;
for (unsigned int i=0; i<channels_; i++)
lastOutputs_[i] = data_[temp++];
counter_++;
if (counter_ >= (long) bufferSize)
if (counter_ >= (long) bufferSize_)
counter_ = 0;
return lastOutput;
return lastOutputs_;
}
MY_FLOAT *RtWvIn :: tickFrame(MY_FLOAT *frameVector, unsigned int frames)
StkFloat *RtWvIn :: tickFrame(StkFloat *frameVector, unsigned int frames)
{
return WvIn::tickFrame( frameVector, frames );
}
StkFrames& RtWvIn :: tickFrame( StkFrames& frames )
{
return WvIn::tickFrame( frames );
}

View File

@@ -1,6 +1,6 @@
/***************************************************/
/*! \class RtWvOut
\brief STK realtime audio output class.
\brief STK realtime audio (blocking) output class.
This class provides a simplified interface to
RtAudio for realtime audio output. It is a
@@ -14,19 +14,19 @@
takes a pointer to multi-channel sample
frame data.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "RtWvOut.h"
#include <iostream>
RtWvOut :: RtWvOut( unsigned int nChannels, MY_FLOAT sampleRate, int device, int bufferFrames, int nBuffers )
RtWvOut :: RtWvOut( unsigned int nChannels, StkFloat sampleRate, int device, int bufferFrames, int nBuffers )
{
// We'll let RtAudio deal with channel and srate limitations.
channels = nChannels;
channels_ = nChannels;
bufferSize_ = bufferFrames;
RtAudioFormat format = ( sizeof(MY_FLOAT) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
audio_ = 0;
try {
@@ -36,11 +36,11 @@ RtWvOut :: RtWvOut( unsigned int nChannels, MY_FLOAT sampleRate, int device, int
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
// Now open a stream and set the callback function.
// Now open a stream and get the buffer pointer.
try {
audio_->openStream(device, (int)channels, 0, 0, format,
audio_->openStream(device, (int)channels_, 0, 0, format,
(int)sampleRate, &bufferSize_, nBuffers);
data = (MY_FLOAT *) audio_->getStreamBuffer();
dataPtr_ = (StkFloat *) audio_->getStreamBuffer();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
@@ -54,7 +54,6 @@ RtWvOut :: ~RtWvOut()
if ( !stopped_ )
audio_->stopStream();
delete audio_;
data = 0;
}
void RtWvOut :: start()
@@ -75,62 +74,155 @@ void RtWvOut :: stop()
unsigned long RtWvOut :: getFrames( void ) const
{
return totalCount;
return totalCount_;
}
MY_FLOAT RtWvOut :: getTime( void ) const
StkFloat RtWvOut :: getTime( void ) const
{
return (MY_FLOAT) totalCount / Stk::sampleRate();
return (StkFloat) totalCount_ / Stk::sampleRate();
}
void RtWvOut :: tick(const MY_FLOAT sample)
void RtWvOut :: tick( const StkFloat sample )
{
if ( stopped_ )
start();
for ( unsigned int j=0; j<channels; j++ )
data[counter*channels+j] = sample;
StkFloat input = sample;
this->clipTest( input );
for ( unsigned int j=0; j<channels_; j++ )
dataPtr_[counter_*channels_+j] = input;
counter++;
totalCount++;
counter_++;
totalCount_++;
if ( counter >= (unsigned int )bufferSize_ ) {
if ( counter_ >= (unsigned int )bufferSize_ ) {
try {
audio_->tickStream();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
counter = 0;
counter_ = 0;
}
}
void RtWvOut :: tick(const MY_FLOAT *vector, unsigned int vectorSize)
void RtWvOut :: tick( const StkFloat *vector, unsigned int vectorSize )
{
for (unsigned int i=0; i<vectorSize; i++)
tick( vector[i] );
}
void RtWvOut :: tickFrame(const MY_FLOAT *frameVector, unsigned int frames)
void RtWvOut :: tick( const StkFrames& frames, unsigned int channel )
{
if ( channel == 0 || frames.channels() < channel ) {
errorString_ << "RtWvOut::tick(): channel argument (" << channel << ") is zero or > channels in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( stopped_ )
start();
if ( frames.channels() == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++ )
tick( frames[i] );
}
else if ( frames.interleaved() ) {
unsigned int hop = frames.channels();
unsigned int index = channel - 1;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
tick( frames[index] );
index += hop;
}
}
else {
unsigned int iStart = (channel - 1) * frames.frames();
for ( unsigned int i=0; i<frames.frames(); i++ )
tick( frames[iStart + i] );
}
}
void RtWvOut :: tickFrame( const StkFloat *frameVector, unsigned int frames )
{
if ( stopped_ )
start();
StkFloat sample;
for ( unsigned int i=0; i<frames; i++ ) {
for ( unsigned int j=0; j<channels; j++ ) {
data[counter*channels+j] = frameVector[i*channels+j];
for ( unsigned int j=0; j<channels_; j++ ) {
sample = frameVector[i*channels_+j];
this->clipTest( sample );
dataPtr_[counter_*channels_+j] = sample;
}
counter++;
counter_++;
totalCount_++;
if ( counter >= (unsigned int)bufferSize_ ) {
if ( counter_ >= (unsigned int)bufferSize_ ) {
try {
audio_->tickStream();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
counter = 0;
counter_ = 0;
}
}
}
void RtWvOut :: tickFrame( const StkFrames& frames )
{
if ( channels_ != frames.channels() ) {
errorString_ << "RtWvOut::tickFrame(): incompatible channel value in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( stopped_ )
start();
unsigned int j;
StkFloat sample;
if ( channels_ == 1 || frames.interleaved() ) {
unsigned long iFrames = 0, iData = counter_;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
for ( j=0; j<channels_; j++ ) {
sample = frames[iFrames++];
this->clipTest( sample );
dataPtr_[iData++] = sample;
}
counter_++;
totalCount_++;
if ( counter_ >= (unsigned int)bufferSize_ ) {
try {
audio_->tickStream();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
counter_ = 0;
}
}
}
else {
unsigned int hop = frames.frames();
unsigned long iData = counter_;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
for ( j=0; j<channels_; j++ ) {
sample = frames[i + j*hop];
this->clipTest( sample );
dataPtr_[iData++] = sample;
}
counter_++;
totalCount_++;
if ( counter_ >= (unsigned int)bufferSize_ ) {
try {
audio_->tickStream();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
counter_ = 0;
}
}
}
}

View File

@@ -1,350 +0,0 @@
/***************************************************/
/*! \class SKINI
\brief STK SKINI parsing class
This class parses SKINI formatted text
messages. It can be used to parse individual
messages or it can be passed an entire file.
The file specification is Perry's and his
alone, but it's all text so it shouldn't be to
hard to figure out.
SKINI (Synthesis toolKit Instrument Network
Interface) is like MIDI, but allows for
floating-point control changes, note numbers,
etc. The following example causes a sharp
middle C to be played with a velocity of 111.132:
noteOn 60.01 111.13
See also SKINI.txt.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
*/
/***************************************************/
#include "SKINI.h"
#include <string.h>
#include <stdlib.h>
// Constructor for use when parsing SKINI strings (coming over socket
// for example. Use parseThis() method with string pointer.
SKINI :: SKINI()
{
}
// Constructor for reading SKINI files ... use nextMessage() method.
SKINI :: SKINI(char *fileName)
{
char msg[256];
myFile = fopen(fileName,"r");
if ((int) myFile < 0) {
sprintf(msg, "SKINI: Could not open or find file (%s).", fileName);
handleError(msg, StkError::FILE_NOT_FOUND);
}
this->nextMessage();
}
SKINI :: ~SKINI()
{
}
/***************** SOME HANDY ROUTINES *******************/
#include "SKINI.tbl"
#define __SK_MAX_FIELDS_ 5
#define __SK_MAX_SIZE_ 32
short ignore(char aChar)
{
short ignoreIt = 0;
if (aChar == 0) ignoreIt = 1; // Null String Termination
if (aChar == '\n') ignoreIt = 1; // Carraige Return???
if (aChar == '/') ignoreIt = 2; // Comment Line
return ignoreIt;
}
short delimit(char aChar)
{
if (aChar == ' ' || // Space
aChar == ',' || // Or Comma
aChar == '\t') // Or Tab
return 1;
else
return 0;
}
short nextChar(char* aString)
{
int i;
for (i=0;i<__SK_MAX_SIZE_;i++) {
if ( aString[i] != ' ' && // Space
aString[i] != ',' && // Or Comma
aString[i] != '\t' ) // Or Tab
return i;
}
return 1024;
}
int subStrings(char *aString,
char someStrings[__SK_MAX_FIELDS_][__SK_MAX_SIZE_],
int somePointrs[__SK_MAX_FIELDS_],
char *remainderString)
{
int notDone,howMany,point,temp;
notDone = 1;
howMany = 0;
point = 0;
temp = nextChar(aString);
if (temp >= __SK_MAX_SIZE_) {
notDone = 0;
printf("Confusion here: Ignoring this line\n");
printf("%s\n",aString);
return howMany;
}
point = temp;
somePointrs[howMany] = point;
temp = 0;
while (notDone) {
if (aString[point] == '\n') {
notDone = 0;
}
else {
someStrings[howMany][temp++] = aString[point++];
if (temp >= __SK_MAX_SIZE_) {
howMany = 0;
return howMany;
}
if (delimit(aString[point]) || aString[point] == '\n') {
someStrings[howMany][temp] = 0;
howMany += 1;
if (howMany < __SK_MAX_FIELDS_) {
temp = nextChar(&aString[point]);
point += temp;
somePointrs[howMany-1] = point;
temp = 0;
}
else {
temp = 0;
somePointrs[howMany-1] = point;
while(aString[point] != '\n')
remainderString[temp++] = aString[point++];
remainderString[temp] = aString[point];
}
}
}
}
// printf("Got: %i Strings:\n",howMany);
// for (temp=0;temp<howMany;temp++)
// printf("%s\n",someStrings[temp]);
return howMany;
}
/**************** THE ENCHILLADA !!!! **********************/
/*** This function parses a single string (if it can) ****/
/*** of SKINI message, setting the appropriate variables ***/
/*************************************************************/
long SKINI :: parseThis(char* aString)
{
int which,aField;
int temp,temp2;
char someStrings[__SK_MAX_FIELDS_][__SK_MAX_SIZE_];
int somePointrs[__SK_MAX_FIELDS_];
temp = nextChar(aString);
if ((which = ignore(aString[temp]))) {
if (which == 2) printf("// CommentLine: %s\n",aString);
messageType = 0;
return messageType;
}
else {
temp = subStrings(aString,someStrings,somePointrs,remainderString);
if (temp > 0)
which = 0;
aField = 0;
strcpy(msgTypeString,someStrings[aField]);
while ((which < __SK_MaxMsgTypes_) &&
(strcmp(msgTypeString,
skini_msgs[which].messageString))) {
which += 1;
}
if (which >= __SK_MaxMsgTypes_) {
messageType = 0;
printf("Couldn't parse this message field: =%s\n %s\n",
msgTypeString,aString);
return messageType;
}
else {
messageType = skini_msgs[which].type;
// printf("Message Token = %s type = %i\n", msgTypeString,messageType);
}
aField += 1;
if (someStrings[aField][0] == '=') {
deltaTime = (MY_FLOAT) atof(&someStrings[aField][1]);
deltaTime = -deltaTime;
}
else {
deltaTime = (MY_FLOAT) atof(someStrings[aField]);
}
// printf("DeltaTime = %f\n",deltaTime);
aField += 1;
channel = atoi(someStrings[aField]);
// printf("Channel = %i\n",channel);
aField += 1;
if (skini_msgs[which].data2 != NOPE) {
if (skini_msgs[which].data2 == SK_INT) {
byteTwoInt = atoi(someStrings[aField]);
byteTwo = (MY_FLOAT) byteTwoInt;
}
else if (skini_msgs[which].data2 == SK_DBL) {
byteTwo = (MY_FLOAT) atof(someStrings[aField]);
byteTwoInt = (long) byteTwo;
}
else if (skini_msgs[which].data2 == SK_STR) {
temp = somePointrs[aField-1]; /* Hack Danger Here, Why -1??? */
temp2 = 0;
while (aString[temp] != '\n') {
remainderString[temp2++] = aString[temp++];
}
remainderString[temp2] = 0;
}
else {
byteTwoInt = skini_msgs[which].data2;
byteTwo = (MY_FLOAT) byteTwoInt;
aField -= 1;
}
aField += 1;
if (skini_msgs[which].data3 != NOPE) {
if (skini_msgs[which].data3 == SK_INT) {
byteThreeInt = atoi(someStrings[aField]);
byteThree = (MY_FLOAT) byteThreeInt;
}
else if (skini_msgs[which].data3 == SK_DBL) {
byteThree = (MY_FLOAT) atof(someStrings[aField]);
byteThreeInt = (long) byteThree;
}
else if (skini_msgs[which].data3 == SK_STR) {
temp = somePointrs[aField-1]; /* Hack Danger Here, Why -1??? */
temp2 = 0;
while (aString[temp] != '\n') {
remainderString[temp2++] = aString[temp++];
}
remainderString[temp2] = 0;
}
else {
byteThreeInt = skini_msgs[which].data3;
byteThree = (MY_FLOAT) byteThreeInt;
}
}
else {
byteThreeInt = byteTwoInt;
byteThree = byteTwo;
}
}
}
return messageType;
}
long SKINI :: nextMessage()
{
int notDone;
char inputString[1024];
notDone = 1;
while (notDone) {
notDone = 0;
if (!fgets(inputString,1024,myFile)) {
printf("// End of Score. Thanks for using SKINI!!\n");
messageType = -1;
return messageType;
}
else if (parseThis(inputString) == 0) {
notDone = 1;
}
}
return messageType;
}
long SKINI :: getType() const
{
return messageType;
}
long SKINI :: getChannel() const
{
return channel;
}
MY_FLOAT SKINI :: getDelta() const
{
return deltaTime;
}
MY_FLOAT SKINI :: getByteTwo() const
{
return byteTwo;
}
long SKINI :: getByteTwoInt() const
{
return byteTwoInt;
}
MY_FLOAT SKINI :: getByteThree() const
{
return byteThree;
}
long SKINI :: getByteThreeInt() const
{
return byteThreeInt;
}
const char* SKINI :: getRemainderString()
{
return remainderString;
}
const char* SKINI :: getMessageTypeString()
{
return msgTypeString;
}
const char* SKINI :: whatsThisType(long type)
{
int i = 0;
whatString[0] = 0;
for ( i=0; i<__SK_MaxMsgTypes_; i++ ) {
if ( type == skini_msgs[i].type ) {
strcat(whatString, skini_msgs[i].messageString);
strcat(whatString, ",");
}
}
return whatString;
}
const char* SKINI :: whatsThisController(long contNum)
{
int i = 0;
whatString[0] = 0;
for ( i=0; i<__SK_MaxMsgTypes_; i++) {
if ( skini_msgs[i].type == __SK_ControlChange_
&& contNum == skini_msgs[i].data2) {
strcat(whatString, skini_msgs[i].messageString);
strcat(whatString, ",");
}
}
return whatString;
}

View File

@@ -2,10 +2,10 @@
/*! \class Sampler
\brief STK sampling synthesis abstract base class.
This instrument contains up to 5 attack waves,
5 looped waves, and an ADSR envelope.
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 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -15,45 +15,40 @@ Sampler :: Sampler()
{
// We don't make the waves here yet, because
// we don't know what they will be.
adsr = new ADSR;
baseFrequency = 440.0;
filter = new OnePole;
attackGain = 0.25;
loopGain = 0.25;
whichOne = 0;
baseFrequency_ = 440.0;
attackGain_ = 0.25;
loopGain_ = 0.25;
}
Sampler :: ~Sampler()
{
delete adsr;
delete filter;
unsigned int i;
for ( i=0; i<attacks_.size(); i++ ) delete attacks_[i];
for ( i=0; i<loops_.size(); i++ ) delete loops_[i];
}
void Sampler :: keyOn()
{
adsr->keyOn();
attacks[0]->reset();
// Reset all attack waves.
for ( unsigned int i=0; i<attacks_.size(); i++ )
attacks_[i]->reset();
// Start the envelope.
adsr_.keyOn();
}
void Sampler :: keyOff()
{
adsr->keyOff();
adsr_.keyOff();
}
void Sampler :: noteOff(MY_FLOAT amplitude)
void Sampler :: noteOff(StkFloat amplitude)
{
this->keyOff();
#if defined(_STK_DEBUG_)
cerr << "Sampler: NoteOff amplitude = " << amplitude << endl;
errorString_ << "Sampler::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT Sampler :: tick()
{
lastOutput = attackGain * attacks[whichOne]->tick();
lastOutput += loopGain * loops[whichOne]->tick();
lastOutput = filter->tick(lastOutput);
lastOutput *= adsr->tick();
return lastOutput;
}

View File

@@ -31,170 +31,179 @@
- Vibrato Gain = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Saxofony.h"
#include "SKINI.msg"
Saxofony :: Saxofony(MY_FLOAT lowestFrequency)
Saxofony :: Saxofony(StkFloat lowestFrequency)
{
length = (long) (Stk::sampleRate() / lowestFrequency + 1);
length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
// Initialize blowing position to 0.2 of length / 2.
position = 0.2;
delays[0] = (DelayL *) new DelayL( (1.0-position) * (length >> 1), length );
delays[1] = (DelayL *) new DelayL( position * (length >> 1), length );
position_ = 0.2;
delays_[0].setMaximumDelay( length_ );
delays_[0].setDelay( (1.0-position_) * (length_ >> 1) );
delays_[1].setMaximumDelay( length_ );
delays_[1].setDelay( (1.0-position_) * (length_ >> 1) );
reedTable = new ReedTabl;
reedTable->setOffset((MY_FLOAT) 0.7);
reedTable->setSlope((MY_FLOAT) 0.3);
filter = new OneZero;
envelope = new Envelope;
noise = new Noise;
reedTable_.setOffset( 0.7 );
reedTable_.setSlope( 0.3 );
// Concatenate the STK rawwave path to the rawwave file
vibrato = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
vibrato->setFrequency((MY_FLOAT) 5.735);
vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
vibrato_->setFrequency((StkFloat) 5.735);
outputGain = (MY_FLOAT) 0.3;
noiseGain = (MY_FLOAT) 0.2;
vibratoGain = (MY_FLOAT) 0.1;
outputGain_ = 0.3;
noiseGain_ = 0.2;
vibratoGain_ = 0.1;
}
Saxofony :: ~Saxofony()
{
delete delays[0];
delete delays[1];
delete reedTable;
delete filter;
delete envelope;
delete noise;
delete vibrato;
delete vibrato_;
}
void Saxofony :: clear()
{
delays[0]->clear();
delays[1]->clear();
filter->tick((MY_FLOAT) 0.0);
delays_[0].clear();
delays_[1].clear();
filter_.clear();
}
void Saxofony :: setFrequency(MY_FLOAT frequency)
void Saxofony :: setFrequency(StkFloat frequency)
{
MY_FLOAT freakency = frequency;
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "Saxofony: setFrequency parameter is less than or equal to zero!" << std::endl;
errorString_ << "Saxofony::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
}
MY_FLOAT delay = (Stk::sampleRate() / freakency) - (MY_FLOAT) 3.0;
StkFloat delay = (Stk::sampleRate() / freakency) - (StkFloat) 3.0;
if (delay <= 0.0) delay = 0.3;
else if (delay > length) delay = length;
else if (delay > length_) delay = length_;
delays[0]->setDelay((1.0-position) * delay);
delays[1]->setDelay(position * delay);
delays_[0].setDelay( (1.0-position_) * delay );
delays_[1].setDelay( position_ * delay );
}
void Saxofony :: setBlowPosition(MY_FLOAT aPosition)
void Saxofony :: setBlowPosition(StkFloat position)
{
if (position == aPosition) return;
if ( position_ == position ) return;
if (aPosition < 0.0) position = 0.0;
else if (aPosition > 1.0) position = 1.0;
else position = aPosition;
if ( position < 0.0 ) position_ = 0.0;
else if ( position > 1.0 ) position_ = 1.0;
else position_ = position;
MY_FLOAT total_delay = delays[0]->getDelay();
total_delay += delays[1]->getDelay();
StkFloat totalDelay = delays_[0].getDelay();
totalDelay += delays_[1].getDelay();
delays[0]->setDelay((1.0-position) * total_delay);
delays[1]->setDelay(position * total_delay);
delays_[0].setDelay( (1.0-position_) * totalDelay );
delays_[1].setDelay( position_ * totalDelay );
}
void Saxofony :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate)
void Saxofony :: startBlowing(StkFloat amplitude, StkFloat rate)
{
envelope->setRate(rate);
envelope->setTarget(amplitude);
envelope_.setRate( rate );
envelope_.setTarget( amplitude );
}
void Saxofony :: stopBlowing(MY_FLOAT rate)
void Saxofony :: stopBlowing(StkFloat rate)
{
envelope->setRate(rate);
envelope->setTarget((MY_FLOAT) 0.0);
envelope_.setRate( rate );
envelope_.setTarget( 0.0 );
}
void Saxofony :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Saxofony :: noteOn(StkFloat frequency, StkFloat amplitude)
{
setFrequency(frequency);
startBlowing((MY_FLOAT) 0.55 + (amplitude * 0.30), amplitude * 0.005);
outputGain = amplitude + 0.001;
this->setFrequency( frequency );
this->startBlowing( 0.55 + (amplitude * 0.30), amplitude * 0.005 );
outputGain_ = amplitude + 0.001;
#if defined(_STK_DEBUG_)
std::cerr << "Saxofony: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Saxofony::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Saxofony :: noteOff(MY_FLOAT amplitude)
void Saxofony :: noteOff(StkFloat amplitude)
{
this->stopBlowing(amplitude * 0.01);
this->stopBlowing( amplitude * 0.01 );
#if defined(_STK_DEBUG_)
std::cerr << "Saxofony: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Saxofony::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT Saxofony :: tick()
StkFloat Saxofony :: tick()
{
MY_FLOAT pressureDiff;
MY_FLOAT breathPressure;
MY_FLOAT temp;
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();
breathPressure = envelope_.tick();
breathPressure += breathPressure * noiseGain_ * noise_.tick();
breathPressure += breathPressure * vibratoGain_ * vibrato_->tick();
temp = -0.95 * filter->tick( delays[0]->lastOut() );
lastOutput = temp - delays[1]->lastOut();
pressureDiff = breathPressure - lastOutput;
delays[1]->tick(temp);
delays[0]->tick(breathPressure - (pressureDiff * reedTable->tick(pressureDiff)) - temp);
temp = -0.95 * filter_.tick( delays_[0].lastOut() );
lastOutput_ = temp - delays_[1].lastOut();
pressureDiff = breathPressure - lastOutput_;
delays_[1].tick( temp );
delays_[0].tick( breathPressure - (pressureDiff * reedTable_.tick(pressureDiff)) - temp );
lastOutput *= outputGain;
return lastOutput;
lastOutput_ *= outputGain_;
return lastOutput_;
}
void Saxofony :: controlChange(int number, MY_FLOAT value)
StkFloat *Saxofony :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Saxofony :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void Saxofony :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "Saxofony: Control value less than zero!" << std::endl;
errorString_ << "Saxofony::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "Saxofony: Control value greater than 128.0!" << std::endl;
errorString_ << "Saxofony::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_ReedStiffness_) // 2
reedTable->setSlope( 0.1 + (0.4 * norm) );
reedTable_.setSlope( 0.1 + (0.4 * norm) );
else if (number == __SK_NoiseLevel_) // 4
noiseGain = ( norm * 0.4 );
noiseGain_ = ( norm * 0.4 );
else if (number == 29) // 29
vibrato->setFrequency( norm * 12.0 );
vibrato_->setFrequency( norm * 12.0 );
else if (number == __SK_ModWheel_) // 1
vibratoGain = ( norm * 0.5 );
vibratoGain_ = ( norm * 0.5 );
else if (number == __SK_AfterTouch_Cont_) // 128
envelope->setValue( norm );
envelope_.setValue( norm );
else if (number == 11) // 11
this->setBlowPosition( norm );
else if (number == 26) // reed table offset
reedTable->setOffset(0.4 + ( norm * 0.6));
else
std::cerr << "Saxofony: Undefined Control Number (" << number << ")!!" << std::endl;
reedTable_.setOffset(0.4 + ( norm * 0.6));
else {
errorString_ << "Saxofony::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "Saxofony: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "Saxofony::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@
- Envelope Rate = 11
- Gain = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -22,101 +22,110 @@
Simple :: Simple()
{
adsr = new ADSR;
baseFrequency = (MY_FLOAT) 440.0;
// Concatenate the STK rawwave path to the rawwave file
loop = new WaveLoop( (Stk::rawwavePath() + "impuls10.raw").c_str(), TRUE );
loop_ = new WaveLoop( (Stk::rawwavePath() + "impuls10.raw").c_str(), true );
filter = new OnePole(0.5);
noise = new Noise;
biquad = new BiQuad();
setFrequency(baseFrequency);
loopGain = 0.5;
filter_.setPole( 0.5 );
baseFrequency_ = 440.0;
setFrequency( baseFrequency_ );
loopGain_ = 0.5;
}
Simple :: ~Simple()
{
delete adsr;
delete loop;
delete filter;
delete biquad;
delete loop_;
}
void Simple :: keyOn()
{
adsr->keyOn();
adsr_.keyOn();
}
void Simple :: keyOff()
{
adsr->keyOff();
adsr_.keyOff();
}
void Simple :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Simple :: noteOn(StkFloat frequency, StkFloat amplitude)
{
keyOn();
setFrequency(frequency);
filter->setGain(amplitude);
this->keyOn();
this->setFrequency( frequency );
filter_.setGain( amplitude );
#if defined(_STK_DEBUG_)
std::cerr << "Simple: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Simple::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Simple :: noteOff(MY_FLOAT amplitude)
void Simple :: noteOff(StkFloat amplitude)
{
keyOff();
this->keyOff();
#if defined(_STK_DEBUG_)
std::cerr << "Simple: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Simple::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Simple :: setFrequency(MY_FLOAT frequency)
void Simple :: setFrequency(StkFloat frequency)
{
biquad->setResonance( frequency, 0.98, true );
loop->setFrequency(frequency);
biquad_.setResonance( frequency, 0.98, true );
loop_->setFrequency( frequency );
}
MY_FLOAT Simple :: tick()
StkFloat Simple :: tick()
{
lastOutput = loopGain * loop->tick();
biquad->tick( noise->tick() );
lastOutput += (1.0 - loopGain) * biquad->lastOut();
lastOutput = filter->tick( lastOutput );
lastOutput *= adsr->tick();
return lastOutput;
lastOutput_ = loopGain_ * loop_->tick();
biquad_.tick( noise_.tick() );
lastOutput_ += (1.0 - loopGain_) * biquad_.lastOut();
lastOutput_ = filter_.tick( lastOutput_ );
lastOutput_ *= adsr_.tick();
return lastOutput_;
}
void Simple :: controlChange(int number, MY_FLOAT value)
StkFloat *Simple :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Simple :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void Simple :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "Clarinet: Control value less than zero!" << std::endl;
errorString_ << "Simple::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "Clarinet: Control value greater than 128.0!" << std::endl;
errorString_ << "Simple::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_Breath_) // 2
filter->setPole( 0.99 * (1.0 - (norm * 2.0)) );
filter_.setPole( 0.99 * (1.0 - (norm * 2.0)) );
else if (number == __SK_NoiseLevel_) // 4
loopGain = norm;
loopGain_ = norm;
else if (number == __SK_ModFrequency_) { // 11
norm /= 0.2 * Stk::sampleRate();
adsr->setAttackRate( norm );
adsr->setDecayRate( norm );
adsr->setReleaseRate( norm );
adsr_.setAttackRate( norm );
adsr_.setDecayRate( norm );
adsr_.setReleaseRate( norm );
}
else if (number == __SK_AfterTouch_Cont_) // 128
adsr->setTarget( norm );
else
std::cerr << "Simple: Undefined Control Number (" << number << ")!!" << std::endl;
adsr_.setTarget( norm );
else {
errorString_ << "Simple::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "Simple: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "Simple::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -9,120 +9,121 @@
from pitch shifting. It will be used as an
excitation source for other instruments.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "SingWave.h"
SingWave :: SingWave(const char *fileName, bool raw)
SingWave :: SingWave( std::string fileName, bool raw)
{
// An exception could be thrown here.
wave = new WaveLoop( fileName, raw );
wave_ = new WaveLoop( fileName, raw );
rate = 1.0;
sweepRate = 0.001;
modulator = new Modulate();
modulator->setVibratoRate( 6.0 );
modulator->setVibratoGain( 0.04 );
modulator->setRandomGain( 0.005 );
envelope = new Envelope;
pitchEnvelope = new Envelope;
setFrequency( 75.0 );
pitchEnvelope->setRate( 1.0 );
rate_ = 1.0;
sweepRate_ = 0.001;
modulator_ = new Modulate();
modulator_->setVibratoRate( 6.0 );
modulator_->setVibratoGain( 0.04 );
modulator_->setRandomGain( 0.005 );
this->setFrequency( 75.0 );
pitchEnvelope_.setRate( 1.0 );
this->tick();
this->tick();
pitchEnvelope->setRate( sweepRate * rate );
pitchEnvelope_.setRate( sweepRate_ * rate_ );
}
SingWave :: ~SingWave()
{
delete wave;
delete modulator;
delete envelope;
delete pitchEnvelope;
delete wave_;
delete modulator_;
}
void SingWave :: reset()
{
wave->reset();
lastOutput = 0.0;
wave_->reset();
lastOutput_ = 0.0;
}
void SingWave :: normalize()
{
wave->normalize();
wave_->normalize();
}
void SingWave :: normalize(MY_FLOAT newPeak)
void SingWave :: normalize(StkFloat peak)
{
wave->normalize( newPeak );
wave_->normalize( peak );
}
void SingWave :: setFrequency(MY_FLOAT frequency)
void SingWave :: setFrequency(StkFloat frequency)
{
MY_FLOAT temp = rate;
rate = wave->getSize() * frequency / Stk::sampleRate();
temp -= rate;
StkFloat temp = rate_;
rate_ = wave_->getSize() * frequency / Stk::sampleRate();
temp -= rate_;
if ( temp < 0) temp = -temp;
pitchEnvelope->setTarget( rate );
pitchEnvelope->setRate( sweepRate * temp );
pitchEnvelope_.setTarget( rate_ );
pitchEnvelope_.setRate( sweepRate_ * temp );
}
void SingWave :: setVibratoRate(MY_FLOAT aRate)
void SingWave :: setVibratoRate(StkFloat rate)
{
modulator->setVibratoRate( aRate );
modulator_->setVibratoRate( rate );
}
void SingWave :: setVibratoGain(MY_FLOAT gain)
void SingWave :: setVibratoGain(StkFloat gain)
{
modulator->setVibratoGain(gain);
modulator_->setVibratoGain(gain);
}
void SingWave :: setRandomGain(MY_FLOAT gain)
void SingWave :: setRandomGain(StkFloat gain)
{
modulator->setRandomGain(gain);
modulator_->setRandomGain(gain);
}
void SingWave :: setSweepRate(MY_FLOAT aRate)
void SingWave :: setSweepRate(StkFloat rate)
{
sweepRate = aRate;
sweepRate_ = rate;
}
void SingWave :: setGainRate(MY_FLOAT aRate)
void SingWave :: setGainRate(StkFloat rate)
{
envelope->setRate(aRate);
envelope_.setRate(rate);
}
void SingWave :: setGainTarget(MY_FLOAT target)
void SingWave :: setGainTarget(StkFloat target)
{
envelope->setTarget(target);
envelope_.setTarget(target);
}
void SingWave :: noteOn()
{
envelope->keyOn();
envelope_.keyOn();
}
void SingWave :: noteOff()
{
envelope->keyOff();
envelope_.keyOff();
}
MY_FLOAT SingWave :: tick()
StkFloat SingWave :: tick()
{
// Set the wave rate.
MY_FLOAT newRate = pitchEnvelope->tick();
newRate += newRate * modulator->tick();
wave->setRate( newRate );
StkFloat newRate = pitchEnvelope_.tick();
newRate += newRate * modulator_->tick();
wave_->setRate( newRate );
lastOutput = wave->tick();
lastOutput *= envelope->tick();
lastOutput_ = wave_->tick();
lastOutput_ *= envelope_.tick();
return lastOutput;
return lastOutput_;
}
MY_FLOAT SingWave :: lastOut()
StkFloat *SingWave :: tick(StkFloat *vector, unsigned int vectorSize)
{
return lastOutput;
return Generator::tick( vector, vectorSize );
}
StkFrames& SingWave :: tick( StkFrames& frames, unsigned int channel )
{
return Generator::tick( frames, channel );
}

View File

@@ -13,105 +13,113 @@
Stanford, bearing the names of Karplus and/or
Strong.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Sitar.h"
#include <math.h>
Sitar :: Sitar(MY_FLOAT lowestFrequency)
Sitar :: Sitar(StkFloat lowestFrequency)
{
length = (long) (Stk::sampleRate() / lowestFrequency + 1);
loopGain = (MY_FLOAT) 0.999;
delayLine = new DelayA( (MY_FLOAT)(length / 2.0), length );
delay = length / 2.0;
targetDelay = delay;
unsigned long length = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
delayLine_.setMaximumDelay( length );
delay_ = 0.5 * length;
delayLine_.setDelay( delay_ );
targetDelay_ = delay_;
loopFilter = new OneZero;
loopFilter->setZero(0.01);
loopFilter_.setZero(0.01);
loopGain_ = 0.999;
envelope = new ADSR();
envelope->setAllTimes(0.001, 0.04, 0.0, 0.5);
noise = new Noise;
envelope_.setAllTimes(0.001, 0.04, 0.0, 0.5);
this->clear();
}
Sitar :: ~Sitar()
{
delete delayLine;
delete loopFilter;
delete noise;
delete envelope;
}
void Sitar :: clear()
{
delayLine->clear();
loopFilter->clear();
delayLine_.clear();
loopFilter_.clear();
}
void Sitar :: setFrequency(MY_FLOAT frequency)
void Sitar :: setFrequency(StkFloat frequency)
{
MY_FLOAT freakency = frequency;
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "Sitar: setFrequency parameter is less than or equal to zero!" << std::endl;
errorString_ << "Sitar::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
}
targetDelay = (Stk::sampleRate() / freakency);
delay = targetDelay * (1.0 + (0.05 * noise->tick()));
delayLine->setDelay(delay);
loopGain = 0.995 + (freakency * 0.0000005);
if (loopGain > 0.9995) loopGain = 0.9995;
targetDelay_ = (Stk::sampleRate() / freakency);
delay_ = targetDelay_ * (1.0 + (0.05 * noise_.tick()));
delayLine_.setDelay( delay_ );
loopGain_ = 0.995 + (freakency * 0.0000005);
if ( loopGain_ > 0.9995 ) loopGain_ = 0.9995;
}
void Sitar :: pluck(MY_FLOAT amplitude)
void Sitar :: pluck(StkFloat amplitude)
{
envelope->keyOn();
envelope_.keyOn();
}
void Sitar :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Sitar :: noteOn(StkFloat frequency, StkFloat amplitude)
{
setFrequency(frequency);
pluck(amplitude);
amGain = 0.1 * amplitude;
this->setFrequency( frequency );
this->pluck( amplitude );
amGain_ = 0.1 * amplitude;
#if defined(_STK_DEBUG_)
std::cerr << "Sitar: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Sitar::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Sitar :: noteOff(MY_FLOAT amplitude)
void Sitar :: noteOff(StkFloat amplitude)
{
loopGain = (MY_FLOAT) 1.0 - amplitude;
if ( loopGain < 0.0 ) {
std::cerr << "Plucked: noteOff amplitude greater than 1.0!" << std::endl;
loopGain = 0.0;
loopGain_ = (StkFloat) 1.0 - amplitude;
if ( loopGain_ < 0.0 ) {
errorString_ << "Sitar::noteOff: amplitude is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
loopGain_ = 0.0;
}
else if ( loopGain > 1.0 ) {
std::cerr << "Plucked: noteOff amplitude less than or zero!" << std::endl;
loopGain = (MY_FLOAT) 0.99999;
else if ( loopGain_ > 1.0 ) {
errorString_ << "Sitar::noteOff: amplitude is < 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
loopGain_ = 0.99999;
}
#if defined(_STK_DEBUG_)
std::cerr << "Plucked: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Sitar::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT Sitar :: tick()
StkFloat Sitar :: tick()
{
if ( fabs(targetDelay - delay) > 0.001 ) {
if (targetDelay < delay)
delay *= 0.99999;
if ( fabs(targetDelay_ - delay_) > 0.001 ) {
if ( targetDelay_ < delay_ )
delay_ *= 0.99999;
else
delay *= 1.00001;
delayLine->setDelay(delay);
delay_ *= 1.00001;
delayLine_.setDelay( delay_ );
}
lastOutput = delayLine->tick( loopFilter->tick( delayLine->lastOut() * loopGain ) +
(amGain * envelope->tick() * noise->tick()));
lastOutput_ = delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ ) +
(amGain_ * envelope_.tick() * noise_.tick()));
return lastOutput;
return lastOutput_;
}
StkFloat *Sitar :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Sitar :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

212
src/Skini.cpp Normal file
View File

@@ -0,0 +1,212 @@
/***************************************************/
/*! \class Skini
\brief STK SKINI parsing class
This class parses SKINI formatted text
messages. It can be used to parse individual
messages or it can be passed an entire file.
The SKINI specification is Perry's and his
alone, but it's all text so it shouldn't be too
hard to figure out.
SKINI (Synthesis toolKit Instrument Network
Interface) is like MIDI, but allows for
floating-point control changes, note numbers,
etc. The following example causes a sharp
middle C to be played with a velocity of 111.132:
noteOn 60.01 111.132
See also SKINI.txt.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Skini.h"
#include "SKINI.tbl"
Skini :: Skini()
{
}
Skini :: ~Skini()
{
}
bool Skini :: setFile( std::string fileName )
{
if ( file_.is_open() ) {
errorString_ << "Skini::setFile: already reaading a file!";
handleError( StkError::WARNING );
return false;
}
file_.open( fileName.c_str() );
if ( !file_ ) {
errorString_ << "Skini::setFile: unable to open file (" << fileName << ")";
handleError( StkError::WARNING );
return false;
}
return true;
}
long Skini :: nextMessage( Message& message )
{
if ( !file_.is_open() ) return 0;
std::string line;
bool done = false;
while ( !done ) {
// Read a line from the file and skip over invalid messages.
if ( std::getline( file_, line ).eof() ) {
errorString_ << "// End of Score. Thanks for using SKINI!!";
handleError( StkError::STATUS );
file_.close();
message.type = 0;
done = true;
}
else if ( parseString( line, message ) > 0 ) done = true;
}
return message.type;
}
void Skini :: tokenize( const std::string& str,
std::vector<std::string>& tokens,
const std::string& delimiters )
{
// Skip delimiters at beginning.
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
// Find first "non-delimiter".
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
while (std::string::npos != pos || std::string::npos != lastPos) {
// Found a token, add it to the vector.
tokens.push_back(str.substr(lastPos, pos - lastPos));
// Skip delimiters. Note the "not_of"
lastPos = str.find_first_not_of(delimiters, pos);
// Find next "non-delimiter"
pos = str.find_first_of(delimiters, lastPos);
}
}
long Skini :: parseString( std::string& line, Message& message )
{
message.type = 0;
if ( line.empty() ) return message.type;
// Check for comment lines.
std::string::size_type lastPos = line.find_first_not_of(" ,\t", 0);
std::string::size_type pos = line.find_first_of("/", lastPos);
if ( std::string::npos != pos ) {
errorString_ << "// Comment Line: " << line;
handleError( StkError::STATUS );
return message.type;
}
// Tokenize the string.
std::vector<std::string> tokens;
this->tokenize( line, tokens, " ,\t");
// Valid SKINI messages must have at least three fields (type, time,
// and channel).
if ( tokens.size() < 3 ) return message.type;
// Determine message type.
int iSkini = 0;
while ( iSkini < __SK_MaxMsgTypes_ ) {
if ( tokens[0] == skini_msgs[iSkini].messageString ) break;
iSkini++;
}
if ( iSkini >= __SK_MaxMsgTypes_ ) {
errorString_ << "Skini::parseString: couldn't parse this line:\n " << line;
handleError( StkError::WARNING );
return message.type;
}
// Found the type.
message.type = skini_msgs[iSkini].type;
// Parse time field.
if ( tokens[1][0] == '=' ) {
tokens[1].erase( tokens[1].begin() );
if ( tokens[1].empty() ) {
errorString_ << "Skini::parseString: couldn't parse time field in line:\n " << line;
handleError( StkError::WARNING );
return message.type = 0;
}
message.time = (StkFloat) -atof( tokens[1].c_str() );
}
else
message.time = (StkFloat) atof( tokens[1].c_str() );
// Parse the channel field.
message.channel = atoi( tokens[2].c_str() );
// Parse the remaining fields (maximum of 2 more).
int iValue = 0;
long dataType = skini_msgs[iSkini].data2;
while ( dataType != NOPE ) {
if ( tokens.size() <= (unsigned int) (iValue+3) ) {
errorString_ << "Skini::parseString: inconsistency between type table and parsed line:\n " << line;
handleError( StkError::WARNING );
return message.type = 0;
}
switch ( dataType ) {
case SK_INT:
message.intValues[iValue] = atoi( tokens[iValue+3].c_str() );
message.floatValues[iValue] = (StkFloat) message.intValues[iValue];
break;
case SK_DBL:
message.floatValues[iValue] = atof( tokens[iValue+3].c_str() );
message.intValues[iValue] = (long) message.floatValues[iValue];
break;
case SK_STR: // Must be the last field.
message.remainder = tokens[iValue+3];
return message.type;
}
if ( ++iValue == 1 )
dataType = skini_msgs[iSkini].data3;
else
dataType = NOPE;
}
return message.type;
}
std::string Skini :: whatsThisType(long type)
{
std::string typeString;
for ( int i=0; i<__SK_MaxMsgTypes_; i++ ) {
if ( type == skini_msgs[i].type ) {
typeString = skini_msgs[i].messageString;
break;
}
}
return typeString;
}
std::string Skini :: whatsThisController( long number )
{
std::string controller;
for ( int i=0; i<__SK_MaxMsgTypes_; i++) {
if ( skini_msgs[i].type == __SK_ControlChange_ &&
number == skini_msgs[i].data2) {
controller = skini_msgs[i].messageString;
break;
}
}
return controller;
}

View File

@@ -14,7 +14,7 @@
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 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -31,6 +31,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#elif defined(__OS_WINDOWS__)
@@ -40,9 +41,9 @@
Socket :: Socket( int port )
{
soket = -1;
server = true;
poort = port;
soket_ = -1;
server_ = true;
port_ = port;
// Create a socket server.
#if defined(__OS_WINDOWS__) // windoze-only stuff
@@ -51,16 +52,23 @@ Socket :: Socket( int port )
WSAStartup(wVersionRequested, &wsaData);
if (wsaData.wVersion != wVersionRequested) {
sprintf( msg, "Socket: Incompatible Windows socket library version!" );
handleError( msg, StkError::PROCESS_SOCKET );
errorString_ << "Socket: Incompatible Windows socket library version!";
handleError( StkError::PROCESS_SOCKET );
}
#endif
// Create the server-side socket
soket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (soket < 0) {
sprintf(msg, "Socket: Couldn't create socket server!");
handleError( msg, StkError::PROCESS_SOCKET );
soket_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (soket_ < 0) {
errorString_ << "Socket: Couldn't create socket server!";
handleError( StkError::PROCESS_SOCKET );
}
int flag = 1;
int result = setsockopt( soket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int) );
if (result < 0) {
errorString_ << "Socket: Error setting socket options!";
handleError( StkError::PROCESS_SOCKET );
}
struct sockaddr_in mysocket;
@@ -69,23 +77,23 @@ Socket :: Socket( int port )
mysocket.sin_port=htons( port );
// Bind socket to the appropriate port and interface (INADDR_ANY)
if (bind(soket, (struct sockaddr *)&mysocket, sizeof(mysocket)) < 0) {
sprintf(msg, "Socket: Couldn't bind socket!");
handleError( msg, StkError::PROCESS_SOCKET );
if ( bind(soket_, (struct sockaddr *)&mysocket, sizeof(mysocket)) < 0 ) {
errorString_ << "Socket: Couldn't bind socket!";
handleError( StkError::PROCESS_SOCKET );
}
// Listen for incoming connection(s)
if ( listen(soket, 1) < 0 ) {
sprintf(msg, "Socket: Couldn't start server listening!");
handleError( msg, StkError::PROCESS_SOCKET );
if ( listen(soket_, 1) < 0 ) {
errorString_ << "Socket: Couldn't start server listening!";
handleError( StkError::PROCESS_SOCKET );
}
}
Socket :: Socket(int port, const char *hostname )
{
soket = -1;
server = false;
poort = port;
soket_ = -1;
server_ = false;
port_ = port;
#if defined(__OS_WINDOWS__) // windoze-only stuff
WSADATA wsaData;
@@ -93,8 +101,8 @@ Socket :: Socket(int port, const char *hostname )
WSAStartup(wVersionRequested, &wsaData);
if (wsaData.wVersion != wVersionRequested) {
sprintf( msg, "Socket: Incompatible Windows socket library version!" );
handleError( msg, StkError::PROCESS_SOCKET );
errorString_ << "Socket: Incompatible Windows socket library version!";
handleError( StkError::PROCESS_SOCKET );
}
#endif
@@ -106,11 +114,11 @@ Socket :: ~Socket()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
::close( soket );
::close( soket_ );
#elif defined(__OS_WINDOWS__)
::closesocket( soket );
::closesocket( soket_ );
WSACleanup();
#endif
@@ -119,22 +127,29 @@ Socket :: ~Socket()
int Socket :: connect( int port, const char *hostname )
{
// This method is for client connections only!
if ( server == true ) return -1;
if ( server_ == true ) return -1;
// Close an existing connection if it exists.
if ( isValid( soket ) ) this->close();
if ( isValid( soket_ ) ) this->close();
// Create the client-side socket
soket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (soket < 0) {
sprintf(msg, "Socket: Couldn't create socket client!");
handleError( msg, StkError::PROCESS_SOCKET );
soket_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (soket_ < 0) {
errorString_ << "Socket: Couldn't create socket client!";
handleError( StkError::PROCESS_SOCKET );
}
int flag = 1;
int result = setsockopt( soket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int) );
if (result < 0) {
errorString_ << "Socket: Error setting socket options!";
handleError( StkError::PROCESS_SOCKET );
}
struct hostent *hostp;
if ( (hostp = gethostbyname(hostname)) == 0 ) {
sprintf(msg, "Socket: unknown host (%s)!", hostname);
handleError( msg, StkError::PROCESS_SOCKET_IPADDR );
errorString_ << "Socket: unknown host (" << hostname << ")!";
handleError( StkError::PROCESS_SOCKET_IPADDR );
}
// Fill in the address structure
@@ -144,29 +159,29 @@ int Socket :: connect( int port, const char *hostname )
server_address.sin_port = htons(port);
// Connect to the server
if ( ::connect(soket, (struct sockaddr *)&server_address,
if ( ::connect(soket_, (struct sockaddr *)&server_address,
sizeof(server_address) ) < 0) {
sprintf(msg, "Socket: Couldn't connect to socket server!");
handleError( msg, StkError::PROCESS_SOCKET );
errorString_ << "Socket: Couldn't connect to socket server!";
handleError( StkError::PROCESS_SOCKET );
}
return soket;
return soket_;
}
int Socket :: socket( void ) const
int Socket :: id( void ) const
{
return soket;
return soket_;
}
int Socket :: port( void ) const
{
return poort;
return port_;
}
int Socket :: accept( void )
{
if ( server )
return ::accept( soket, NULL, NULL );
if ( server_ )
return ::accept( soket_, NULL, NULL );
else
return -1;
}
@@ -196,9 +211,9 @@ void Socket :: setBlocking( int socket, bool enable )
void Socket :: close( void )
{
if ( !isValid( soket ) ) return;
this->close( soket );
soket = -1;
if ( !isValid( soket_ ) ) return;
this->close( soket_ );
soket_ = -1;
}
void Socket :: close( int socket )
@@ -218,8 +233,8 @@ void Socket :: close( int socket )
int Socket :: writeBuffer(const void *buffer, long bufferSize, int flags )
{
if ( !isValid( soket ) ) return -1;
return send( soket, (const char *)buffer, bufferSize, flags );
if ( !isValid( soket_ ) ) return -1;
return send( soket_, (const char *)buffer, bufferSize, flags );
}
int Socket :: writeBuffer(int socket, const void *buffer, long bufferSize, int flags )
@@ -230,8 +245,8 @@ int Socket :: writeBuffer(int socket, const void *buffer, long bufferSize, int f
int Socket :: readBuffer(void *buffer, long bufferSize, int flags )
{
if ( !isValid( soket ) ) return -1;
return recv( soket, (char *)buffer, bufferSize, flags );
if ( !isValid( soket_ ) ) return -1;
return recv( soket_, (char *)buffer, bufferSize, flags );
}
int Socket :: readBuffer(int socket, void *buffer, long bufferSize, int flags )

View File

@@ -5,100 +5,95 @@
This class implements a spherical ball with
radius, mass, position, and velocity parameters.
by Perry R. Cook, 1995 - 2002.
by Perry R. Cook, 1995 - 2004.
*/
/***************************************************/
#include "Sphere.h"
#include <stdio.h>
#include <math.h>
Sphere::Sphere(double initRadius)
Sphere::Sphere(StkFloat radius)
{
myRadius = initRadius;
myMass = 1.0;
myPosition = new Vector3D(0, 0, 0);
myVelocity = new Vector3D(0, 0, 0);
radius_ = radius;
mass_ = 1.0;
};
Sphere::~Sphere()
{
delete myPosition;
delete myVelocity;
}
void Sphere::setPosition(double anX, double aY, double aZ)
void Sphere::setPosition(StkFloat x, StkFloat y, StkFloat z)
{
myPosition->setXYZ(anX, aY, aZ);
position_.setXYZ(x, y, z);
};
void Sphere::setVelocity(double anX, double aY, double aZ)
void Sphere::setVelocity(StkFloat x, StkFloat y, StkFloat z)
{
myVelocity->setXYZ(anX, aY, aZ);
velocity_.setXYZ(x, y, z);
};
void Sphere::setRadius(double aRadius)
void Sphere::setRadius(StkFloat radius)
{
myRadius = aRadius;
radius_ = radius;
};
void Sphere::setMass(double aMass)
void Sphere::setMass(StkFloat mass)
{
myMass = aMass;
mass_ = mass;
};
Vector3D* Sphere::getPosition()
{
return myPosition;
return &position_;
};
Vector3D* Sphere::getRelativePosition(Vector3D* aPosition)
Vector3D* Sphere::getRelativePosition(Vector3D* position)
{
workingVector.setXYZ(aPosition->getX() - myPosition->getX(),
aPosition->getY() - myPosition->getY(),
aPosition->getZ() - myPosition->getZ());
return &workingVector;
workingVector_.setXYZ(position->getX() - position_.getX(),
position->getY() - position_.getY(),
position->getZ() - position_.getZ());
return &workingVector_;
};
double Sphere::getVelocity(Vector3D* aVelocity)
StkFloat Sphere::getVelocity(Vector3D* velocity)
{
aVelocity->setXYZ(myVelocity->getX(), myVelocity->getY(), myVelocity->getZ());
return myVelocity->getLength();
velocity->setXYZ( velocity_.getX(), velocity_.getY(), velocity_.getZ() );
return velocity_.getLength();
};
double Sphere::isInside(Vector3D *aPosition)
StkFloat Sphere::isInside(Vector3D *position)
{
// Return directed distance from aPosition to spherical boundary ( <
// 0 if inside).
double distance;
StkFloat distance;
Vector3D *tempVector;
tempVector = this->getRelativePosition(aPosition);
tempVector = this->getRelativePosition( position );
distance = tempVector->getLength();
return distance - myRadius;
return distance - radius_;
};
double Sphere::getRadius()
StkFloat Sphere::getRadius()
{
return myRadius;
return radius_;
};
double Sphere::getMass()
StkFloat Sphere::getMass()
{
return myMass;
return mass_;
};
void Sphere::addVelocity(double anX, double aY, double aZ)
void Sphere::addVelocity(StkFloat x, StkFloat y, StkFloat z)
{
myVelocity->setX(myVelocity->getX() + anX);
myVelocity->setY(myVelocity->getY() + aY);
myVelocity->setZ(myVelocity->getZ() + aZ);
velocity_.setX(velocity_.getX() + x);
velocity_.setY(velocity_.getY() + y);
velocity_.setZ(velocity_.getZ() + z);
}
void Sphere::tick(double timeIncrement)
void Sphere::tick(StkFloat timeIncrement)
{
myPosition->setX(myPosition->getX() + (timeIncrement * myVelocity->getX()));
myPosition->setY(myPosition->getY() + (timeIncrement * myVelocity->getY()));
myPosition->setZ(myPosition->getZ() + (timeIncrement * myVelocity->getZ()));
position_.setX(position_.getX() + (timeIncrement * velocity_.getX()));
position_.setY(position_.getY() + (timeIncrement * velocity_.getY()));
position_.setZ(position_.getZ() + (timeIncrement * velocity_.getZ()));
};

View File

@@ -17,211 +17,223 @@
- String Sustain = 11
- String Stretch = 1
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "StifKarp.h"
#include "SKINI.msg"
#include <string.h>
#include <math.h>
StifKarp :: StifKarp(MY_FLOAT lowestFrequency)
StifKarp :: StifKarp(StkFloat lowestFrequency)
{
length = (long) (Stk::sampleRate() / lowestFrequency + 1);
delayLine = new DelayA(0.5 * length, length);
combDelay = new DelayL( 0.2 * length, length);
length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( 0.5 * length_ );
combDelay_.setMaximumDelay( length_ );
combDelay_.setDelay( 0.2 * length_ );
filter = new OneZero();
noise = new Noise();
biQuad[0] = new BiQuad();
biQuad[1] = new BiQuad();
biQuad[2] = new BiQuad();
biQuad[3] = new BiQuad();
pluckAmplitude_ = 0.3;
pickupPosition_ = 0.4;
lastFrequency_ = lowestFrequency * 2.0;
lastLength_ = length_ * 0.5;
stretching_ = 0.9999;
baseLoopGain_ = 0.995;
loopGain_ = 0.999;
pluckAmplitude = 0.3;
pickupPosition = (MY_FLOAT) 0.4;
lastFrequency = lowestFrequency * 2.0;
lastLength = length * 0.5;
stretching = 0.9999;
baseLoopGain = 0.995;
loopGain = 0.999;
clear();
this->clear();
}
StifKarp :: ~StifKarp()
{
delete delayLine;
delete combDelay;
delete filter;
delete noise;
delete biQuad[0];
delete biQuad[1];
delete biQuad[2];
delete biQuad[3];
}
void StifKarp :: clear()
{
delayLine->clear();
combDelay->clear();
filter->clear();
delayLine_.clear();
combDelay_.clear();
filter_.clear();
}
void StifKarp :: setFrequency(MY_FLOAT frequency)
void StifKarp :: setFrequency(StkFloat frequency)
{
lastFrequency = frequency;
lastFrequency_ = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "StifKarp: setFrequency parameter is less than or equal to zero!" << std::endl;
lastFrequency = 220.0;
errorString_ << "StifKarp::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
lastFrequency_ = 220.0;
}
lastLength = Stk::sampleRate() / lastFrequency;
MY_FLOAT delay = lastLength - 0.5;
if (delay <= 0.0) delay = 0.3;
else if (delay > length) delay = length;
delayLine->setDelay( delay );
lastLength_ = Stk::sampleRate() / lastFrequency_;
StkFloat delay = lastLength_ - 0.5;
if (delay <= 0.0)
delay = 0.3;
else if (delay > length_)
delay = length_;
delayLine_.setDelay( delay );
loopGain = baseLoopGain + (frequency * (MY_FLOAT) 0.000005);
if (loopGain >= 1.0) loopGain = (MY_FLOAT) 0.99999;
loopGain_ = baseLoopGain_ + (frequency * 0.000005);
if (loopGain_ >= 1.0) loopGain_ = 0.99999;
setStretch(stretching);
setStretch(stretching_);
combDelay->setDelay((MY_FLOAT) 0.5 * pickupPosition * lastLength);
combDelay_.setDelay( 0.5 * pickupPosition_ * lastLength_ );
}
void StifKarp :: setStretch(MY_FLOAT stretch)
void StifKarp :: setStretch(StkFloat stretch)
{
stretching = stretch;
MY_FLOAT coefficient;
MY_FLOAT freq = lastFrequency * 2.0;
MY_FLOAT dFreq = ( (0.5 * Stk::sampleRate()) - freq ) * 0.25;
MY_FLOAT temp = 0.5 + (stretch * 0.5);
stretching_ = stretch;
StkFloat coefficient;
StkFloat freq = lastFrequency_ * 2.0;
StkFloat dFreq = ( (0.5 * Stk::sampleRate()) - freq ) * 0.25;
StkFloat temp = 0.5 + (stretch * 0.5);
if (temp > 0.9999) temp = 0.9999;
for (int i=0; i<4; i++) {
coefficient = temp * temp;
biQuad[i]->setA2( coefficient );
biQuad[i]->setB0( coefficient );
biQuad[i]->setB2( 1.0 );
biquad_[i].setA2( coefficient );
biquad_[i].setB0( coefficient );
biquad_[i].setB2( 1.0 );
coefficient = -2.0 * temp * cos(TWO_PI * freq / Stk::sampleRate());
biQuad[i]->setA1( coefficient );
biQuad[i]->setB1( coefficient );
biquad_[i].setA1( coefficient );
biquad_[i].setB1( coefficient );
freq += dFreq;
}
}
void StifKarp :: setPickupPosition(MY_FLOAT position) {
pickupPosition = position;
void StifKarp :: setPickupPosition(StkFloat position) {
pickupPosition_ = position;
if ( position < 0.0 ) {
std::cerr << "StifKarp: setPickupPosition parameter is less than zero!" << std::endl;
pickupPosition = 0.0;
errorString_ << "StifKarp::setPickupPosition: parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
pickupPosition_ = 0.0;
}
else if ( position > 1.0 ) {
std::cerr << "StifKarp: setPickupPosition parameter is greater than 1.0!" << std::endl;
pickupPosition = 1.0;
errorString_ << "StifKarp::setPickupPosition: parameter is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
pickupPosition_ = 1.0;
}
// Set the pick position, which puts zeroes at position * length.
combDelay->setDelay(0.5 * pickupPosition * lastLength);
combDelay_.setDelay( 0.5 * pickupPosition_ * lastLength_ );
}
void StifKarp :: setBaseLoopGain(MY_FLOAT aGain)
void StifKarp :: setBaseLoopGain(StkFloat aGain)
{
baseLoopGain = aGain;
loopGain = baseLoopGain + (lastFrequency * 0.000005);
if ( loopGain > 0.99999 ) loopGain = (MY_FLOAT) 0.99999;
baseLoopGain_ = aGain;
loopGain_ = baseLoopGain_ + (lastFrequency_ * 0.000005);
if ( loopGain_ > 0.99999 ) loopGain_ = (StkFloat) 0.99999;
}
void StifKarp :: pluck(MY_FLOAT amplitude)
void StifKarp :: pluck(StkFloat amplitude)
{
MY_FLOAT gain = amplitude;
StkFloat gain = amplitude;
if ( gain > 1.0 ) {
std::cerr << "StifKarp: pluck amplitude greater than 1.0!" << std::endl;
errorString_ << "StifKarp::pluck: amplitude is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
gain = 1.0;
}
else if ( gain < 0.0 ) {
std::cerr << "StifKarp: pluck amplitude less than zero!" << std::endl;
errorString_ << "StifKarp::pluck: amplitude is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
gain = 0.0;
}
pluckAmplitude = amplitude;
for (long i=0; i<length; i++) {
pluckAmplitude_ = amplitude;
for (unsigned long i=0; i<length_; i++) {
// Fill delay with noise additively with current contents.
delayLine->tick((delayLine->lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude);
//delayLine->tick( combDelay->tick((delayLine->lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude));
delayLine_.tick( (delayLine_.lastOut() * 0.6) + 0.4 * noise_.tick() * pluckAmplitude_ );
//delayLine_.tick( combDelay_.tick((delayLine_.lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude_) );
}
}
void StifKarp :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void StifKarp :: noteOn(StkFloat frequency, StkFloat amplitude)
{
this->setFrequency(frequency);
this->pluck(amplitude);
this->setFrequency( frequency );
this->pluck( amplitude );
#if defined(_STK_DEBUG_)
std::cerr << "StifKarp: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "StifKarp::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void StifKarp :: noteOff(MY_FLOAT amplitude)
void StifKarp :: noteOff(StkFloat amplitude)
{
MY_FLOAT gain = amplitude;
StkFloat gain = amplitude;
if ( gain > 1.0 ) {
std::cerr << "StifKarp: noteOff amplitude greater than 1.0!" << std::endl;
errorString_ << "StifKarp::noteOff: amplitude is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
gain = 1.0;
}
else if ( gain < 0.0 ) {
std::cerr << "StifKarp: noteOff amplitude less than zero!" << std::endl;
errorString_ << "StifKarp::noteOff: amplitude is < 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
gain = 0.0;
}
loopGain = (1.0 - gain) * 0.5;
loopGain_ = (1.0 - gain) * 0.5;
#if defined(_STK_DEBUG_)
std::cerr << "StifPluck: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "StifKarp::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT StifKarp :: tick()
StkFloat StifKarp :: tick()
{
MY_FLOAT temp = delayLine->lastOut() * loopGain;
StkFloat temp = delayLine_.lastOut() * loopGain_;
// Calculate allpass stretching.
for (int i=0; i<4; i++)
temp = biQuad[i]->tick(temp);
temp = biquad_[i].tick(temp);
// Moving average filter.
temp = filter->tick(temp);
temp = filter_.tick(temp);
lastOutput = delayLine->tick(temp);
lastOutput = lastOutput - combDelay->tick(lastOutput);
return lastOutput;
lastOutput_ = delayLine_.tick(temp);
lastOutput_ = lastOutput_ - combDelay_.tick( lastOutput_ );
return lastOutput_;
}
void StifKarp :: controlChange(int number, MY_FLOAT value)
StkFloat *StifKarp :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& StifKarp :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void StifKarp :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "StifKarp: Control value less than zero!" << std::endl;
errorString_ << "StifKarp::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "StifKarp: Control value greater than 128.0!" << std::endl;
errorString_ << "StifKarp::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_PickPosition_) // 4
setPickupPosition( norm );
this->setPickupPosition( norm );
else if (number == __SK_StringDamping_) // 11
setBaseLoopGain( 0.97 + (norm * 0.03) );
this->setBaseLoopGain( 0.97 + (norm * 0.03) );
else if (number == __SK_StringDetune_) // 1
setStretch( 0.9 + (0.1 * (1.0 - norm)) );
else
std::cerr << "StifKarp: Undefined Control Number (" << number << ")!!" << std::endl;
this->setStretch( 0.9 + (0.1 * (1.0 - norm)) );
else {
errorString_ << "StifKarp::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "StifKarp: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "StifKarp::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -8,21 +8,19 @@
provides error handling and byte-swapping
functions.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Stk.h"
#include <stdio.h>
#include <string.h>
MY_FLOAT Stk :: srate = (MY_FLOAT) SRATE;
std::string Stk :: rawwavepath = RAWWAVE_PATH;
const Stk::STK_FORMAT Stk :: STK_SINT8 = 1;
const Stk::STK_FORMAT Stk :: STK_SINT16 = 2;
const Stk::STK_FORMAT Stk :: STK_SINT32 = 8;
const Stk::STK_FORMAT Stk :: MY_FLOAT32 = 16;
const Stk::STK_FORMAT Stk :: MY_FLOAT64 = 32;
StkFloat Stk :: srate_ = (StkFloat) SRATE;
std::string Stk :: rawwavepath_ = RAWWAVE_PATH;
const Stk::StkFormat Stk :: STK_SINT8 = 0x1;
const Stk::StkFormat Stk :: STK_SINT16 = 0x2;
const Stk::StkFormat Stk :: STK_SINT32 = 0x8;
const Stk::StkFormat Stk :: STK_FLOAT32 = 0x10;
const Stk::StkFormat Stk :: STK_FLOAT64 = 0x20;
Stk :: Stk(void)
{
@@ -32,30 +30,14 @@ Stk :: ~Stk(void)
{
}
MY_FLOAT Stk :: sampleRate(void)
void Stk :: setRawwavePath( std::string path )
{
return srate;
}
void Stk :: setSampleRate(MY_FLOAT newRate)
{
if (newRate > 0)
srate = newRate;
}
std::string Stk :: rawwavePath(void)
{
return rawwavepath;
}
void Stk :: setRawwavePath(std::string newPath)
{
if ( !newPath.empty() )
rawwavepath = newPath;
if ( !path.empty() )
rawwavepath_ = path;
// Make sure the path includes a "/"
if ( rawwavepath[rawwavepath.length()-1] != '/' )
rawwavepath += "/";
if ( rawwavepath_[rawwavepath_.length()-1] != '/' )
rawwavepath_ += "/";
}
void Stk :: swap16(unsigned char *ptr)
@@ -127,33 +109,74 @@ void Stk :: sleep(unsigned long milliseconds)
#endif
}
void Stk :: handleError( const char *message, StkError::TYPE type )
void Stk :: handleError( StkError::Type type )
{
if (type == StkError::WARNING)
fprintf(stderr, "\n%s\n\n", message);
handleError( errorString_.str(), type );
errorString_.str( std::string() ); // reset the ostringstream buffer
}
void Stk :: handleError( const char *message, StkError::Type type )
{
std::string msg( message );
handleError( msg, type );
}
void Stk :: handleError( std::string message, StkError::Type type )
{
if (type == StkError::WARNING || type == StkError::STATUS )
std::cerr << '\n' << message << '\n' << std::endl;
else if (type == StkError::DEBUG_WARNING) {
#if defined(_STK_DEBUG_)
fprintf(stderr, "\n%s\n\n", message);
std::cerr << '\n' << message << '\n' << std::endl;
#endif
}
else {
// Print error message before throwing.
fprintf(stderr, "\n%s\n\n", message);
std::cerr << '\n' << message << '\n' << std::endl;
throw StkError(message, type);
}
}
StkError :: StkError(const char *p, TYPE tipe)
: type(tipe)
StkFrames :: StkFrames( unsigned int nFrames, unsigned int nChannels, bool interleaved )
: nFrames_( nFrames ), nChannels_( nChannels ), interleaved_( interleaved )
{
strncpy(message, p, 256);
if ( nChannels == 0 ) {
std::string message = "StkFrames::StkFrames: nChannels argument should be 1 or greater (even if nFrames = 0) ... correcting to one channel!";
Stk::handleError( message, StkError::WARNING );
nChannels_ = 1;
}
size_ = nFrames_ * nChannels_;
if ( size_ > 0 ) data_.resize( size_, 0.0 );
}
StkError :: ~StkError(void)
StkFrames :: StkFrames( const StkFloat& value, unsigned int nFrames, unsigned int nChannels, bool interleaved )
: nFrames_( nFrames ), nChannels_( nChannels ), interleaved_( interleaved )
{
if ( nChannels == 0 ) {
std::string message = "StkFrames::StkFrames: nChannels argument should be 1 or greater (even if nFrames = 0) ... correcting to one channel!";
Stk::handleError( message, StkError::WARNING );
nChannels_ = 1;
}
size_ = nFrames_ * nChannels_;
if ( size_ > 0 ) data_.resize( size_, value );
}
void StkError :: printMessage(void)
void StkFrames :: resize( unsigned int nFrames, unsigned int nChannels, StkFloat value )
{
printf("\n%s\n\n", message);
nFrames_ = nFrames;
nChannels_ = nChannels;
if ( nChannels == 0 ) {
std::string message = "StkFrames::resize(): nChannels argument should be 1 or greater (even if nFrames = 0) ... correcting to one channel!";
Stk::handleError( message, StkError::WARNING );
nChannels_ = 1;
}
size_t newSize = nFrames_ * nChannels_;
if ( size_ != newSize ) {
size_ = newSize;
data_.resize( size_, value );
}
}

View File

@@ -6,7 +6,7 @@
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 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -14,8 +14,8 @@
SubNoise :: SubNoise(int subRate) : Noise()
{
rate = subRate;
counter = rate;
rate_ = subRate;
counter_ = rate_;
}
SubNoise :: ~SubNoise()
{
@@ -23,21 +23,31 @@ SubNoise :: ~SubNoise()
int SubNoise :: subRate(void) const
{
return rate;
return rate_;
}
void SubNoise :: setRate(int subRate)
{
if (subRate > 0)
rate = subRate;
rate_ = subRate;
}
MY_FLOAT SubNoise :: tick()
StkFloat SubNoise :: tick()
{
if ( ++counter > rate ) {
if ( ++counter_ > rate_ ) {
Noise::tick();
counter = 1;
counter_ = 1;
}
return lastOutput;
return lastOutput_;
}
StkFloat *SubNoise :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Generator::tick( vector, vectorSize );
}
StkFrames& SubNoise :: tick( StkFrames& frames, unsigned int channel )
{
return Generator::tick( frames, channel );
}

View File

@@ -10,97 +10,91 @@
An StkError will be thrown if the table file
is not found.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "Table.h"
#include <stdio.h>
#include <fstream>
#include <sys/stat.h>
#include <sys/types.h>
#include <iostream>
Table :: Table(char *fileName)
Table :: Table( std::string fileName)
{
char message[256];
// Use the system call "stat" to determine the file length
struct stat filestat;
if ( stat(fileName, &filestat) == -1 ) {
sprintf(message, "Table: Couldn't stat or find file (%s).", fileName);
handleError( message, StkError::FILE_NOT_FOUND );
if ( stat( fileName.c_str(), &filestat ) == -1 ) {
errorString_ << "Table: Couldn't stat or find file (" << fileName << ").";
handleError( StkError::FILE_NOT_FOUND );
}
length = (long) filestat.st_size / 8; // length in 8-byte samples
length_ = (long) filestat.st_size / 8; // length in 8-byte samples
// Open the file and read samples into data[]
FILE *fd;
fd = fopen(fileName,"rb");
fd = fopen(fileName.c_str(),"rb");
if (!fd) {
sprintf(message, "Table: Couldn't open or find file (%s).", fileName);
handleError( message, StkError::FILE_NOT_FOUND );
errorString_ << "Table::Table: unable to open or find file (" << fileName << ")";
handleError( StkError::FILE_NOT_FOUND );
}
data = (MY_FLOAT *) new MY_FLOAT[length];
data_.resize( length_, 0.0 );
// Read samples into data[]
// Read samples into data
long i = 0;
double temp;
while ( fread(&temp, 8, 1, fd) ) {
while ( fread( &temp, 8, 1, fd ) ) {
#ifdef __LITTLE_ENDIAN__
swap64((unsigned char *)&temp);
swap64( (unsigned char *)&temp );
#endif
data[i++] = (MY_FLOAT) temp;
data_[i++] = (StkFloat) temp;
}
fclose(fd);
lastOutput = 0.0;
lastOutput_ = 0.0;
}
Table :: ~Table()
{
delete [ ] data;
}
long Table :: getLength() const
{
return length;
return length_;
}
MY_FLOAT Table :: lastOut() const
StkFloat Table :: tick(StkFloat index)
{
return lastOutput;
}
MY_FLOAT Table :: tick(MY_FLOAT index)
{
MY_FLOAT alpha;
StkFloat alpha;
long temp;
if (index > length-1) {
std::cerr << "Table: Index (" << index << ") exceeds table length ... sticking at end!" << std::endl;
index = length-1;
if ( index > length_-1 ) {
errorString_ << "Table: Index (" << index << ") exceeds table length ... sticking at end!\n";
handleError( StkError::WARNING );
index = length_-1;
}
else if (index < 0.0) {
std::cerr << "Table: Index (" << index << ") is less than zero ... setting to zero!" << std::endl;
errorString_ << "Table: Index (" << index << ") is less than zero ... setting to zero!\n";
handleError( StkError::WARNING );
index = 0.0;
}
// Index in range 0 to length-1
temp = (long) index; // Integer part of index
alpha = index - (MY_FLOAT) temp; // Fractional part of index
temp = (long) index; // Integer part of index
alpha = index - (StkFloat) temp; // Fractional part of index
if (alpha > 0.0) { // Do linear interpolation
lastOutput = data[temp];
lastOutput += (alpha*(data[temp+1] - lastOutput));
lastOutput_ = data_[temp];
lastOutput_ += (alpha*(data_[temp+1] - lastOutput_));
}
else lastOutput = data[temp];
else lastOutput_ = data_[temp];
return lastOutput;
return lastOutput_;
}
MY_FLOAT *Table :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *Table :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Function::tick( vector, vectorSize );
}
StkFrames& Table :: tick( StkFrames& frames, unsigned int channel )
{
return Function::tick( frames, channel );
}

View File

@@ -20,15 +20,15 @@
for a single remote connection. The default
data type for the incoming stream is signed
16-bit integers, though any of the defined
STK_FORMATs are permissible.
StkFormats are permissible.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "TcpWvIn.h"
#define N_BUFFERS 10
const int N_BUFFERS = 10;
// Do OS dependent includes
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
@@ -42,7 +42,6 @@ extern "C" THREAD_RETURN THREAD_TYPE inputThread(void * ptr)
thread_info *info = (thread_info *)ptr;
while ( !info->finished ) {
Thread::test();
((TcpWvIn *) info->object)->receive();
}
@@ -57,135 +56,137 @@ TcpWvIn :: TcpWvIn( int port )
TcpWvIn :: ~TcpWvIn()
{
// Close down the thread.
connected = false;
threadInfo.finished = true;
thread->wait( -1 );
delete thread;
connected_ = false;
threadInfo_.finished = true;
delete thread_;
delete soket;
delete soket_;
if (buffer)
delete [] buffer;
if (buffer_)
delete [] buffer_;
}
void TcpWvIn :: init( int port )
{
buffer = 0;
bufferBytes = 0;
connected = false;
buffer_ = 0;
bufferBytes_ = 0;
connected_ = false;
// Start socket server ... an error can be thrown from the Socket class.
soket = new Socket( port );
soket_ = new Socket( port );
thread = new Thread();
threadInfo.finished = false;
threadInfo.object = (void *) this;
thread_ = new Thread();
threadInfo_.finished = false;
threadInfo_.object = (void *) this;
// Start the input thread.
if ( !thread->start( &inputThread, &threadInfo ) ) {
sprintf(msg, "TcpWvIn: Unable to start input thread!");
handleError( msg, StkError::PROCESS_THREAD );
if ( !thread_->start( &inputThread, &threadInfo_ ) ) {
errorString_ << "TcpWvIn::init: unable to start input thread!";
handleError( StkError::PROCESS_THREAD );
}
}
void TcpWvIn :: listen(unsigned int nChannels, Stk::STK_FORMAT format)
void TcpWvIn :: listen(unsigned int nChannels, Stk::StkFormat format)
{
mutex.lock();
mutex_.lock();
if ( connected ) {
soket->close(fd);
if ( connected_ ) {
soket_->close(fd_);
}
if (nChannels < 1) {
sprintf(msg, "TcpWvOut: the channel argument (%d) must be greater than zero.", nChannels);
handleError( msg, StkError::FUNCTION_ARGUMENT );
if ( nChannels < 1 ) {
errorString_ << "TcpWvOut::listen: the channel argument (" << nChannels << ") must be greater than zero.";
handleError( StkError::FUNCTION_ARGUMENT );
}
unsigned int lastChannels = channels;
channels = nChannels;
unsigned int lastChannels = channels_;
channels_ = nChannels;
if ( format == STK_SINT16 ) dataSize = 2;
else if ( format == STK_SINT32 || format == MY_FLOAT32 ) dataSize = 4;
else if ( format == MY_FLOAT64 ) dataSize = 8;
else if ( format == STK_SINT8 ) dataSize = 1;
if ( format == STK_SINT16 ) dataSize_ = 2;
else if ( format == STK_SINT32 || format == STK_FLOAT32 ) dataSize_ = 4;
else if ( format == STK_FLOAT64 ) dataSize_ = 8;
else if ( format == STK_SINT8 ) dataSize_ = 1;
else {
sprintf( msg, "TcpWvIn: Unknown data type specified (%ld).", format );
handleError(msg, StkError::FUNCTION_ARGUMENT);
errorString_ << "TcpWvIn::listen: unknown data type specified (" << format << ").";
handleError( StkError::FUNCTION_ARGUMENT );
}
dataType = format;
dataType_ = format;
int lastBufferBytes = bufferBytes;
bufferBytes = CHUNK_SIZE * N_BUFFERS * channels * dataSize;
int lastBufferBytes = bufferBytes_;
bufferBytes_ = CHUNK_SIZE * N_BUFFERS * channels_ * dataSize_;
// Allocate new memory if necessary.
if ( lastBufferBytes < bufferBytes ) {
if ( buffer) delete [] buffer;
buffer = (char *) new char[bufferBytes];
if ( lastBufferBytes < bufferBytes_ ) {
if ( buffer_) delete [] buffer_;
buffer_ = (char *) new char[bufferBytes_];
}
if ( lastChannels < channels ) {
if ( data ) delete [] data;
data = (MY_FLOAT *) new MY_FLOAT[CHUNK_SIZE*channels];
if ( lastOutput ) delete [] lastOutput;
lastOutput = (MY_FLOAT *) new MY_FLOAT[channels];
if ( lastChannels < channels_ ) {
if ( data_ ) delete [] data_;
data_ = (StkFloat *) new StkFloat[CHUNK_SIZE*channels_];
if ( lastOutputs_ ) delete [] lastOutputs_;
lastOutputs_ = (StkFloat *) new StkFloat[channels_];
}
WvIn::reset();
counter = 0;
writePoint = 0;
bytesFilled = 0;
counter_ = 0;
writePoint_ = 0;
bytesFilled_ = 0;
// Accept a connection.
printf("Listening for connection on port %d ... ", soket->port());
fd = soket->accept();
if ( fd < 0) {
sprintf( msg, "TcpWvIn: Couldn't accept connection request!");
handleError( msg, StkError::PROCESS_SOCKET );
errorString_ << "TcpWvIn: listening for connection on port " << soket_->port() << " ... ";
handleError( StkError::STATUS );
fd_ = soket_->accept();
if ( fd_ < 0) {
errorString_ << "TcpWvIn: Could not accept connection request!";
handleError( StkError::PROCESS_SOCKET );
}
printf(" connection made!\n\n");
errorString_ << "TcpWvIn::listen: connection made!";
handleError( StkError::STATUS );
// Start input thread.
connected = true;
connected_ = true;
mutex.unlock();
mutex_.unlock();
}
void TcpWvIn :: receive( void )
{
if ( !connected ) {
if ( !connected_ ) {
Stk::sleep(100);
return;
}
fd_set mask;
FD_ZERO(&mask);
FD_SET(fd, &mask);
FD_SET(fd_, &mask);
// The select function will block until data is available for reading.
select(fd+1, &mask, (fd_set *)0, (fd_set *)0, NULL);
select(fd_+1, &mask, (fd_set *)0, (fd_set *)0, NULL);
if (FD_ISSET(fd, &mask)) {
mutex.lock();
long unfilled = bufferBytes - bytesFilled;
if (FD_ISSET(fd_, &mask)) {
mutex_.lock();
long unfilled = bufferBytes_ - bytesFilled_;
if ( unfilled > 0 ) {
// There's room in our buffer for more data.
long endPoint = writePoint + unfilled;
if ( endPoint > bufferBytes ) unfilled -= endPoint - bufferBytes;
int i = Socket::readBuffer(fd, (void *)&buffer[writePoint], unfilled, 0);
long endPoint = writePoint_ + unfilled;
if ( endPoint > bufferBytes_ ) unfilled -= endPoint - bufferBytes_;
int i = Socket::readBuffer(fd_, (void *)&buffer_[writePoint_], unfilled, 0);
if ( i <= 0 ) {
printf("The remote TcpWvIn socket connection has closed.\n\n");
connected = false;
mutex.unlock();
errorString_ << "TcpWvIn::receive: the remote TcpWvIn socket connection has closed.";
handleError( StkError::STATUS );
connected_ = false;
mutex_.unlock();
return;
}
bytesFilled += i;
writePoint += i;
if (writePoint == bufferBytes)
writePoint = 0;
mutex.unlock();
bytesFilled_ += i;
writePoint_ += i;
if (writePoint_ == bufferBytes_)
writePoint_ = 0;
mutex_.unlock();
}
else {
// Sleep 10 milliseconds AFTER unlocking mutex.
mutex.unlock();
mutex_.unlock();
Stk::sleep( 10 );
}
}
@@ -202,124 +203,134 @@ int TcpWvIn :: readData( void )
// adequate network bandwidth and speed).
// Wait until data is ready.
long bytes = CHUNK_SIZE * channels * dataSize;
while ( connected && bytesFilled < bytes )
long bytes = CHUNK_SIZE * channels_ * dataSize_;
while ( connected_ && bytesFilled_ < bytes )
Stk::sleep( 10 );
if ( !connected && bytesFilled == 0 ) return 0;
bytes = ( bytesFilled < bytes ) ? bytesFilled : bytes;
if ( !connected_ && bytesFilled_ == 0 ) return 0;
bytes = ( bytesFilled_ < bytes ) ? bytesFilled_ : bytes;
// Copy samples from buffer to data.
long samples = bytes / dataSize;
mutex.lock();
if ( dataType == STK_SINT16 ) {
gain = 1.0 / 32767.0;
SINT16 *buf = (SINT16 *) (buffer+readPoint);
long samples = bytes / dataSize_;
mutex_.lock();
if ( dataType_ == STK_SINT16 ) {
gain_ = 1.0 / 32767.0;
SINT16 *buf = (SINT16 *) (buffer_+readPoint_);
for (int i=0; i<samples; i++ ) {
#ifdef __LITTLE_ENDIAN__
swap16((unsigned char *) buf);
#endif
data[i] = (MY_FLOAT) *buf++;
data[i] *= gain;
data_[i] = (StkFloat) *buf++;
data_[i] *= gain_;
}
}
else if ( dataType == STK_SINT32 ) {
gain = 1.0 / 2147483647.0;
SINT32 *buf = (SINT32 *) (buffer+readPoint);
else if ( dataType_ == STK_SINT32 ) {
gain_ = 1.0 / 2147483647.0;
SINT32 *buf = (SINT32 *) (buffer_+readPoint_);
for (int i=0; i<samples; i++ ) {
#ifdef __LITTLE_ENDIAN__
swap32((unsigned char *) buf);
#endif
data[i] = (MY_FLOAT) *buf++;
data[i] *= gain;
data_[i] = (StkFloat) *buf++;
data_[i] *= gain_;
}
}
else if ( dataType == MY_FLOAT32 ) {
FLOAT32 *buf = (FLOAT32 *) (buffer+readPoint);
else if ( dataType_ == STK_FLOAT32 ) {
FLOAT32 *buf = (FLOAT32 *) (buffer_+readPoint_);
for (int i=0; i<samples; i++ ) {
#ifdef __LITTLE_ENDIAN__
swap32((unsigned char *) buf);
#endif
data[i] = (MY_FLOAT) *buf++;
data_[i] = (StkFloat) *buf++;
}
}
else if ( dataType == MY_FLOAT64 ) {
FLOAT64 *buf = (FLOAT64 *) (buffer+readPoint);
else if ( dataType_ == STK_FLOAT64 ) {
FLOAT64 *buf = (FLOAT64 *) (buffer_+readPoint_);
for (int i=0; i<samples; i++ ) {
#ifdef __LITTLE_ENDIAN__
swap64((unsigned char *) buf);
#endif
data[i] = (MY_FLOAT) *buf++;
data_[i] = (StkFloat) *buf++;
}
}
else if ( dataType == STK_SINT8 ) {
gain = 1.0 / 127.0;
signed char *buf = (signed char *) (buffer+readPoint);
else if ( dataType_ == STK_SINT8 ) {
gain_ = 1.0 / 127.0;
signed char *buf = (signed char *) (buffer_+readPoint_);
for (int i=0; i<samples; i++ ) {
data[i] = (MY_FLOAT) *buf++;
data[i] *= gain;
data_[i] = (StkFloat) *buf++;
data_[i] *= gain_;
}
}
readPoint += bytes;
if ( readPoint == bufferBytes )
readPoint = 0;
bytesFilled -= bytes;
if ( bytesFilled < 0 )
bytesFilled = 0;
readPoint_ += bytes;
if ( readPoint_ == bufferBytes_ )
readPoint_ = 0;
bytesFilled_ -= bytes;
if ( bytesFilled_ < 0 )
bytesFilled_ = 0;
mutex.unlock();
return samples / channels;
mutex_.unlock();
return samples / channels_;
}
bool TcpWvIn :: isConnected(void)
{
if ( bytesFilled > 0 || counter > 0 )
if ( bytesFilled_ > 0 || counter_ > 0 )
return true;
else
return connected;
return connected_;
}
const MY_FLOAT *TcpWvIn :: lastFrame(void) const
const StkFloat *TcpWvIn :: lastFrame(void) const
{
return lastOutput;
return lastOutputs_;
}
MY_FLOAT TcpWvIn :: lastOut(void) const
StkFloat TcpWvIn :: lastOut(void) const
{
return WvIn::lastOut();
}
MY_FLOAT TcpWvIn :: tick(void)
StkFloat TcpWvIn :: tick(void)
{
return WvIn::tick();
}
MY_FLOAT *TcpWvIn :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *TcpWvIn :: tick(StkFloat *vector, unsigned int vectorSize)
{
return WvIn::tick( vector, vectorSize );
}
const MY_FLOAT *TcpWvIn :: tickFrame(void)
StkFrames& TcpWvIn :: tick( StkFrames& frames, unsigned int channel )
{
// If no connection and we've output all samples in the queue, return.
if ( !connected && bytesFilled == 0 && counter == 0 ) return lastOutput;
if (counter == 0)
counter = readData();
long temp = (CHUNK_SIZE - counter) * channels;
for (unsigned int i=0; i<channels; i++)
lastOutput[i] = data[temp++];
counter--;
if ( counter < 0 )
counter = 0;
return lastOutput;
return WvIn::tick( frames, channel );
}
MY_FLOAT *TcpWvIn :: tickFrame(MY_FLOAT *frameVector, unsigned int frames)
const StkFloat *TcpWvIn :: tickFrame(void)
{
// If no connection and we've output all samples in the queue, return.
if ( !connected_ && bytesFilled_ == 0 && counter_ == 0 ) return lastOutputs_;
if (counter_ == 0)
counter_ = readData();
long temp = (CHUNK_SIZE - counter_) * channels_;
for (unsigned int i=0; i<channels_; i++)
lastOutputs_[i] = data_[temp++];
counter_--;
if ( counter_ < 0 )
counter_ = 0;
return lastOutputs_;
}
StkFloat *TcpWvIn :: tickFrame(StkFloat *frameVector, unsigned int frames)
{
return WvIn::tickFrame( frameVector, frames );
}
StkFrames& TcpWvIn :: tickFrame( StkFrames& frames )
{
return WvIn::tickFrame( frames );
}

View File

@@ -19,9 +19,9 @@
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 STK_FORMATs are permissible.
defined StkFormats are permissible.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -30,112 +30,117 @@
TcpWvOut :: TcpWvOut()
{
buffer = 0;
soket = 0;
buffer_ = 0;
soket_ = 0;
}
TcpWvOut :: TcpWvOut(int port, const char *hostname, unsigned int nChannels, Stk::STK_FORMAT format)
TcpWvOut :: TcpWvOut(int port, const char *hostname, unsigned int nChannels, Stk::StkFormat format)
{
buffer = 0;
soket = 0;
buffer_ = 0;
soket_ = 0;
connect( port, hostname, nChannels, format );
}
TcpWvOut :: ~TcpWvOut()
{
disconnect();
delete soket;
delete [] buffer;
delete soket_;
delete [] buffer_;
}
void TcpWvOut :: connect(int port, const char *hostname, unsigned int nChannels, Stk::STK_FORMAT format)
void TcpWvOut :: connect(int port, const char *hostname, unsigned int nChannels, Stk::StkFormat format)
{
if ( soket && soket->isValid( soket->socket() ) )
if ( soket_ && soket_->isValid( soket_->id() ) )
disconnect();
if (nChannels < 1) {
sprintf(msg, "TcpWvOut: the channel argument (%d) must be greater than zero.", nChannels);
handleError( msg, StkError::FUNCTION_ARGUMENT );
errorString_ << "TcpWvOut::connect: the channel argument (" << nChannels << ") must be greater than zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
unsigned int lastChannels = channels;
channels = nChannels;
unsigned int lastChannels = channels_;
channels_ = nChannels;
if ( format == STK_SINT8 ) dataSize = 1;
else if ( format == STK_SINT16 ) dataSize = 2;
else if ( format == STK_SINT32 || format == MY_FLOAT32 ) dataSize = 4;
else if ( format == MY_FLOAT64 ) dataSize = 8;
if ( format == STK_SINT8 ) dataSize_ = 1;
else if ( format == STK_SINT16 ) dataSize_ = 2;
else if ( format == STK_SINT32 || format == STK_FLOAT32 ) dataSize_ = 4;
else if ( format == STK_FLOAT64 ) dataSize_ = 8;
else {
sprintf( msg, "TcpWvOut: Unknown data type specified (%ld).", format );
handleError(msg, StkError::FUNCTION_ARGUMENT);
errorString_ << "TcpWvOut::connect: unknown data type specified (" << format << ").";
handleError( StkError::FUNCTION_ARGUMENT );
}
dataType = format;
dataType_ = format;
if ( !soket )
soket = new Socket( port, hostname );
if ( !soket_ )
soket_ = new Socket( port, hostname );
else
soket->connect( port, hostname );
soket_->connect( port, hostname );
// Allocate new memory if necessary.
if ( lastChannels < channels ) {
if ( data ) delete [] data;
data = (MY_FLOAT *) new MY_FLOAT[BUFFER_SIZE*channels];
if ( buffer) delete [] buffer;
long bytes = dataSize * BUFFER_SIZE * channels;
buffer = (char *) new char[bytes];
if ( lastChannels < channels_ ) {
data_.resize( BUFFER_SIZE*channels_ );
if ( buffer_) delete [] buffer_;
long bytes = dataSize_ * BUFFER_SIZE * channels_;
buffer_ = (char *) new char[bytes];
}
counter = 0;
counter_ = 0;
}
void TcpWvOut :: disconnect(void)
{
if ( soket ) {
writeData( counter );
soket->close();
if ( soket_ ) {
writeData( counter_ );
soket_->close();
}
}
void TcpWvOut :: writeData( unsigned long frames )
{
if ( dataType == STK_SINT8 ) {
signed char *ptr = (signed char *) buffer;
for ( unsigned long k=0; k<frames*channels; k++ )
*ptr++ = (signed char) (data[k] * 127.0);
if ( dataType_ == STK_SINT8 ) {
signed char *ptr = (signed char *) buffer_;
for ( unsigned long k=0; k<frames*channels_; k++ ) {
this->clipTest( data_[k] );
*ptr++ = (signed char) (data_[k] * 127.0);
}
}
else if ( dataType == STK_SINT16 ) {
SINT16 *ptr = (SINT16 *) buffer;
for ( unsigned long k=0; k<frames*channels; k++ ) {
*ptr = (SINT16) (data[k] * 32767.0);
else if ( dataType_ == STK_SINT16 ) {
SINT16 *ptr = (SINT16 *) buffer_;
for ( unsigned long k=0; k<frames*channels_; k++ ) {
this->clipTest( data_[k] );
*ptr = (SINT16) (data_[k] * 32767.0);
#ifdef __LITTLE_ENDIAN__
swap16 ((unsigned char *)ptr);
#endif
ptr++;
}
}
else if ( dataType == STK_SINT32 ) {
SINT32 *ptr = (SINT32 *) buffer;
for ( unsigned long k=0; k<frames*channels; k++ ) {
*ptr = (SINT32) (data[k] * 2147483647.0);
else if ( dataType_ == STK_SINT32 ) {
SINT32 *ptr = (SINT32 *) buffer_;
for ( unsigned long k=0; k<frames*channels_; k++ ) {
this->clipTest( data_[k] );
*ptr = (SINT32) (data_[k] * 2147483647.0);
#ifdef __LITTLE_ENDIAN__
swap32 ((unsigned char *)ptr);
#endif
ptr++;
}
}
else if ( dataType == MY_FLOAT32 ) {
FLOAT32 *ptr = (FLOAT32 *) buffer;
for ( unsigned long k=0; k<frames*channels; k++ ) {
*ptr = (FLOAT32) data[k];
else if ( dataType_ == STK_FLOAT32 ) {
FLOAT32 *ptr = (FLOAT32 *) buffer_;
for ( unsigned long k=0; k<frames*channels_; k++ ) {
this->clipTest( data_[k] );
*ptr = (FLOAT32) data_[k];
#ifdef __LITTLE_ENDIAN__
swap32 ((unsigned char *)ptr);
#endif
ptr++;
}
}
else if ( dataType == MY_FLOAT64 ) {
FLOAT64 *ptr = (FLOAT64 *) buffer;
for ( unsigned long k=0; k<frames*channels; k++ ) {
*ptr = (FLOAT64) data[k];
else if ( dataType_ == STK_FLOAT64 ) {
FLOAT64 *ptr = (FLOAT64 *) buffer_;
for ( unsigned long k=0; k<frames*channels_; k++ ) {
this->clipTest( data_[k] );
*ptr = (FLOAT64) data_[k];
#ifdef __LITTLE_ENDIAN__
swap64 ((unsigned char *)ptr);
#endif
@@ -143,62 +148,133 @@ void TcpWvOut :: writeData( unsigned long frames )
}
}
long bytes = dataSize * frames * channels;
if ( soket->writeBuffer( (const void *)buffer, bytes, 0 ) < 0 ) {
sprintf(msg, "TcpWvOut: connection to socket server failed!");
handleError( msg, StkError::PROCESS_SOCKET );
long bytes = dataSize_ * frames * channels_;
if ( soket_->writeBuffer( (const void *)buffer_, bytes, 0 ) < 0 ) {
errorString_ << "TcpWvOut: connection to socket server failed!";
handleError( StkError::PROCESS_SOCKET );
}
}
unsigned long TcpWvOut :: getFrames( void ) const
{
return totalCount;
return totalCount_;
}
MY_FLOAT TcpWvOut :: getTime( void ) const
StkFloat TcpWvOut :: getTime( void ) const
{
return (MY_FLOAT) totalCount / Stk::sampleRate();
return (StkFloat) totalCount_ / Stk::sampleRate();
}
void TcpWvOut :: tick(MY_FLOAT sample)
void TcpWvOut :: tick( const StkFloat sample )
{
if ( !soket || !soket->isValid( soket->socket() ) ) return;
if ( !soket_ || !soket_->isValid( soket_->id() ) ) return;
for ( unsigned int j=0; j<channels; j++ )
data[counter*channels+j] = sample;
for ( unsigned int j=0; j<channels_; j++ )
data_[counter_*channels_+j] = sample;
counter++;
totalCount++;
counter_++;
totalCount_++;
if ( counter == BUFFER_SIZE ) {
if ( counter_ == BUFFER_SIZE ) {
writeData( BUFFER_SIZE );
counter = 0;
counter_ = 0;
}
}
void TcpWvOut :: tick(const MY_FLOAT *vector, unsigned int vectorSize)
void TcpWvOut :: tick( const StkFloat *vector, unsigned int vectorSize )
{
if ( !soket || !soket->isValid( soket->socket() ) ) return;
if ( !soket_ || !soket_->isValid( soket_->id() ) ) return;
for (unsigned int i=0; i<vectorSize; i++)
tick( vector[i] );
}
void TcpWvOut :: tickFrame(const MY_FLOAT *frameVector, unsigned int frames)
void TcpWvOut :: tick( const StkFrames& frames, unsigned int channel )
{
if ( !soket || !soket->isValid( soket->socket() ) ) return;
if ( channel == 0 || frames.channels() < channel ) {
errorString_ << "TcpWvOut::tick(): channel argument (" << channel << ") is zero or > channels in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( !soket_ || !soket_->isValid( soket_->id() ) ) return;
if ( frames.channels() == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++ )
tick( frames[i] );
}
else if ( frames.interleaved() ) {
unsigned int hop = frames.channels();
unsigned int index = channel - 1;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
tick( frames[index] );
index += hop;
}
}
else {
unsigned int iStart = (channel - 1) * frames.frames();
for ( unsigned int i=0; i<frames.frames(); i++ )
tick( frames[iStart + i] );
}
}
void TcpWvOut :: tickFrame( const StkFloat *frameVector, unsigned int frames )
{
if ( !soket_ || !soket_->isValid( soket_->id() ) ) return;
unsigned int j;
for ( unsigned int i=0; i<frames; i++ ) {
for ( j=0; j<channels; j++ ) {
data[counter*channels+j] = frameVector[i*channels+j];
for ( j=0; j<channels_; j++ ) {
data_[counter_*channels_+j] = frameVector[i*channels_+j];
}
counter++;
totalCount++;
counter_++;
totalCount_++;
if ( counter == BUFFER_SIZE ) {
if ( counter_ == BUFFER_SIZE ) {
writeData( BUFFER_SIZE );
counter = 0;
counter_ = 0;
}
}
}
void TcpWvOut :: tickFrame( const StkFrames& frames )
{
if ( channels_ != frames.channels() ) {
errorString_ << "TcpWvOut::tickFrame(): incompatible channel value in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( !soket_ || !soket_->isValid( soket_->id() ) ) return;
unsigned int j;
if ( channels_ == 1 || frames.interleaved() ) {
unsigned long iFrames = 0, iData = counter_;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
for ( j=0; j<channels_; j++ ) {
data_[iData++] = frames[iFrames++];
}
counter_++;
totalCount_++;
if ( counter_ == BUFFER_SIZE ) {
writeData( BUFFER_SIZE );
counter_ = 0;
}
}
}
else {
unsigned int hop = frames.frames();
unsigned long iData = counter_;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
for ( j=0; j<channels_; j++ ) {
data_[iData++] = frames[i + j*hop];
}
counter_++;
totalCount_++;
if ( counter_ == BUFFER_SIZE ) {
writeData( BUFFER_SIZE );
counter_ = 0;
}
}
}
}

View File

@@ -7,7 +7,7 @@
systems, the pthread library is used. Under Windows,
the Windows thread library is used.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -15,66 +15,75 @@
Thread :: Thread()
{
thread = 0;
thread_ = 0;
}
Thread :: ~Thread()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
pthread_cancel(thread);
pthread_join(thread, NULL);
#elif defined(__OS_WINDOWS__)
if ( thread )
TerminateThread((HANDLE)thread, 0);
#endif
}
bool Thread :: start( THREAD_FUNCTION routine, void * ptr )
{
bool result = false;
if ( thread_ ) {
errorString_ << "Thread:: a thread is already running!";
handleError( StkError::WARNING );
return false;
}
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
if ( pthread_create(&thread, NULL, *routine, ptr) == 0 )
result = true;
if ( pthread_create(&thread_, NULL, *routine, ptr) == 0 )
return true;
#elif defined(__OS_WINDOWS__)
unsigned thread_id;
thread = _beginthreadex(NULL, 0, routine, ptr, 0, &thread_id);
if ( thread ) result = true;
thread_ = _beginthreadex(NULL, 0, routine, ptr, 0, &thread_id);
if ( thread_ ) return true;
#endif
return result;
return false;
}
bool Thread :: wait( long milliseconds )
bool Thread :: cancel()
{
bool result = false;
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
pthread_cancel(thread);
pthread_join(thread, NULL);
if ( pthread_cancel(thread_) == 0 ) {
return true;
}
#elif defined(__OS_WINDOWS__)
DWORD timeout, retval;
if ( milliseconds < 0 ) timeout = INFINITE;
else timeout = milliseconds;
retval = WaitForSingleObject( (HANDLE)thread, timeout );
TerminateThread((HANDLE)thread_, 0);
return true;
#endif
return false;
}
bool Thread :: wait()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
if ( pthread_join(thread_, NULL) == 0 ) {
thread_ = 0;
return true;
}
#elif defined(__OS_WINDOWS__)
long retval = WaitForSingleObject( (HANDLE)thread_, INFINITE );
if ( retval == WAIT_OBJECT_0 ) {
CloseHandle( (HANDLE)thread );
thread = 0;
result = true;
CloseHandle( (HANDLE)thread_ );
thread_ = 0;
return true;
}
#endif
return result;
return false;
}
void Thread :: test(void)
void Thread :: testCancel(void)
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
@@ -82,57 +91,3 @@ void Thread :: test(void)
#endif
}
Mutex :: Mutex()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
pthread_mutex_init(&mutex, NULL);
#elif defined(__OS_WINDOWS__)
InitializeCriticalSection(&mutex);
#endif
}
Mutex :: ~Mutex()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
pthread_mutex_destroy(&mutex);
#elif defined(__OS_WINDOWS__)
DeleteCriticalSection(&mutex);
#endif
}
void Mutex :: lock()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
pthread_mutex_lock(&mutex);
#elif defined(__OS_WINDOWS__)
EnterCriticalSection(&mutex);
#endif
}
void Mutex :: unlock()
{
#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
pthread_mutex_unlock(&mutex);
#elif defined(__OS_WINDOWS__)
LeaveCriticalSection(&mutex);
#endif
}

View File

@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -36,67 +36,78 @@ TubeBell :: TubeBell()
: FM()
{
// Concatenate the STK rawwave path to the rawwave files
for ( int i=0; i<3; i++ )
waves[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
waves[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), TRUE );
for ( unsigned int i=0; i<3; i++ )
waves_[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
waves_[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true );
this->setRatio(0, 1.0 * 0.995);
this->setRatio(1, 1.414 * 0.995);
this->setRatio(2, 1.0 * 1.005);
this->setRatio(3, 1.414 * 1.000);
gains[0] = __FM_gains[94];
gains[1] = __FM_gains[76];
gains[2] = __FM_gains[99];
gains[3] = __FM_gains[71];
gains_[0] = fmGains_[94];
gains_[1] = fmGains_[76];
gains_[2] = fmGains_[99];
gains_[3] = fmGains_[71];
adsr[0]->setAllTimes( 0.005, 4.0, 0.0, 0.04);
adsr[1]->setAllTimes( 0.005, 4.0, 0.0, 0.04);
adsr[2]->setAllTimes( 0.001, 2.0, 0.0, 0.04);
adsr[3]->setAllTimes( 0.004, 4.0, 0.0, 0.04);
adsr_[0]->setAllTimes( 0.005, 4.0, 0.0, 0.04);
adsr_[1]->setAllTimes( 0.005, 4.0, 0.0, 0.04);
adsr_[2]->setAllTimes( 0.001, 2.0, 0.0, 0.04);
adsr_[3]->setAllTimes( 0.004, 4.0, 0.0, 0.04);
twozero->setGain( 0.5 );
vibrato->setFrequency( 2.0 );
twozero_.setGain( 0.5 );
vibrato_->setFrequency( 2.0 );
}
TubeBell :: ~TubeBell()
{
}
void TubeBell :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void TubeBell :: noteOn(StkFloat frequency, StkFloat amplitude)
{
gains[0] = amplitude * __FM_gains[94];
gains[1] = amplitude * __FM_gains[76];
gains[2] = amplitude * __FM_gains[99];
gains[3] = amplitude * __FM_gains[71];
this->setFrequency(frequency);
gains_[0] = amplitude * fmGains_[94];
gains_[1] = amplitude * fmGains_[76];
gains_[2] = amplitude * fmGains_[99];
gains_[3] = amplitude * fmGains_[71];
this->setFrequency( frequency );
this->keyOn();
#if defined(_STK_DEBUG_)
cerr << "TubeBell: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << endl;
errorString_ << "TubeBell::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT TubeBell :: tick()
StkFloat TubeBell :: tick()
{
MY_FLOAT temp, temp2;
StkFloat temp, temp2;
temp = gains[1] * adsr[1]->tick() * waves[1]->tick();
temp = temp * control1;
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_[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();
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;
temp2 = vibrato_->tick() * modDepth_;
temp = temp * (1.0 + temp2);
lastOutput = temp * 0.5;
return lastOutput;
lastOutput_ = temp * 0.5;
return lastOutput_;
}
StkFloat *TubeBell :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& TubeBell :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

View File

@@ -8,7 +8,7 @@
frequency response while maintaining a nearly
constant filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -17,9 +17,10 @@
TwoPole :: TwoPole() : Filter()
{
MY_FLOAT B = 1.0;
MY_FLOAT A[3] = {1.0, 0.0, 0.0};
Filter::setCoefficients( 1, &B, 3, A );
std::vector<StkFloat> b(1, 1.0);
std::vector<StkFloat> a(3, 0.0);
a[0] = 1.0;
Filter::setCoefficients( b, a );
}
TwoPole :: ~TwoPole()
@@ -31,63 +32,65 @@ void TwoPole :: clear(void)
Filter::clear();
}
void TwoPole :: setB0(MY_FLOAT b0)
void TwoPole :: setB0(StkFloat b0)
{
b[0] = b0;
b_[0] = b0;
}
void TwoPole :: setA1(MY_FLOAT a1)
void TwoPole :: setA1(StkFloat a1)
{
a[1] = a1;
a_[1] = a1;
}
void TwoPole :: setA2(MY_FLOAT a2)
void TwoPole :: setA2(StkFloat a2)
{
a[2] = a2;
a_[2] = a2;
}
void TwoPole :: setResonance(MY_FLOAT frequency, MY_FLOAT radius, bool normalize)
void TwoPole :: setResonance(StkFloat frequency, StkFloat radius, bool normalize)
{
a[2] = radius * radius;
a[1] = (MY_FLOAT) -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate());
a_[2] = radius * radius;
a_[1] = (StkFloat) -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate());
if ( normalize ) {
// Normalize the filter gain ... not terribly efficient.
MY_FLOAT real = 1 - radius + (a[2] - radius) * cos(TWO_PI * 2 * frequency / Stk::sampleRate());
MY_FLOAT imag = (a[2] - radius) * sin(TWO_PI * 2 * frequency / Stk::sampleRate());
b[0] = sqrt( pow(real, 2) + pow(imag, 2) );
StkFloat real = 1 - radius + (a_[2] - radius) * cos(TWO_PI * 2 * frequency / Stk::sampleRate());
StkFloat imag = (a_[2] - radius) * sin(TWO_PI * 2 * frequency / Stk::sampleRate());
b_[0] = sqrt( pow(real, 2) + pow(imag, 2) );
}
}
void TwoPole :: setGain(MY_FLOAT theGain)
void TwoPole :: setGain(StkFloat gain)
{
Filter::setGain(theGain);
Filter::setGain(gain);
}
MY_FLOAT TwoPole :: getGain(void) const
StkFloat TwoPole :: getGain(void) const
{
return Filter::getGain();
}
MY_FLOAT TwoPole :: lastOut(void) const
StkFloat TwoPole :: lastOut(void) const
{
return Filter::lastOut();
}
MY_FLOAT TwoPole :: tick(MY_FLOAT sample)
StkFloat TwoPole :: tick(StkFloat sample)
{
inputs[0] = gain * sample;
outputs[0] = b[0] * inputs[0] - a[2] * outputs[2] - a[1] * outputs[1];
outputs[2] = outputs[1];
outputs[1] = outputs[0];
inputs_[0] = gain_ * sample;
outputs_[0] = b_[0] * inputs_[0] - a_[2] * outputs_[2] - a_[1] * outputs_[1];
outputs_[2] = outputs_[1];
outputs_[1] = outputs_[0];
return outputs[0];
return outputs_[0];
}
MY_FLOAT *TwoPole :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *TwoPole :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Filter::tick( vector, vectorSize );
}
StkFrames& TwoPole :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
}

View File

@@ -8,7 +8,7 @@
frequency response while maintaining a
constant filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -17,9 +17,10 @@
TwoZero :: TwoZero() : Filter()
{
MY_FLOAT B[3] = {1.0, 0.0, 0.0};
MY_FLOAT A = 1.0;
Filter::setCoefficients( 3, B, 1, &A );
std::vector<StkFloat> b(3, 0.0);
b[0] = 1.0;
std::vector<StkFloat> a(1, 1.0);
Filter::setCoefficients( b, a );
}
TwoZero :: ~TwoZero()
@@ -31,64 +32,66 @@ void TwoZero :: clear(void)
Filter::clear();
}
void TwoZero :: setB0(MY_FLOAT b0)
void TwoZero :: setB0(StkFloat b0)
{
b[0] = b0;
b_[0] = b0;
}
void TwoZero :: setB1(MY_FLOAT b1)
void TwoZero :: setB1(StkFloat b1)
{
b[1] = b1;
b_[1] = b1;
}
void TwoZero :: setB2(MY_FLOAT b2)
void TwoZero :: setB2(StkFloat b2)
{
b[2] = b2;
b_[2] = b2;
}
void TwoZero :: setNotch(MY_FLOAT frequency, MY_FLOAT radius)
void TwoZero :: setNotch(StkFloat frequency, StkFloat radius)
{
b[2] = radius * radius;
b[1] = (MY_FLOAT) -2.0 * radius * cos(TWO_PI * (double) frequency / Stk::sampleRate());
b_[2] = radius * radius;
b_[1] = (StkFloat) -2.0 * radius * cos(TWO_PI * (double) frequency / Stk::sampleRate());
// Normalize the filter gain.
if (b[1] > 0.0) // Maximum at z = 0.
b[0] = 1.0 / (1.0+b[1]+b[2]);
if (b_[1] > 0.0) // Maximum at z = 0.
b_[0] = 1.0 / (1.0+b_[1]+b_[2]);
else // Maximum at z = -1.
b[0] = 1.0 / (1.0-b[1]+b[2]);
b[1] *= b[0];
b[2] *= b[0];
b_[0] = 1.0 / (1.0-b_[1]+b_[2]);
b_[1] *= b_[0];
b_[2] *= b_[0];
}
void TwoZero :: setGain(MY_FLOAT theGain)
void TwoZero :: setGain(StkFloat gain)
{
Filter::setGain(theGain);
Filter::setGain(gain);
}
MY_FLOAT TwoZero :: getGain(void) const
StkFloat TwoZero :: getGain(void) const
{
return Filter::getGain();
}
MY_FLOAT TwoZero :: lastOut(void) const
StkFloat TwoZero :: lastOut(void) const
{
return Filter::lastOut();
}
MY_FLOAT TwoZero :: tick(MY_FLOAT sample)
StkFloat TwoZero :: tick(StkFloat sample)
{
inputs[0] = gain * sample;
outputs[0] = b[2] * inputs[2] + b[1] * inputs[1] + b[0] * inputs[0];
inputs[2] = inputs[1];
inputs[1] = inputs[0];
inputs_[0] = gain_ * sample;
outputs_[0] = b_[2] * inputs_[2] + b_[1] * inputs_[1] + b_[0] * inputs_[0];
inputs_[2] = inputs_[1];
inputs_[1] = inputs_[0];
return outputs[0];
return outputs_[0];
}
MY_FLOAT *TwoZero :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *TwoZero :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick(vector[i]);
return vector;
return Filter::tick( vector, vectorSize );
}
StkFrames& TwoZero :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
}

View File

@@ -4,69 +4,69 @@
This class implements a three-dimensional vector.
by Perry R. Cook, 1995 - 2002.
by Perry R. Cook, 1995 - 2004.
*/
/***************************************************/
#include "Vector3D.h"
#include <math.h>
Vector3D :: Vector3D(double initX, double initY, double initZ)
Vector3D :: Vector3D(StkFloat initX, StkFloat initY, StkFloat initZ)
{
myX = initX;
myY = initY;
myZ = initZ;
myX_ = initX;
myY_ = initY;
myZ_ = initZ;
}
Vector3D :: ~Vector3D()
{
}
double Vector3D :: getX()
StkFloat Vector3D :: getX()
{
return myX;
return myX_;
}
double Vector3D :: getY()
StkFloat Vector3D :: getY()
{
return myY;
return myY_;
}
double Vector3D :: getZ()
StkFloat Vector3D :: getZ()
{
return myZ;
return myZ_;
}
double Vector3D :: getLength()
StkFloat Vector3D :: getLength()
{
double temp;
temp = myX * myX;
temp += myY * myY;
temp += myZ * myZ;
StkFloat temp;
temp = myX_ * myX_;
temp += myY_ * myY_;
temp += myZ_ * myZ_;
temp = sqrt(temp);
return temp;
}
void Vector3D :: setXYZ(double anX, double aY, double aZ)
void Vector3D :: setXYZ(StkFloat x, StkFloat y, StkFloat z)
{
myX = anX;
myY = aY;
myZ = aZ;
myX_ = z;
myY_ = y;
myZ_ = z;
};
void Vector3D :: setX(double aval)
void Vector3D :: setX(StkFloat x)
{
myX = aval;
myX_ = x;
}
void Vector3D :: setY(double aval)
void Vector3D :: setY(StkFloat y)
{
myY = aval;
myY_ = y;
}
void Vector3D :: setZ(double aval)
void Vector3D :: setZ(StkFloat z)
{
myZ = aval;
myZ_ = z;
}

View File

@@ -21,7 +21,7 @@
- Vibrato Gain = 1
- Loudness (Spectral Tilt) = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -34,25 +34,18 @@
VoicForm :: VoicForm() : Instrmnt()
{
// Concatenate the STK rawwave path to the rawwave file
voiced = new SingWave( (Stk::rawwavePath() + "impuls20.raw").c_str(), TRUE );
voiced->setGainRate( 0.001 );
voiced->setGainTarget( 0.0 );
voiced_ = new SingWave( (Stk::rawwavePath() + "impuls20.raw").c_str(), true );
voiced_->setGainRate( 0.001 );
voiced_->setGainTarget( 0.0 );
noise = new Noise;
for ( int i=0; i<4; i++ ) {
filters[i] = new FormSwep;
filters[i]->setSweepRate( 0.001 );
}
for ( int i=0; i<4; i++ )
filters_[i].setSweepRate( 0.001 );
onezero = new OneZero;
onezero->setZero( -0.9 );
onepole = new OnePole;
onepole->setPole( 0.9 );
onezero_.setZero( -0.9 );
onepole_.setPole( 0.9 );
noiseEnv = new Envelope;
noiseEnv->setRate( 0.001 );
noiseEnv->setTarget( 0.0 );
noiseEnv_.setRate( 0.001 );
noiseEnv_.setTarget( 0.0 );
this->setPhoneme( "eee" );
this->clear();
@@ -60,34 +53,28 @@ VoicForm :: VoicForm() : Instrmnt()
VoicForm :: ~VoicForm()
{
delete voiced;
delete noise;
delete onezero;
delete onepole;
delete noiseEnv;
for ( int i=0; i<4; i++ ) {
delete filters[i];
}
delete voiced_;
}
void VoicForm :: clear()
{
onezero->clear();
onepole->clear();
onezero_.clear();
onepole_.clear();
for ( int i=0; i<4; i++ ) {
filters[i]->clear();
filters_[i].clear();
}
}
void VoicForm :: setFrequency(MY_FLOAT frequency)
void VoicForm :: setFrequency(StkFloat frequency)
{
MY_FLOAT freakency = frequency;
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
std::cerr << "VoicForm: setFrequency parameter is less than or equal to zero!" << std::endl;
errorString_ << "VoicForm::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
}
voiced->setFrequency( freakency );
voiced_->setFrequency( freakency );
}
bool VoicForm :: setPhoneme(const char *phoneme )
@@ -97,102 +84,118 @@ bool VoicForm :: setPhoneme(const char *phoneme )
while( i < 32 && !found ) {
if ( !strcmp( Phonemes::name(i), phoneme ) ) {
found = true;
filters[0]->setTargets( Phonemes::formantFrequency(i, 0), Phonemes::formantRadius(i, 0), pow(10.0, Phonemes::formantGain(i, 0 ) / 20.0) );
filters[1]->setTargets( Phonemes::formantFrequency(i, 1), Phonemes::formantRadius(i, 1), pow(10.0, Phonemes::formantGain(i, 1 ) / 20.0) );
filters[2]->setTargets( Phonemes::formantFrequency(i, 2), Phonemes::formantRadius(i, 2), pow(10.0, Phonemes::formantGain(i, 2 ) / 20.0) );
filters[3]->setTargets( Phonemes::formantFrequency(i, 3), Phonemes::formantRadius(i, 3), pow(10.0, Phonemes::formantGain(i, 3 ) / 20.0) );
setVoiced( Phonemes::voiceGain( i ) );
setUnVoiced( Phonemes::noiseGain( i ) );
filters_[0].setTargets( Phonemes::formantFrequency(i, 0), Phonemes::formantRadius(i, 0), pow(10.0, Phonemes::formantGain(i, 0 ) / 20.0) );
filters_[1].setTargets( Phonemes::formantFrequency(i, 1), Phonemes::formantRadius(i, 1), pow(10.0, Phonemes::formantGain(i, 1 ) / 20.0) );
filters_[2].setTargets( Phonemes::formantFrequency(i, 2), Phonemes::formantRadius(i, 2), pow(10.0, Phonemes::formantGain(i, 2 ) / 20.0) );
filters_[3].setTargets( Phonemes::formantFrequency(i, 3), Phonemes::formantRadius(i, 3), pow(10.0, Phonemes::formantGain(i, 3 ) / 20.0) );
this->setVoiced( Phonemes::voiceGain( i ) );
this->setUnVoiced( Phonemes::noiseGain( i ) );
#if defined(_STK_DEBUG_)
cout << "VoicForm: found formant " << phoneme << " (number " << i << ")" << std::endl;
errorString_ << "VoicForm::setPhoneme: found formant " << phoneme << " (number " << i << ").";
handleError( StkError::DEBUG_WARNING );
#endif
}
i++;
}
if ( !found )
std::cerr << "VoicForm: phoneme " << phoneme << " not found!" << std::endl;
if ( !found ) {
errorString_ << "VoicForm::setPhoneme: phoneme " << phoneme << " not found!";
handleError( StkError::WARNING );
}
return found;
}
void VoicForm :: setVoiced(MY_FLOAT vGain)
void VoicForm :: setVoiced(StkFloat vGain)
{
voiced->setGainTarget(vGain);
voiced_->setGainTarget(vGain);
}
void VoicForm :: setUnVoiced(MY_FLOAT nGain)
void VoicForm :: setUnVoiced(StkFloat nGain)
{
noiseEnv->setTarget(nGain);
noiseEnv_.setTarget(nGain);
}
void VoicForm :: setFilterSweepRate(int whichOne, MY_FLOAT rate)
void VoicForm :: setFilterSweepRate(unsigned int whichOne, StkFloat rate)
{
if ( whichOne < 0 || whichOne > 3 ) {
std::cerr << "VoicForm: setFilterSweepRate filter argument outside range 0-3!" << std::endl;
errorString_ << "VoicForm::setFilterSweepRate: filter select argument outside range 0-3!";
handleError( StkError::WARNING );
return;
}
filters[whichOne]->setSweepRate(rate);
filters_[whichOne].setSweepRate(rate);
}
void VoicForm :: setPitchSweepRate(MY_FLOAT rate)
void VoicForm :: setPitchSweepRate(StkFloat rate)
{
voiced->setSweepRate(rate);
voiced_->setSweepRate(rate);
}
void VoicForm :: speak()
{
voiced->noteOn();
voiced_->noteOn();
}
void VoicForm :: quiet()
{
voiced->noteOff();
noiseEnv->setTarget( 0.0 );
voiced_->noteOff();
noiseEnv_.setTarget( 0.0 );
}
void VoicForm :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void VoicForm :: noteOn(StkFloat frequency, StkFloat amplitude)
{
setFrequency(frequency);
voiced->setGainTarget(amplitude);
onepole->setPole( 0.97 - (amplitude * 0.2) );
this->setFrequency( frequency );
voiced_->setGainTarget( amplitude );
onepole_.setPole( 0.97 - (amplitude * 0.2) );
}
void VoicForm :: noteOff(MY_FLOAT amplitude)
void VoicForm :: noteOff(StkFloat amplitude)
{
this->quiet();
}
MY_FLOAT VoicForm :: tick()
StkFloat VoicForm :: tick()
{
MY_FLOAT temp;
temp = onepole->tick( onezero->tick( voiced->tick() ) );
temp += noiseEnv->tick() * noise->tick();
lastOutput = filters[0]->tick(temp);
lastOutput += filters[1]->tick(temp);
lastOutput += filters[2]->tick(temp);
lastOutput += filters[3]->tick(temp);
StkFloat temp;
temp = onepole_.tick( onezero_.tick( voiced_->tick() ) );
temp += noiseEnv_.tick() * noise_.tick();
lastOutput_ = filters_[0].tick(temp);
lastOutput_ += filters_[1].tick(temp);
lastOutput_ += filters_[2].tick(temp);
lastOutput_ += filters_[3].tick(temp);
/*
temp += noiseEnv->tick() * noise->tick();
lastOutput = filters[0]->tick(temp);
lastOutput = filters[1]->tick(lastOutput);
lastOutput = filters[2]->tick(lastOutput);
lastOutput = filters[3]->tick(lastOutput);
temp += noiseEnv_.tick() * noise_.tick();
lastOutput_ = filters_[0].tick(temp);
lastOutput_ = filters_[1].tick(lastOutput_);
lastOutput_ = filters_[2].tick(lastOutput_);
lastOutput_ = filters_[3].tick(lastOutput_);
*/
return lastOutput;
return lastOutput_;
}
StkFloat *VoicForm :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& VoicForm :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void VoicForm :: controlChange(int number, MY_FLOAT value)
void VoicForm :: controlChange(int number, StkFloat value)
{
MY_FLOAT norm = value * ONE_OVER_128;
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "VoicForm: Control value less than zero!" << std::endl;
errorString_ << "VoicForm::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "VoicForm: Control value greater than 128.0!" << std::endl;
errorString_ << "VoicForm::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_Breath_) { // 2
@@ -200,7 +203,7 @@ void VoicForm :: controlChange(int number, MY_FLOAT value)
this->setUnVoiced( 0.01 * norm );
}
else if (number == __SK_FootControl_) { // 4
MY_FLOAT temp = 0.0;
StkFloat temp = 0.0;
unsigned int i = (int) value;
if (i < 32) {
temp = 0.9;
@@ -221,25 +224,28 @@ void VoicForm :: controlChange(int number, MY_FLOAT value)
i = 0;
temp = 1.4;
}
filters[0]->setTargets( temp * Phonemes::formantFrequency(i, 0), Phonemes::formantRadius(i, 0), pow(10.0, Phonemes::formantGain(i, 0 ) / 20.0) );
filters[1]->setTargets( temp * Phonemes::formantFrequency(i, 1), Phonemes::formantRadius(i, 1), pow(10.0, Phonemes::formantGain(i, 1 ) / 20.0) );
filters[2]->setTargets( temp * Phonemes::formantFrequency(i, 2), Phonemes::formantRadius(i, 2), pow(10.0, Phonemes::formantGain(i, 2 ) / 20.0) );
filters[3]->setTargets( temp * Phonemes::formantFrequency(i, 3), Phonemes::formantRadius(i, 3), pow(10.0, Phonemes::formantGain(i, 3 ) / 20.0) );
setVoiced( Phonemes::voiceGain( i ) );
setUnVoiced( Phonemes::noiseGain( i ) );
filters_[0].setTargets( temp * Phonemes::formantFrequency(i, 0), Phonemes::formantRadius(i, 0), pow(10.0, Phonemes::formantGain(i, 0 ) / 20.0) );
filters_[1].setTargets( temp * Phonemes::formantFrequency(i, 1), Phonemes::formantRadius(i, 1), pow(10.0, Phonemes::formantGain(i, 1 ) / 20.0) );
filters_[2].setTargets( temp * Phonemes::formantFrequency(i, 2), Phonemes::formantRadius(i, 2), pow(10.0, Phonemes::formantGain(i, 2 ) / 20.0) );
filters_[3].setTargets( temp * Phonemes::formantFrequency(i, 3), Phonemes::formantRadius(i, 3), pow(10.0, Phonemes::formantGain(i, 3 ) / 20.0) );
this->setVoiced( Phonemes::voiceGain( i ) );
this->setUnVoiced( Phonemes::noiseGain( i ) );
}
else if (number == __SK_ModFrequency_) // 11
voiced->setVibratoRate( norm * 12.0); // 0 to 12 Hz
voiced_->setVibratoRate( norm * 12.0); // 0 to 12 Hz
else if (number == __SK_ModWheel_) // 1
voiced->setVibratoGain( norm * 0.2);
voiced_->setVibratoGain( norm * 0.2);
else if (number == __SK_AfterTouch_Cont_) { // 128
setVoiced( norm );
onepole->setPole( 0.97 - ( norm * 0.2) );
this->setVoiced( norm );
onepole_.setPole( 0.97 - ( norm * 0.2) );
}
else
std::cerr << "VoicForm: Undefined Control Number (" << number << ")!!" << std::endl;
else {
errorString_ << "VoicForm::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "VoicForm: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "VoicForm::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -25,7 +25,7 @@
an ensemble. Alternately, control changes can
be sent to all voices on a given channel.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -33,183 +33,167 @@
#include <stdlib.h>
#include <math.h>
Voicer :: Voicer( int maxInstruments, MY_FLOAT decayTime )
Voicer :: Voicer( StkFloat decayTime )
{
nVoices = 0;
maxVoices = maxInstruments;
voices = (Voice *) new Voice[maxVoices];
tags = 23456;
muteTime = (int) ( decayTime * Stk::sampleRate() );
tags_ = 23456;
muteTime_ = (int) ( decayTime * Stk::sampleRate() );
}
Voicer :: ~Voicer()
{
delete [] voices;
}
void Voicer :: addInstrument( Instrmnt *instrument, int channel )
{
//voices = (Voice *) realloc( (void *) voices, nVoices+1 * sizeof( Voice ) );
if ( nVoices == maxVoices ) {
std::cerr << "Voicer: Maximum number of voices already added!!" << std::endl;
return;
}
voices[nVoices].instrument = instrument;
voices[nVoices].tag = 0;
voices[nVoices].channel = channel;
voices[nVoices].noteNumber = -1;
voices[nVoices].frequency = 0.0;
voices[nVoices].sounding = 0;
nVoices++;
Voicer::Voice voice;
voice.instrument = instrument;
voice.channel = channel;
voice.noteNumber = -1;
voices_.push_back( voice );
}
void Voicer :: removeInstrument( Instrmnt *instrument )
{
bool found = false;
for ( int i=0; i<nVoices; i++ ) {
if ( voices[i].instrument == instrument ) found = true;
if ( found && i+1 < nVoices ) {
voices[i].instrument = voices[i+1].instrument;
voices[i].tag = voices[i+1].tag;
voices[i].noteNumber = voices[i+1].noteNumber;
voices[i].frequency = voices[i+1].frequency;
voices[i].sounding = voices[i+1].sounding;
voices[i].channel = voices[i+1].channel;
}
std::vector< Voicer::Voice>::iterator i;
for ( i=voices_.begin(); i!=voices_.end(); ++i ) {
if ( (*i).instrument != instrument ) continue;
voices_.erase( i );
found = true;
break;
}
if ( found )
nVoices--;
//voices = (Voice *) realloc( voices, --nVoices * sizeof( Voice ) );
if ( !found ) {
errorString_ << "Voicer::removeInstrument: instrument pointer not found in current voices!";
handleError( StkError::WARNING );
}
}
long Voicer :: noteOn(MY_FLOAT noteNumber, MY_FLOAT amplitude, int channel )
long Voicer :: noteOn(StkFloat noteNumber, StkFloat amplitude, int channel )
{
int i;
MY_FLOAT frequency = (MY_FLOAT) 220.0 * pow( 2.0, (noteNumber - 57.0) / 12.0 );
for ( i=0; i<nVoices; i++ ) {
if (voices[i].noteNumber < 0 && voices[i].channel == channel) {
voices[i].tag = tags++;
voices[i].channel = channel;
voices[i].noteNumber = noteNumber;
voices[i].frequency = frequency;
voices[i].instrument->noteOn( frequency, amplitude * ONE_OVER_128 );
voices[i].sounding = 1;
return voices[i].tag;
unsigned int i;
StkFloat frequency = (StkFloat) 220.0 * pow( 2.0, (noteNumber - 57.0) / 12.0 );
for ( i=0; i<voices_.size(); i++ ) {
if (voices_[i].noteNumber < 0 && voices_[i].channel == channel) {
voices_[i].tag = tags_++;
voices_[i].channel = channel;
voices_[i].noteNumber = noteNumber;
voices_[i].frequency = frequency;
voices_[i].instrument->noteOn( frequency, amplitude * ONE_OVER_128 );
voices_[i].sounding = 1;
return voices_[i].tag;
}
}
// All voices are sounding, so interrupt the oldest voice.
int voice = -1;
for ( i=0; i<nVoices; i++ ) {
if ( voices[i].channel == channel ) {
for ( i=0; i<voices_.size(); i++ ) {
if ( voices_[i].channel == channel ) {
if ( voice == -1 ) voice = i;
else if ( voices[i].tag < voices[voice].tag ) voice = i;
else if ( voices_[i].tag < voices_[voice].tag ) voice = (int) i;
}
}
if ( voice >= 0 ) {
voices[voice].tag = tags++;
voices[voice].channel = channel;
voices[voice].noteNumber = noteNumber;
voices[voice].frequency = frequency;
voices[voice].instrument->noteOn( frequency, amplitude * ONE_OVER_128 );
voices[voice].sounding = 1;
return voices[voice].tag;
voices_[voice].tag = tags_++;
voices_[voice].channel = channel;
voices_[voice].noteNumber = noteNumber;
voices_[voice].frequency = frequency;
voices_[voice].instrument->noteOn( frequency, amplitude * ONE_OVER_128 );
voices_[voice].sounding = 1;
return voices_[voice].tag;
}
return -1;
}
void Voicer :: noteOff( MY_FLOAT noteNumber, MY_FLOAT amplitude, int channel )
void Voicer :: noteOff( StkFloat noteNumber, StkFloat amplitude, int channel )
{
for ( int i=0; i<nVoices; i++ ) {
if ( voices[i].noteNumber == noteNumber && voices[i].channel == channel ) {
voices[i].instrument->noteOff( amplitude * ONE_OVER_128 );
voices[i].sounding = -muteTime;
for ( unsigned int i=0; i<voices_.size(); i++ ) {
if ( voices_[i].noteNumber == noteNumber && voices_[i].channel == channel ) {
voices_[i].instrument->noteOff( amplitude * ONE_OVER_128 );
voices_[i].sounding = -muteTime_;
}
}
}
void Voicer :: noteOff( long tag, MY_FLOAT amplitude )
void Voicer :: noteOff( long tag, StkFloat amplitude )
{
for ( int i=0; i<nVoices; i++ ) {
if ( voices[i].tag == tag ) {
voices[i].instrument->noteOff( amplitude * ONE_OVER_128 );
voices[i].sounding = -muteTime;
for ( unsigned int i=0; i<voices_.size(); i++ ) {
if ( voices_[i].tag == tag ) {
voices_[i].instrument->noteOff( amplitude * ONE_OVER_128 );
voices_[i].sounding = -muteTime_;
break;
}
}
}
void Voicer :: setFrequency( MY_FLOAT noteNumber, int channel )
void Voicer :: setFrequency( StkFloat noteNumber, int channel )
{
MY_FLOAT frequency = (MY_FLOAT) 220.0 * pow( 2.0, (noteNumber - 57.0) / 12.0 );
for ( int i=0; i<nVoices; i++ ) {
if ( voices[i].channel == channel ) {
voices[i].noteNumber = noteNumber;
voices[i].frequency = frequency;
voices[i].instrument->setFrequency( frequency );
StkFloat frequency = (StkFloat) 220.0 * pow( 2.0, (noteNumber - 57.0) / 12.0 );
for ( unsigned int i=0; i<voices_.size(); i++ ) {
if ( voices_[i].channel == channel ) {
voices_[i].noteNumber = noteNumber;
voices_[i].frequency = frequency;
voices_[i].instrument->setFrequency( frequency );
}
}
}
void Voicer :: setFrequency( long tag, MY_FLOAT noteNumber )
void Voicer :: setFrequency( long tag, StkFloat noteNumber )
{
MY_FLOAT frequency = (MY_FLOAT) 220.0 * pow( 2.0, (noteNumber - 57.0) / 12.0 );
for ( int i=0; i<nVoices; i++ ) {
if ( voices[i].tag == tag ) {
voices[i].noteNumber = noteNumber;
voices[i].frequency = frequency;
voices[i].instrument->setFrequency( frequency );
StkFloat frequency = (StkFloat) 220.0 * pow( 2.0, (noteNumber - 57.0) / 12.0 );
for ( unsigned int i=0; i<voices_.size(); i++ ) {
if ( voices_[i].tag == tag ) {
voices_[i].noteNumber = noteNumber;
voices_[i].frequency = frequency;
voices_[i].instrument->setFrequency( frequency );
break;
}
}
}
void Voicer :: pitchBend( MY_FLOAT value, int channel )
void Voicer :: pitchBend( StkFloat value, int channel )
{
MY_FLOAT pitchScaler;
StkFloat pitchScaler;
if ( value < 64.0 )
pitchScaler = pow(0.5, (64.0-value)/64.0);
else
pitchScaler = pow(2.0, (value-64.0)/64.0);
for ( int i=0; i<nVoices; i++ ) {
if ( voices[i].channel == channel )
voices[i].instrument->setFrequency( (MY_FLOAT) (voices[i].frequency * pitchScaler) );
for ( unsigned int i=0; i<voices_.size(); i++ ) {
if ( voices_[i].channel == channel )
voices_[i].instrument->setFrequency( (StkFloat) (voices_[i].frequency * pitchScaler) );
}
}
void Voicer :: pitchBend( long tag, MY_FLOAT value )
void Voicer :: pitchBend( long tag, StkFloat value )
{
MY_FLOAT pitchScaler;
StkFloat pitchScaler;
if ( value < 64.0 )
pitchScaler = pow(0.5, (64.0-value)/64.0);
else
pitchScaler = pow(2.0, (value-64.0)/64.0);
for ( int i=0; i<nVoices; i++ ) {
if ( voices[i].tag == tag ) {
voices[i].instrument->setFrequency( (MY_FLOAT) (voices[i].frequency * pitchScaler) );
for ( unsigned int i=0; i<voices_.size(); i++ ) {
if ( voices_[i].tag == tag ) {
voices_[i].instrument->setFrequency( (StkFloat) (voices_[i].frequency * pitchScaler) );
break;
}
}
}
void Voicer :: controlChange( int number, MY_FLOAT value, int channel )
void Voicer :: controlChange( int number, StkFloat value, int channel )
{
for ( int i=0; i<nVoices; i++ ) {
if ( voices[i].channel == channel )
voices[i].instrument->controlChange( number, value );
for ( unsigned int i=0; i<voices_.size(); i++ ) {
if ( voices_[i].channel == channel )
voices_[i].instrument->controlChange( number, value );
}
}
void Voicer :: controlChange( long tag, int number, MY_FLOAT value )
void Voicer :: controlChange( long tag, int number, StkFloat value )
{
for ( int i=0; i<nVoices; i++ ) {
if ( voices[i].tag == tag ) {
voices[i].instrument->controlChange( number, value );
for ( unsigned int i=0; i<voices_.size(); i++ ) {
if ( voices_[i].tag == tag ) {
voices_[i].instrument->controlChange( number, value );
break;
}
}
@@ -217,31 +201,31 @@ void Voicer :: controlChange( long tag, int number, MY_FLOAT value )
void Voicer :: silence( void )
{
for ( int i=0; i<nVoices; i++ ) {
if ( voices[i].sounding > 0 )
voices[i].instrument->noteOff( 0.5 );
for ( unsigned int i=0; i<voices_.size(); i++ ) {
if ( voices_[i].sounding > 0 )
voices_[i].instrument->noteOff( 0.5 );
}
}
MY_FLOAT Voicer :: tick()
StkFloat Voicer :: tick()
{
lastOutput = lastOutputLeft = lastOutputRight = 0.0;
for ( int i=0; i<nVoices; i++ ) {
if ( voices[i].sounding != 0 ) {
lastOutput += voices[i].instrument->tick();
lastOutputLeft += voices[i].instrument->lastOutLeft();
lastOutputRight += voices[i].instrument->lastOutRight();
lastOutput_ = lastOutputLeft_ = lastOutputRight_ = 0.0;
for ( unsigned int i=0; i<voices_.size(); i++ ) {
if ( voices_[i].sounding != 0 ) {
lastOutput_ += voices_[i].instrument->tick();
lastOutputLeft_ += voices_[i].instrument->lastOutLeft();
lastOutputRight_ += voices_[i].instrument->lastOutRight();
}
if ( voices[i].sounding < 0 ) {
voices[i].sounding++;
if ( voices[i].sounding == 0 )
voices[i].noteNumber = -1;
if ( voices_[i].sounding < 0 ) {
voices_[i].sounding++;
if ( voices_[i].sounding == 0 )
voices_[i].noteNumber = -1;
}
}
return lastOutput / nVoices;
return lastOutput_ / voices_.size();
}
MY_FLOAT *Voicer :: tick(MY_FLOAT *vector, unsigned int vectorSize)
StkFloat *Voicer :: tick(StkFloat *vector, unsigned int vectorSize)
{
for (unsigned int i=0; i<vectorSize; i++)
vector[i] = tick();
@@ -249,18 +233,46 @@ MY_FLOAT *Voicer :: tick(MY_FLOAT *vector, unsigned int vectorSize)
return vector;
}
MY_FLOAT Voicer :: lastOut() const
StkFrames& Voicer :: tick( StkFrames& frames, unsigned int channel )
{
return lastOutput;
if ( channel == 0 || frames.channels() < channel ) {
errorString_ << "Voicer::tick(): channel argument (" << channel << ") is zero or > channels in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( frames.channels() == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[i] = tick();
}
else if ( frames.interleaved() ) {
unsigned int hop = frames.channels();
unsigned int index = channel - 1;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
frames[index] = tick();
index += hop;
}
}
else {
unsigned int iStart = (channel - 1) * frames.frames();
for ( unsigned int i=0; i<frames.frames(); i++ )
frames[iStart + i] = tick();
}
return frames;
}
MY_FLOAT Voicer :: lastOutLeft() const
StkFloat Voicer :: lastOut() const
{
return lastOutputLeft;
return lastOutput_;
}
MY_FLOAT Voicer :: lastOutRight() const
StkFloat Voicer :: lastOutLeft() const
{
return lastOutputRight;
return lastOutputLeft_;
}
StkFloat Voicer :: lastOutRight() const
{
return lastOutputRight_;
}

View File

@@ -14,20 +14,19 @@
For single-channel data, these methods return
equivalent values.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "WaveLoop.h"
#include <math.h>
WaveLoop :: WaveLoop( const char *fileName, bool raw )
: WvIn( fileName, raw ), phaseOffset(0.0)
WaveLoop :: WaveLoop( std::string fileName, bool raw )
: WvIn( fileName, raw ), phaseOffset_(0.0)
{
// If at end of file, redo extra sample frame for looping.
if (chunkPointer+bufferSize == fileSize) {
for (unsigned int j=0; j<channels; j++)
data[bufferSize*channels+j] = data[j];
if (chunkPointer_+bufferSize_ == fileSize_) {
for (unsigned int j=0; j<channels_; j++)
data_[bufferSize_*channels_+j] = data_[j];
}
}
@@ -40,96 +39,105 @@ void WaveLoop :: readData( unsigned long index )
WvIn::readData( index );
// If at end of file, redo extra sample frame for looping.
if (chunkPointer+bufferSize == fileSize) {
for (unsigned int j=0; j<channels; j++)
data[bufferSize*channels+j] = data[j];
if (chunkPointer_+bufferSize_ == fileSize_) {
for (unsigned int j=0; j<channels_; j++)
data_[bufferSize_*channels_+j] = data_[j];
}
}
void WaveLoop :: setFrequency(MY_FLOAT aFrequency)
void WaveLoop :: setFrequency(StkFloat frequency)
{
// This is a looping frequency.
rate = fileSize * aFrequency / sampleRate();
rate_ = fileSize_ * frequency / Stk::sampleRate();
}
void WaveLoop :: addTime(MY_FLOAT aTime)
void WaveLoop :: addTime(StkFloat time)
{
// Add an absolute time in samples
time += aTime;
time_ += time;
while (time < 0.0)
time += fileSize;
while (time >= fileSize)
time -= fileSize;
while (time_ < 0.0)
time_ += fileSize_;
while (time_ >= fileSize_)
time_ -= fileSize_;
}
void WaveLoop :: addPhase(MY_FLOAT anAngle)
void WaveLoop :: addPhase(StkFloat angle)
{
// Add a time in cycles (one cycle = fileSize).
time += fileSize * anAngle;
time_ += fileSize_ * angle;
while (time < 0.0)
time += fileSize;
while (time >= fileSize)
time -= fileSize;
while (time_ < 0.0)
time_ += fileSize_;
while (time_ >= fileSize_)
time_ -= fileSize_;
}
void WaveLoop :: addPhaseOffset(MY_FLOAT anAngle)
void WaveLoop :: addPhaseOffset(StkFloat angle)
{
// Add a phase offset in cycles, where 1.0 = fileSize.
phaseOffset = fileSize * anAngle;
phaseOffset_ = fileSize_ * angle;
}
const MY_FLOAT *WaveLoop :: tickFrame(void)
const StkFloat *WaveLoop :: tickFrame(void)
{
register MY_FLOAT tyme, alpha;
register StkFloat tyme, alpha;
register unsigned long i, index;
// Check limits of time address ... if necessary, recalculate modulo fileSize.
while (time < 0.0)
time += fileSize;
while (time >= fileSize)
time -= fileSize;
while (time_ < 0.0)
time_ += fileSize_;
while (time_ >= fileSize_)
time_ -= fileSize_;
if (phaseOffset) {
tyme = time + phaseOffset;
if (phaseOffset_) {
tyme = time_ + phaseOffset_;
while (tyme < 0.0)
tyme += fileSize;
while (tyme >= fileSize)
tyme -= fileSize;
tyme += fileSize_;
while (tyme >= fileSize_)
tyme -= fileSize_;
}
else {
tyme = time;
tyme = time_;
}
if (chunking) {
if (chunking_) {
// Check the time address vs. our current buffer limits.
if ( (tyme < chunkPointer) || (tyme >= chunkPointer+bufferSize) )
if ( (tyme < chunkPointer_) || (tyme >= chunkPointer_+bufferSize_) )
this->readData((long) tyme);
// Adjust index for the current buffer.
tyme -= chunkPointer;
tyme -= chunkPointer_;
}
// Always do linear interpolation here ... integer part of time address.
index = (unsigned long) tyme;
// Fractional part of time address.
alpha = tyme - (MY_FLOAT) index;
index *= channels;
for (i=0; i<channels; i++) {
lastOutput[i] = data[index];
lastOutput[i] += (alpha * (data[index+channels] - lastOutput[i]));
alpha = tyme - (StkFloat) index;
index *= channels_;
for (i=0; i<channels_; i++) {
lastOutputs_[i] = data_[index];
lastOutputs_[i] += (alpha * (data_[index+channels_] - lastOutputs_[i]));
index++;
}
if (chunking) {
if (chunking_) {
// Scale outputs by gain.
for (i=0; i<channels; i++) lastOutput[i] *= gain;
for (i=0; i<channels_; i++) lastOutputs_[i] *= gain_;
}
// Increment time, which can be negative.
time += rate;
time_ += rate_;
return lastOutput;
return lastOutputs_;
}
StkFloat *WaveLoop :: tickFrame(StkFloat *frameVector, unsigned int frames)
{
return WvIn::tickFrame( frameVector, frames );
}
StkFrames& WaveLoop :: tickFrame( StkFrames& frames )
{
return WvIn::tickFrame( frames );
}

View File

@@ -12,190 +12,186 @@
- Blowing Frequency Modulation = 2
- Volume = 128
by Perry R. Cook 1996 - 2002.
by Perry R. Cook 1996 - 2004.
*/
/***************************************************/
#include "Whistle.h"
#include "SKINI.msg"
#include <stdlib.h>
#include <math.h>
#define CAN_RADIUS 100
#define PEA_RADIUS 30
#define BUMP_RADIUS 5
const int CAN_RADIUS = 100;
const int PEA_RADIUS = 30;
const int BUMP_RADIUS = 5;
#define NORM_CAN_LOSS 0.97
#define SLOW_CAN_LOSS 0.90
#define GRAVITY 20.0
// GRAVITY WAS 6.0
const StkFloat NORM_CAN_LOSS = 0.97;
const StkFloat SLOW_CAN_LOSS = 0.90;
const StkFloat GRAVITY = 20.0;
#define NORM_TICK_SIZE 0.004
#define SLOW_TICK_SIZE 0.0001
const StkFloat NORM_TICK_SIZE = 0.004;
const StkFloat SLOW_TICK_SIZE = 0.0001;
#define ENV_RATE 0.001
const StkFloat ENV_RATE = 0.001;
Whistle :: Whistle()
{
tempVector = new Vector3D(0,0,0);
can = new Sphere(CAN_RADIUS);
pea = new Sphere(PEA_RADIUS);
bumper = new Sphere(BUMP_RADIUS);
// Concatenate the STK rawwave path to the rawwave file
sine = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
sine->setFrequency(2800.0);
sine_ = new WaveLoop( ( Stk::rawwavePath() + "sinewave.raw").c_str(), true );
sine_->setFrequency( 2800.0 );
can->setPosition(0, 0, 0); // set can location
can->setVelocity(0, 0, 0); // and the velocity
can_.setRadius( CAN_RADIUS );
can_.setPosition(0, 0, 0); // set can location
can_.setVelocity(0, 0, 0); // and the velocity
onepole.setPole(0.95); // 0.99
onepole_.setPole(0.95); // 0.99
bumper->setPosition(0.0, CAN_RADIUS-BUMP_RADIUS, 0);
bumper->setPosition(0.0, CAN_RADIUS-BUMP_RADIUS, 0);
pea->setPosition(0, CAN_RADIUS/2, 0);
pea->setVelocity(35, 15, 0);
bumper_.setRadius( BUMP_RADIUS );
bumper_.setPosition(0.0, CAN_RADIUS-BUMP_RADIUS, 0);
bumper_.setPosition(0.0, CAN_RADIUS-BUMP_RADIUS, 0);
envelope.setRate(ENV_RATE);
envelope.keyOn();
pea_.setRadius( PEA_RADIUS );
pea_.setPosition(0, CAN_RADIUS/2, 0);
pea_.setVelocity(35, 15, 0);
fippleFreqMod = 0.5;
fippleGainMod = 0.5;
blowFreqMod = 0.25;
noiseGain = 0.125;
maxPressure = (MY_FLOAT) 0.0;
baseFrequency = 2000;
envelope_.setRate( ENV_RATE );
envelope_.keyOn();
tickSize = NORM_TICK_SIZE;
canLoss = NORM_CAN_LOSS;
fippleFreqMod_ = 0.5;
fippleGainMod_ = 0.5;
blowFreqMod_ = 0.25;
noiseGain_ = 0.125;
baseFrequency_ = 2000;
subSample = 1;
subSampCount = subSample;
tickSize_ = NORM_TICK_SIZE;
canLoss_ = NORM_CAN_LOSS;
subSample_ = 1;
subSampCount_ = subSample_;
}
Whistle :: ~Whistle()
{
delete tempVector;
delete can;
delete pea;
delete bumper;
delete sine;
delete sine_;
}
void Whistle :: clear()
{
}
void Whistle :: setFrequency(MY_FLOAT frequency)
void Whistle :: setFrequency(StkFloat frequency)
{
MY_FLOAT freakency = frequency * 4; // the whistle is a transposing instrument
StkFloat freakency = frequency * 4; // the whistle is a transposing instrument
if ( frequency <= 0.0 ) {
std::cerr << "Whistle: setFrequency parameter is less than or equal to zero!" << std::endl;
errorString_ << "Whistle::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
}
baseFrequency = freakency;
baseFrequency_ = freakency;
}
void Whistle :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate)
void Whistle :: startBlowing(StkFloat amplitude, StkFloat rate)
{
envelope.setRate(ENV_RATE);
envelope.setTarget(amplitude);
envelope_.setRate( ENV_RATE );
envelope_.setTarget( amplitude );
}
void Whistle :: stopBlowing(MY_FLOAT rate)
void Whistle :: stopBlowing(StkFloat rate)
{
envelope.setRate(rate);
envelope.keyOff();
envelope_.setRate( rate );
envelope_.keyOff();
}
void Whistle :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Whistle :: noteOn(StkFloat frequency, StkFloat amplitude)
{
setFrequency(frequency);
startBlowing(amplitude*2.0 ,amplitude * 0.2);
this->setFrequency( frequency );
this->startBlowing( amplitude*2.0 ,amplitude * 0.2 );
#if defined(_STK_DEBUG_)
std::cerr << "Whistle: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl;
errorString_ << "Whistle::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Whistle :: noteOff(MY_FLOAT amplitude)
void Whistle :: noteOff(StkFloat amplitude)
{
this->stopBlowing(amplitude * 0.02);
this->stopBlowing( amplitude * 0.02 );
#if defined(_STK_DEBUG_)
std::cerr << "Whistle: NoteOff amplitude = " << amplitude << std::endl;
errorString_ << "Whistle::NoteOff: amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
int frameCount = 0;
MY_FLOAT Whistle :: tick()
StkFloat Whistle :: tick()
{
MY_FLOAT soundMix, tempFreq;
double envOut = 0, temp, temp1, temp2, tempX, tempY;
StkFloat soundMix, tempFreq;
StkFloat envOut = 0, temp, temp1, temp2, tempX, tempY;
double phi, cosphi, sinphi;
double gain = 0.5, mod = 0.0;
if (--subSampCount <= 0) {
tempVectorP = pea->getPosition();
subSampCount = subSample;
temp = bumper->isInside(tempVectorP);
if ( --subSampCount_ <= 0 ) {
tempVectorP_ = pea_.getPosition();
subSampCount_ = subSample_;
temp = bumper_.isInside( tempVectorP_ );
#ifdef WHISTLE_ANIMATION
frameCount += 1;
if (frameCount >= (1470 / subSample)) {
if ( frameCount >= (1470 / subSample_) ) {
frameCount = 0;
printf("%f %f %f\n",tempVectorP->getX(),tempVectorP->getY(),envOut);
fflush(stdout);
}
#endif
envOut = envelope.tick();
envOut = envelope_.tick();
if (temp < (BUMP_RADIUS + PEA_RADIUS)) {
tempX = envOut * tickSize * 2000 * noise.tick();
tempY = -envOut * tickSize * 1000 * (1.0 + noise.tick());
pea->addVelocity(tempX,tempY,0);
pea->tick(tickSize);
tempX = envOut * tickSize_ * 2000 * noise_.tick();
tempY = -envOut * tickSize_ * 1000 * (1.0 + noise_.tick());
pea_.addVelocity( tempX, tempY, 0 );
pea_.tick( tickSize_ );
}
mod = exp(-temp * 0.01); // exp. distance falloff of fipple/pea effect
temp = onepole.tick(mod); // smooth it a little
gain = (1.0 - (fippleGainMod*0.5)) + (2.0 * fippleGainMod * temp);
gain *= gain; // squared distance/gain
mod = exp(-temp * 0.01); // exp. distance falloff of fipple/pea effect
temp = onepole_.tick(mod); // smooth it a little
gain = (1.0 - (fippleGainMod_*0.5)) + (2.0 * fippleGainMod_ * temp);
gain *= gain; // squared distance/gain
// tempFreq = 1.0 // Normalized Base Freq
// + (fippleFreqMod * 0.25) - (fippleFreqMod * temp) // fippleModulation
// - (blowFreqMod) + (blowFreqMod * envOut); // blowingModulation
// + (fippleFreqMod_ * 0.25) - (fippleFreqMod_ * temp) // fippleModulation
// - (blowFreqMod_) + (blowFreqMod_ * envOut); // blowingModulation
// short form of above
tempFreq = 1.0 + fippleFreqMod*(0.25-temp) + blowFreqMod*(envOut-1.0);
tempFreq *= baseFrequency;
tempFreq = 1.0 + fippleFreqMod_*(0.25-temp) + blowFreqMod_*(envOut-1.0);
tempFreq *= baseFrequency_;
sine->setFrequency(tempFreq);
sine_->setFrequency(tempFreq);
tempVectorP = pea->getPosition();
temp = can->isInside(tempVectorP);
tempVectorP_ = pea_.getPosition();
temp = can_.isInside(tempVectorP_);
temp = -temp; // We know (hope) it's inside, just how much??
if (temp < (PEA_RADIUS * 1.25)) {
pea->getVelocity(tempVector); // This is the can/pea collision
tempX = tempVectorP->getX(); // calculation. Could probably
tempY = tempVectorP->getY(); // simplify using tables, etc.
if (temp < (PEA_RADIUS * 1.25)) {
pea_.getVelocity( &tempVector_ ); // This is the can/pea collision
tempX = tempVectorP_->getX(); // calculation. Could probably
tempY = tempVectorP_->getY(); // simplify using tables, etc.
phi = -atan2(tempY,tempX);
cosphi = cos(phi);
sinphi = sin(phi);
temp1 = (cosphi*tempVector->getX()) - (sinphi*tempVector->getY());
temp2 = (sinphi*tempVector->getX()) + (cosphi*tempVector->getY());
temp1 = (cosphi*tempVector_.getX()) - (sinphi*tempVector_.getY());
temp2 = (sinphi*tempVector_.getX()) + (cosphi*tempVector_.getY());
temp1 = -temp1;
tempX = (cosphi*temp1) + (sinphi*temp2);
tempY = (-sinphi*temp1) + (cosphi*temp2);
pea->setVelocity(tempX, tempY, 0);
pea->tick(tickSize);
pea->setVelocity(tempX*canLoss, tempY*canLoss, 0);
pea->tick(tickSize);
pea_.setVelocity(tempX, tempY, 0);
pea_.tick(tickSize_);
pea_.setVelocity( tempX*canLoss_, tempY*canLoss_, 0 );
pea_.tick(tickSize_);
}
temp = tempVectorP->getLength();
if (temp > 0.01) {
tempX = tempVectorP->getX();
tempY = tempVectorP->getY();
phi = atan2(tempY,tempX);
temp = tempVectorP_->getLength();
if (temp > 0.01) {
tempX = tempVectorP_->getX();
tempY = tempVectorP_->getY();
phi = atan2( tempY, tempX );
phi += 0.3 * temp / CAN_RADIUS;
cosphi = cos(phi);
sinphi = sin(phi);
@@ -207,50 +203,64 @@ MY_FLOAT Whistle :: tick()
tempY = 0.0;
}
temp = (0.9 + 0.1*subSample*noise.tick()) * envOut * 0.6 * tickSize;
pea->addVelocity(temp * tempX,
(temp*tempY) - (GRAVITY*tickSize),0);
pea->tick(tickSize);
temp = (0.9 + 0.1*subSample_*noise_.tick()) * envOut * 0.6 * tickSize_;
pea_.addVelocity( temp * tempX, (temp*tempY) - (GRAVITY*tickSize_), 0 );
pea_.tick( tickSize_ );
// bumper->tick(0.0);
// bumper_.tick(0.0);
}
temp = envOut * envOut * gain / 2;
soundMix = temp * (sine->tick() + (noiseGain*noise.tick()));
lastOutput = 0.25 * soundMix; // should probably do one-zero filter here
soundMix = temp * ( sine_->tick() + ( noiseGain_*noise_.tick() ) );
lastOutput_ = 0.25 * soundMix; // should probably do one-zero filter here
return lastOutput;
return lastOutput_;
}
void Whistle :: controlChange(int number, MY_FLOAT value)
StkFloat *Whistle :: tick(StkFloat *vector, unsigned int vectorSize)
{
MY_FLOAT norm = value * ONE_OVER_128;
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Whistle :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}
void Whistle :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
std::cerr << "Whistle: Control value less than zero!" << std::endl;
errorString_ << "Whistle::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
std::cerr << "Whistle: Control value greater than 128.0!" << std::endl;
errorString_ << "Whistle::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_NoiseLevel_) // 4
noiseGain = 0.25 * norm;
noiseGain_ = 0.25 * norm;
else if (number == __SK_ModFrequency_) // 11
fippleFreqMod = norm;
fippleFreqMod_ = norm;
else if (number == __SK_ModWheel_) // 1
fippleGainMod = norm;
fippleGainMod_ = norm;
else if (number == __SK_AfterTouch_Cont_) // 128
envelope.setTarget( norm * 2.0 );
envelope_.setTarget( norm * 2.0 );
else if (number == __SK_Breath_) // 2
blowFreqMod = norm * 0.5;
blowFreqMod_ = norm * 0.5;
else if (number == __SK_Sustain_) // 64
if (value < 1.0) subSample = 1;
else
std::cerr << "Whistle: Undefined Control Number (" << number << ")!!" << std::endl;
if (value < 1.0) subSample_ = 1;
else {
errorString_ << "Whistle::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
std::cerr << "Whistle: controlChange number = " << number << ", value = " << value << std::endl;
errorString_ << "Whistle::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
@@ -36,76 +36,87 @@ Wurley :: Wurley()
: FM()
{
// Concatenate the STK rawwave path to the rawwave files
for ( int i=0; i<3; i++ )
waves[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), TRUE );
waves[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), TRUE );
for ( unsigned int i=0; i<3; i++ )
waves_[i] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
waves_[3] = new WaveLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true );
this->setRatio(0, 1.0);
this->setRatio(1, 4.0);
this->setRatio(2, -510.0);
this->setRatio(3, -510.0);
gains[0] = __FM_gains[99];
gains[1] = __FM_gains[82];
gains[2] = __FM_gains[92];
gains[3] = __FM_gains[68];
gains_[0] = fmGains_[99];
gains_[1] = fmGains_[82];
gains_[2] = fmGains_[92];
gains_[3] = fmGains_[68];
adsr[0]->setAllTimes( 0.001, 1.50, 0.0, 0.04);
adsr[1]->setAllTimes( 0.001, 1.50, 0.0, 0.04);
adsr[2]->setAllTimes( 0.001, 0.25, 0.0, 0.04);
adsr[3]->setAllTimes( 0.001, 0.15, 0.0, 0.04);
adsr_[0]->setAllTimes( 0.001, 1.50, 0.0, 0.04);
adsr_[1]->setAllTimes( 0.001, 1.50, 0.0, 0.04);
adsr_[2]->setAllTimes( 0.001, 0.25, 0.0, 0.04);
adsr_[3]->setAllTimes( 0.001, 0.15, 0.0, 0.04);
twozero->setGain( 2.0 );
vibrato->setFrequency( 8.0 );
twozero_.setGain( 2.0 );
vibrato_->setFrequency( 8.0 );
}
Wurley :: ~Wurley()
{
}
void Wurley :: setFrequency(MY_FLOAT frequency)
void Wurley :: setFrequency(StkFloat frequency)
{
baseFrequency = frequency;
waves[0]->setFrequency(baseFrequency * ratios[0]);
waves[1]->setFrequency(baseFrequency * ratios[1]);
waves[2]->setFrequency(ratios[2]); // Note here a 'fixed resonance'.
waves[3]->setFrequency(ratios[3]);
baseFrequency_ = frequency;
waves_[0]->setFrequency( baseFrequency_ * ratios_[0]);
waves_[1]->setFrequency( baseFrequency_ * ratios_[1]);
waves_[2]->setFrequency( ratios_[2] ); // Note here a 'fixed resonance'.
waves_[3]->setFrequency( ratios_[3] );
}
void Wurley :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude)
void Wurley :: noteOn(StkFloat frequency, StkFloat amplitude)
{
gains[0] = amplitude * __FM_gains[99];
gains[1] = amplitude * __FM_gains[82];
gains[2] = amplitude * __FM_gains[82];
gains[3] = amplitude * __FM_gains[68];
this->setFrequency(frequency);
gains_[0] = amplitude * fmGains_[99];
gains_[1] = amplitude * fmGains_[82];
gains_[2] = amplitude * fmGains_[82];
gains_[3] = amplitude * fmGains_[68];
this->setFrequency( frequency );
this->keyOn();
#if defined(_STK_DEBUG_)
cerr << "Wurley: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << endl;
errorString_ << "Wurley::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
MY_FLOAT Wurley :: tick()
StkFloat Wurley :: tick()
{
MY_FLOAT temp, temp2;
StkFloat temp, temp2;
temp = gains[1] * adsr[1]->tick() * waves[1]->tick();
temp = temp * control1;
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_[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();
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;
temp2 = vibrato_->tick() * modDepth_;
temp = temp * (1.0 + temp2);
lastOutput = temp * 0.5;
return lastOutput;
lastOutput_ = temp * 0.5;
return lastOutput_;
}
StkFloat *Wurley :: tick(StkFloat *vector, unsigned int vectorSize)
{
return Instrmnt::tick( vector, vectorSize );
}
StkFrames& Wurley :: tick( StkFrames& frames, unsigned int channel )
{
return Instrmnt::tick( frames, channel );
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@ static LONG findDrvPath (char *clsidstr,char *dllpath,int dllpathsize)
DWORD index;
OFSTRUCT ofs;
HFILE hfile;
BOOL found = FALSE;
BOOL found = false;
CharLowerBuff(clsidstr,strlen(clsidstr));
if ((cr = RegOpenKey(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {
@@ -44,7 +44,7 @@ static LONG findDrvPath (char *clsidstr,char *dllpath,int dllpathsize)
}
RegCloseKey(hksub);
}
found = TRUE; // break out
found = true; // break out
}
}
}
@@ -134,7 +134,7 @@ AsioDriverList::AsioDriverList ()
LPASIODRVSTRUCT pdl;
LONG cr;
DWORD index = 0;
BOOL fin = FALSE;
BOOL fin = false;
numdrv = 0;
lpdrvlist = 0;
@@ -144,7 +144,7 @@ AsioDriverList::AsioDriverList ()
if ((cr = RegEnumKey(hkEnum,index++,(LPTSTR)keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {
lpdrvlist = newDrvStruct (hkEnum,keyname,0,lpdrvlist);
}
else fin = TRUE;
else fin = true;
}
if (hkEnum) RegCloseKey(hkEnum);