mirror of
https://github.com/thestk/stk
synced 2026-01-18 23:21:53 +00:00
Version 4.2.0
This commit is contained in:
committed by
Stephen Sinclair
parent
cf06b7598b
commit
a6381b9d38
191
src/ADSR.cpp
191
src/ADSR.cpp
@@ -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
115
src/Asymp.cpp
Normal 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 );
|
||||
}
|
||||
394
src/BandedWG.cpp
394
src/BandedWG.cpp
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
131
src/BlowBotl.cpp
131
src/BlowBotl.cpp
@@ -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
|
||||
}
|
||||
|
||||
247
src/BlowHole.cpp
247
src/BlowHole.cpp
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
60
src/BowTable.cpp
Normal 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 );
|
||||
}
|
||||
183
src/Bowed.cpp
183
src/Bowed.cpp
@@ -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
|
||||
}
|
||||
|
||||
162
src/Brass.cpp
162
src/Brass.cpp
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
138
src/Clarinet.cpp
138
src/Clarinet.cpp
@@ -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
|
||||
}
|
||||
|
||||
179
src/Delay.cpp
179
src/Delay.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
127
src/DelayA.cpp
127
src/DelayA.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
118
src/DelayL.cpp
118
src/DelayL.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
127
src/Drummer.cpp
127
src/Drummer.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
72
src/Echo.cpp
72
src/Echo.cpp
@@ -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
99
src/Effect.cpp
Normal 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
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
176
src/FM.cpp
176
src/FM.cpp
@@ -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
|
||||
}
|
||||
|
||||
|
||||
179
src/FMVoices.cpp
179
src/FMVoices.cpp
@@ -26,7 +26,7 @@
|
||||
type who should worry about this (making
|
||||
money) worry away.
|
||||
|
||||
by Perry R. Cook and Gary P. Scavone, 1995 - 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
|
||||
}
|
||||
|
||||
261
src/Filter.cpp
261
src/Filter.cpp
@@ -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;
|
||||
}
|
||||
|
||||
201
src/Flute.cpp
201
src/Flute.cpp
@@ -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
|
||||
}
|
||||
|
||||
132
src/FormSwep.cpp
132
src/FormSwep.cpp
@@ -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
58
src/Function.cpp
Normal 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
57
src/Generator.cpp
Normal 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;
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
134
src/JCRev.cpp
134
src/JCRev.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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
49
src/JetTable.cpp
Normal 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 );
|
||||
}
|
||||
@@ -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@
|
||||
|
||||
153
src/Mandolin.cpp
153
src/Mandolin.cpp
@@ -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
|
||||
}
|
||||
|
||||
316
src/Mesh2D.cpp
316
src/Mesh2D.cpp
@@ -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
|
||||
}
|
||||
|
||||
702
src/Messager.cpp
702
src/Messager.cpp
@@ -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
359
src/MidiFileIn.cpp
Normal 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;
|
||||
}
|
||||
214
src/Modal.cpp
214
src/Modal.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
141
src/Moog.cpp
141
src/Moog.cpp
@@ -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
100
src/Mutex.cpp
Normal 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
|
||||
}
|
||||
101
src/NRev.cpp
101
src/NRev.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
114
src/PitShift.cpp
114
src/PitShift.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
127
src/PluckTwo.cpp
127
src/PluckTwo.cpp
@@ -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
|
||||
}
|
||||
|
||||
|
||||
112
src/Plucked.cpp
112
src/Plucked.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
127
src/Resonate.cpp
127
src/Resonate.cpp
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
1433
src/RtAudio.cpp
1433
src/RtAudio.cpp
File diff suppressed because it is too large
Load Diff
122
src/RtDuplex.cpp
122
src/RtDuplex.cpp
@@ -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;
|
||||
}
|
||||
|
||||
2844
src/RtMidi.cpp
2844
src/RtMidi.cpp
File diff suppressed because it is too large
Load Diff
@@ -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 );
|
||||
}
|
||||
|
||||
144
src/RtWvOut.cpp
144
src/RtWvOut.cpp
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
350
src/SKINI.cpp
350
src/SKINI.cpp
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
179
src/Saxofony.cpp
179
src/Saxofony.cpp
@@ -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
|
||||
|
||||
}
|
||||
|
||||
1368
src/Shakers.cpp
1368
src/Shakers.cpp
File diff suppressed because it is too large
Load Diff
105
src/Simple.cpp
105
src/Simple.cpp
@@ -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
|
||||
}
|
||||
|
||||
105
src/SingWave.cpp
105
src/SingWave.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
112
src/Sitar.cpp
112
src/Sitar.cpp
@@ -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
212
src/Skini.cpp
Normal 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;
|
||||
}
|
||||
109
src/Socket.cpp
109
src/Socket.cpp
@@ -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 )
|
||||
|
||||
@@ -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()));
|
||||
};
|
||||
|
||||
|
||||
216
src/StifKarp.cpp
216
src/StifKarp.cpp
@@ -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
|
||||
}
|
||||
|
||||
|
||||
107
src/Stk.cpp
107
src/Stk.cpp
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
281
src/TcpWvIn.cpp
281
src/TcpWvIn.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
236
src/TcpWvOut.cpp
236
src/TcpWvOut.cpp
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
127
src/Thread.cpp
127
src/Thread.cpp
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
186
src/VoicForm.cpp
186
src/VoicForm.cpp
@@ -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
|
||||
}
|
||||
|
||||
254
src/Voicer.cpp
254
src/Voicer.cpp
@@ -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_;
|
||||
}
|
||||
|
||||
|
||||
108
src/WaveLoop.cpp
108
src/WaveLoop.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
252
src/Whistle.cpp
252
src/Whistle.cpp
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
801
src/WvIn.cpp
801
src/WvIn.cpp
File diff suppressed because it is too large
Load Diff
700
src/WvOut.cpp
700
src/WvOut.cpp
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user