mirror of
https://github.com/thestk/stk
synced 2026-01-12 04:21:52 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffce5357c6 | ||
|
|
b39c0bb101 | ||
|
|
f25eb5c3d7 | ||
|
|
71e5c027fb | ||
|
|
43dcd5775a | ||
|
|
6e0d1955a8 | ||
|
|
2f09fcd019 | ||
|
|
81475b04c5 | ||
|
|
3f126af4e5 | ||
|
|
4b6500d3de | ||
|
|
868787a5f9 | ||
|
|
7c0ee03d60 | ||
|
|
ea749b71d2 |
173
ADSR.cpp
173
ADSR.cpp
@@ -1,173 +0,0 @@
|
||||
/*******************************************/
|
||||
/* ADSR Subclass of the Envelope Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This is the traditional ADSR (Attack */
|
||||
/* Decay, Sustain, Release) ADSR. */
|
||||
/* It responds to simple KeyOn and KeyOff */
|
||||
/* messages, keeping track of it's state. */
|
||||
/* There are two tick (update value) */
|
||||
/* methods, one returns the value, and */
|
||||
/* other returns the state (0 = A, 1 = D, */
|
||||
/* 2 = S, 3 = R) */
|
||||
/*******************************************/
|
||||
|
||||
#include "ADSR.h"
|
||||
|
||||
ADSR :: ADSR() : Envelope()
|
||||
{
|
||||
target = 0.0;
|
||||
value = 0.0;
|
||||
attackRate = 0.001;
|
||||
decayRate = 0.001;
|
||||
sustainLevel = 0.5;
|
||||
releaseRate = 0.01;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
ADSR :: ~ADSR()
|
||||
{
|
||||
/* Nothing to do here */
|
||||
}
|
||||
|
||||
void ADSR :: keyOn()
|
||||
{
|
||||
target = 1.0;
|
||||
rate = attackRate;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
void ADSR :: keyOff()
|
||||
{
|
||||
target = 0.0;
|
||||
rate = releaseRate;
|
||||
state = 3;
|
||||
}
|
||||
|
||||
void ADSR :: setAttackRate(MY_FLOAT aRate)
|
||||
{
|
||||
if (aRate < 0.0) {
|
||||
printf("negative rates not allowed!!, correcting\n");
|
||||
attackRate = -aRate;
|
||||
}
|
||||
else attackRate = aRate;
|
||||
attackRate = attackRate * RATE_NORM; /* SEE Object.h */
|
||||
}
|
||||
|
||||
void ADSR :: setDecayRate(MY_FLOAT aRate)
|
||||
{
|
||||
if (aRate < 0.0) {
|
||||
printf("negative rates not allowed!!, correcting\n");
|
||||
decayRate = -aRate;
|
||||
}
|
||||
else decayRate = aRate;
|
||||
decayRate = decayRate * RATE_NORM; /* SEE Object.h */
|
||||
}
|
||||
|
||||
void ADSR :: setSustainLevel(MY_FLOAT aLevel)
|
||||
{
|
||||
if (aLevel < 0.0 ) {
|
||||
printf("Sustain level out of range!!, correcting\n");
|
||||
sustainLevel = 0.0;
|
||||
}
|
||||
else sustainLevel = aLevel;
|
||||
}
|
||||
|
||||
void ADSR :: setReleaseRate(MY_FLOAT aRate)
|
||||
{
|
||||
if (aRate < 0.0) {
|
||||
printf("negative rates not allowed!!, correcting\n");
|
||||
releaseRate = -aRate;
|
||||
}
|
||||
else releaseRate = aRate;
|
||||
releaseRate = releaseRate * RATE_NORM; /* SEE Object.h */
|
||||
}
|
||||
|
||||
void ADSR :: setAll(MY_FLOAT attRate, MY_FLOAT decRate, MY_FLOAT susLevel, MY_FLOAT relRate)
|
||||
{
|
||||
this->setAttackRate(attRate);
|
||||
this->setDecayRate(decRate);
|
||||
this->setSustainLevel(susLevel);
|
||||
this->setReleaseRate(relRate);
|
||||
}
|
||||
|
||||
void ADSR :: setTarget(MY_FLOAT aTarget)
|
||||
{
|
||||
target = aTarget;
|
||||
if (value < target) {
|
||||
state = ATTACK;
|
||||
this->setSustainLevel(target);
|
||||
rate = attackRate;
|
||||
}
|
||||
if (value > target) {
|
||||
this->setSustainLevel(target);
|
||||
state = DECAY;
|
||||
rate = decayRate;
|
||||
}
|
||||
}
|
||||
|
||||
void ADSR :: setValue(MY_FLOAT aValue)
|
||||
{
|
||||
state = SUSTAIN;
|
||||
target = aValue;
|
||||
value = aValue;
|
||||
this->setSustainLevel(aValue);
|
||||
rate = 0.0;
|
||||
}
|
||||
|
||||
MY_FLOAT ADSR :: tick()
|
||||
{
|
||||
if (state==ATTACK) {
|
||||
value += rate;
|
||||
if (value >= target) {
|
||||
value = target;
|
||||
rate = decayRate;
|
||||
target = sustainLevel;
|
||||
state = DECAY;
|
||||
}
|
||||
}
|
||||
else if (state==DECAY) {
|
||||
value -= decayRate;
|
||||
if (value <= sustainLevel) {
|
||||
value = sustainLevel;
|
||||
rate = 0.0;
|
||||
state = SUSTAIN;
|
||||
}
|
||||
}
|
||||
else if (state==RELEASE) {
|
||||
value -= releaseRate;
|
||||
if (value <= 0.0) {
|
||||
value = 0.0;
|
||||
state = 4;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int ADSR :: informTick()
|
||||
{
|
||||
this->tick();
|
||||
return state;
|
||||
}
|
||||
|
||||
MY_FLOAT ADSR :: lastOut()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/************ Test Main ************************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
long i;
|
||||
ADSR test;
|
||||
|
||||
test.setAttackRate(0.15);
|
||||
test.keyOn();
|
||||
while(test.informTick()==ATTACK) printf("%lf\n",test.tick());
|
||||
test.setDecayRate(0.1);
|
||||
while (test.informTick()==DECAY) printf("%lf\n",test.lastOut());
|
||||
test.setReleaseRate(0.05);
|
||||
test.keyOff();
|
||||
while(test.informTick()==RELEASE) printf("%lf\n",test.lastOut());
|
||||
}
|
||||
*/
|
||||
43
ADSR.h
43
ADSR.h
@@ -1,43 +0,0 @@
|
||||
/*******************************************/
|
||||
/* ADSR Subclass of the Envelope Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This is the traditional ADSR (Attack */
|
||||
/* Decay, Sustain, Release) envelope. */
|
||||
/* It responds to simple KeyOn and KeyOff */
|
||||
/* messages, keeping track of it's state. */
|
||||
/* There are two tick (update value) */
|
||||
/* methods, one returns the value, and */
|
||||
/* other returns the state (0 = A, 1 = D, */
|
||||
/* 2 = S, 3 = R) */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__ADSR_h)
|
||||
#define __ADSR_h
|
||||
|
||||
#include "Envelope.h"
|
||||
|
||||
class ADSR : public Envelope
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT attackRate;
|
||||
MY_FLOAT decayRate;
|
||||
MY_FLOAT sustainLevel;
|
||||
MY_FLOAT releaseRate;
|
||||
public:
|
||||
ADSR();
|
||||
~ADSR();
|
||||
void keyOn();
|
||||
void keyOff();
|
||||
void setAttackRate(MY_FLOAT aRate);
|
||||
void setDecayRate(MY_FLOAT aRate);
|
||||
void setSustainLevel(MY_FLOAT aLevel);
|
||||
void setReleaseRate(MY_FLOAT aRate);
|
||||
void setAll(MY_FLOAT attRate, MY_FLOAT decRate, MY_FLOAT susLevel, MY_FLOAT relRate);
|
||||
void setTarget(MY_FLOAT aTarget);
|
||||
void setValue(MY_FLOAT aValue);
|
||||
MY_FLOAT tick();
|
||||
int informTick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
75
AgogoBel.cpp
75
AgogoBel.cpp
@@ -1,75 +0,0 @@
|
||||
/*******************************************/
|
||||
/* AgogoBell SubClass of Modal4 Instrument*/
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = stickHardness */
|
||||
/* CONTROL2 = strikePosition*/
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/*******************************************/
|
||||
|
||||
/* Modes measured from my Agogo Bell by FFT: */
|
||||
/* 360, 1470, 2401, 4600 */
|
||||
|
||||
#include "AgogoBel.h"
|
||||
|
||||
AgogoBel :: AgogoBel() : Modal4()
|
||||
{
|
||||
wave = new RawWave("rawwaves/britestk.raw");
|
||||
wave->normalize();
|
||||
wave->setRate(7.0); /* hardstick */
|
||||
this->setRatioAndReson(0, 1.00,0.999); /* Set our */
|
||||
this->setRatioAndReson(1, 4.08,0.999); /* resonances */
|
||||
this->setRatioAndReson(2,6.669,0.999); /* here */
|
||||
this->setRatioAndReson(3,-3725.0,0.999); /* (One fixed) */
|
||||
this->setFiltGain(0,0.07); /* And filter */
|
||||
this->setFiltGain(1,0.06); /* gains too */
|
||||
this->setFiltGain(2,0.04);
|
||||
this->setFiltGain(3,0.02);
|
||||
directGain = 0.3;
|
||||
}
|
||||
|
||||
AgogoBel :: ~AgogoBel()
|
||||
{
|
||||
delete wave;
|
||||
}
|
||||
|
||||
void AgogoBel :: setStickHardness(MY_FLOAT hardness)
|
||||
{
|
||||
stickHardness = hardness; /* To an approximation, */
|
||||
wave->setRate(3.0 + (8.0 * stickHardness)); /* hardness <-> center */
|
||||
masterGain = 1.0; /* freq and amplitude */
|
||||
}
|
||||
|
||||
void AgogoBel :: setStrikePosition(MY_FLOAT position)
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
temp2 = position * PI;
|
||||
strikePosition = position; /* Hack only first */
|
||||
temp = sin(0.7 * temp2); /* three modes, */
|
||||
this->setFiltGain(0,0.08 * temp); /* leave the other */
|
||||
temp = sin(0.1 + (5.0 * temp2)); /* fixed. Why? */
|
||||
this->setFiltGain(1,0.07 * temp); /* So it doesn't */
|
||||
temp = sin(0.2 + (7.0 * temp2)); /* sound like a */
|
||||
this->setFiltGain(2,0.04 * temp); /* sample! */
|
||||
}
|
||||
|
||||
void AgogoBel :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("AgogoBel : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == MIDI_control1)
|
||||
this->setStickHardness(value * NORM_7);
|
||||
else if (number == MIDI_control2)
|
||||
this->setStrikePosition(value * NORM_7);
|
||||
else if (number == MIDI_control3)
|
||||
vibr->setFreq((value * NORM_7 * 12.0));
|
||||
else if (number == MIDI_mod_wheel)
|
||||
vibrGain = (value * NORM_7);
|
||||
else if (number == MIDI_after_touch)
|
||||
this->strike(value * NORM_7);
|
||||
else {
|
||||
printf("AgogoBel : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
26
AgogoBel.h
26
AgogoBel.h
@@ -1,26 +0,0 @@
|
||||
/*******************************************/
|
||||
/* AgogoBell SubClass of Modal4 Instrument*/
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = stickHardness */
|
||||
/* CONTROL2 = strikePosition*/
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__AgogoBel_h)
|
||||
#define __AgogoBel_h
|
||||
|
||||
#include "Modal4.h"
|
||||
|
||||
class AgogoBel : public Modal4
|
||||
{
|
||||
public:
|
||||
AgogoBel();
|
||||
~AgogoBel();
|
||||
void setStickHardness(MY_FLOAT hardness);
|
||||
void setStrikePosition(MY_FLOAT position);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
39
AllPass1.cpp
39
AllPass1.cpp
@@ -1,39 +0,0 @@
|
||||
/*******************************************/
|
||||
/* 1st order allpass filter. */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* A special case of the one pole */
|
||||
/* one zero filter. */
|
||||
/*******************************************/
|
||||
|
||||
#include "AllPass1.h"
|
||||
|
||||
AllPass1 :: AllPass1()
|
||||
{
|
||||
inputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
|
||||
outputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
|
||||
this->clear();
|
||||
|
||||
}
|
||||
|
||||
AllPass1 :: ~AllPass1()
|
||||
{
|
||||
free(inputs);
|
||||
free(outputs);
|
||||
}
|
||||
|
||||
void AllPass1 :: clear()
|
||||
{
|
||||
outputs[0] = 0.0;
|
||||
inputs[0] = 0.0;
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
MY_FLOAT AllPass1 :: tick(MY_FLOAT sample)
|
||||
{
|
||||
outputs[0] = sample - inputs[0] + (0.99 * outputs[0]);
|
||||
inputs[0] = sample;
|
||||
lastOutput = outputs[0];
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
|
||||
24
AllPass1.h
24
AllPass1.h
@@ -1,24 +0,0 @@
|
||||
/*******************************************/
|
||||
/* 1st order allpass filter. */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* A special case of the one pole */
|
||||
/* one zero filter. */
|
||||
/*******************************************/
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
#if !defined(__AllPass1_h)
|
||||
#define __AllPass1_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class AllPass1 : Filter
|
||||
{
|
||||
public:
|
||||
AllPass1();
|
||||
~AllPass1();
|
||||
void clear();
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
71
BeeThree.cpp
71
BeeThree.cpp
@@ -1,71 +0,0 @@
|
||||
/******************************************/
|
||||
/* Hammond(OID) Organ Subclass */
|
||||
/* of Algorithm 8 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/******************************************/
|
||||
|
||||
#include "BeeThree.h"
|
||||
|
||||
BeeThree :: BeeThree() : FM4Alg8()
|
||||
{
|
||||
this->loadWaves("rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw");
|
||||
this->setRatio(0,0.999);
|
||||
this->setRatio(1,1.997);
|
||||
this->setRatio(2,3.006);
|
||||
this->setRatio(3,6.009);
|
||||
gains[0] = __FM4Op_gains[95];
|
||||
gains[1] = __FM4Op_gains[95];
|
||||
gains[2] = __FM4Op_gains[99];
|
||||
gains[3] = __FM4Op_gains[95];
|
||||
adsr[0]->setAll(0.05,0.03,1.0,0.04);
|
||||
adsr[1]->setAll(0.05,0.03,1.0,0.04);
|
||||
adsr[2]->setAll(0.05,0.03,1.0,0.04);
|
||||
adsr[3]->setAll(0.05,0.001,0.4,0.06);
|
||||
twozero->setGain(0.1);
|
||||
}
|
||||
|
||||
BeeThree :: ~BeeThree()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void BeeThree :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
waves[0]->setFreq(baseFreq * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * ratios[3]);
|
||||
}
|
||||
|
||||
MY_FLOAT BeeThree :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
if (modDepth > 0.0) {
|
||||
temp = 1.0 + (modDepth * vibWave->tick() * 0.1);
|
||||
waves[0]->setFreq(baseFreq * ratios[0] * temp);
|
||||
waves[1]->setFreq(baseFreq * ratios[1] * temp);
|
||||
waves[2]->setFreq(baseFreq * ratios[2] * temp);
|
||||
waves[3]->setFreq(baseFreq * ratios[3] * temp);
|
||||
}
|
||||
lastOutput = FM4Alg8 :: tick();
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
void BeeThree :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
gains[0] = amp * __FM4Op_gains[95];
|
||||
gains[1] = amp * __FM4Op_gains[95];
|
||||
gains[2] = amp * __FM4Op_gains[99];
|
||||
gains[3] = amp * __FM4Op_gains[95];
|
||||
this->setFreq(freq);
|
||||
this->keyOn();
|
||||
#if defined(_debug_)
|
||||
printf("BeeThree : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
23
BeeThree.h
23
BeeThree.h
@@ -1,23 +0,0 @@
|
||||
/******************************************/
|
||||
/* HammondOid Organ Subclass */
|
||||
/* of Algorithm 8 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__BeeThree_h)
|
||||
#define __BeeThree_h
|
||||
|
||||
#include "FM4Alg8.h"
|
||||
|
||||
class BeeThree : public FM4Alg8
|
||||
{
|
||||
public:
|
||||
BeeThree();
|
||||
~BeeThree();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
MY_FLOAT tick();
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
};
|
||||
|
||||
#endif
|
||||
80
BiQuad.cpp
80
BiQuad.cpp
@@ -1,80 +0,0 @@
|
||||
/*******************************************/
|
||||
/* BiQuad (2-pole, 2-zero) Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* See books on filters to understand */
|
||||
/* more about how this works. Nothing */
|
||||
/* out of the ordinary in this version. */
|
||||
/*******************************************/
|
||||
|
||||
#include "BiQuad.h"
|
||||
|
||||
BiQuad :: BiQuad() : Filter()
|
||||
{
|
||||
inputs = (MY_FLOAT *) malloc(2 * MY_FLOAT_SIZE);
|
||||
zeroCoeffs[0] = 0.0;
|
||||
zeroCoeffs[1] = 0.0;
|
||||
poleCoeffs[0] = 0.0;
|
||||
poleCoeffs[1] = 0.0;
|
||||
gain = 1.0;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
BiQuad :: ~BiQuad()
|
||||
{
|
||||
free(inputs);
|
||||
}
|
||||
|
||||
void BiQuad :: clear()
|
||||
{
|
||||
inputs[0] = 0.0;
|
||||
inputs[1] = 0.0;
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
void BiQuad :: setPoleCoeffs(MY_FLOAT *coeffs)
|
||||
{
|
||||
poleCoeffs[0] = coeffs[0];
|
||||
poleCoeffs[1] = coeffs[1];
|
||||
}
|
||||
|
||||
void BiQuad :: setZeroCoeffs(MY_FLOAT *coeffs)
|
||||
{
|
||||
zeroCoeffs[0] = coeffs[0];
|
||||
zeroCoeffs[1] = coeffs[1];
|
||||
}
|
||||
|
||||
void BiQuad :: setFreqAndReson(MY_FLOAT freq, MY_FLOAT reson)
|
||||
{
|
||||
poleCoeffs[1] = - (reson * reson);
|
||||
poleCoeffs[0] = 2.0 * reson * cos(TWO_PI * freq / SRATE);
|
||||
}
|
||||
|
||||
void BiQuad :: setEqualGainZeroes()
|
||||
{
|
||||
zeroCoeffs[1] = -1.0;
|
||||
zeroCoeffs[0] = 0.0;
|
||||
}
|
||||
|
||||
void BiQuad :: setGain(MY_FLOAT aValue)
|
||||
{
|
||||
gain = aValue;
|
||||
}
|
||||
|
||||
MY_FLOAT BiQuad :: tick(MY_FLOAT sample) /* Perform Filter Operation */
|
||||
{ /* Biquad is two pole, two zero filter */
|
||||
MY_FLOAT temp; /* Look it up in your favorite DSP text */
|
||||
|
||||
temp = sample * gain; /* Here's the math for the */
|
||||
temp += inputs[0] * poleCoeffs[0]; /* version which implements */
|
||||
temp += inputs[1] * poleCoeffs[1]; /* only 2 state variables. */
|
||||
|
||||
lastOutput = temp; /* This form takes */
|
||||
lastOutput += (inputs[0] * zeroCoeffs[0]); /* 5 multiplies and */
|
||||
lastOutput += (inputs[1] * zeroCoeffs[1]); /* 4 adds */
|
||||
inputs[1] = inputs[0]; /* and 3 moves */
|
||||
inputs[0] = temp; /* like the 2 state-var form*/
|
||||
|
||||
return lastOutput;
|
||||
|
||||
}
|
||||
|
||||
31
BiQuad.h
31
BiQuad.h
@@ -1,31 +0,0 @@
|
||||
/*******************************************/
|
||||
/* BiQuad (2-pole, 2-zero) Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* See books on filters to understand */
|
||||
/* more about how this works. Nothing */
|
||||
/* out of the ordinary in this version. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__BiQuad_h)
|
||||
#define __BiQuad_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class BiQuad : public Filter
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT poleCoeffs[2];
|
||||
MY_FLOAT zeroCoeffs[2];
|
||||
public:
|
||||
BiQuad();
|
||||
~BiQuad();
|
||||
void clear();
|
||||
void setPoleCoeffs(MY_FLOAT *coeffs);
|
||||
void setZeroCoeffs(MY_FLOAT *coeffs);
|
||||
void setGain(MY_FLOAT aValue);
|
||||
void setFreqAndReson(MY_FLOAT freq, MY_FLOAT reson);
|
||||
void setEqualGainZeroes();
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
46
BowTabl.cpp
46
BowTabl.cpp
@@ -1,46 +0,0 @@
|
||||
/***********************************************/
|
||||
/* Simple Bow Table Object, after Smith */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/***********************************************/
|
||||
|
||||
#include "BowTabl.h"
|
||||
|
||||
BowTabl :: BowTabl()
|
||||
{
|
||||
offSet = 0.0; /* offset is a bias, really not needed unless */
|
||||
/* friction is different in each direction */
|
||||
slope = 0.1; /* controls width of friction pulse, */
|
||||
/* related to bowForce */
|
||||
}
|
||||
|
||||
BowTabl :: ~BowTabl()
|
||||
{
|
||||
}
|
||||
|
||||
void BowTabl :: setOffset(MY_FLOAT aValue)
|
||||
{
|
||||
offSet = aValue;
|
||||
}
|
||||
|
||||
void BowTabl :: setSlope(MY_FLOAT aValue)
|
||||
{
|
||||
slope = aValue;
|
||||
}
|
||||
|
||||
MY_FLOAT BowTabl :: lookup(MY_FLOAT sample) /* Perform Table Lookup */
|
||||
{ /* sample is differential */
|
||||
/* string vs. bow velocity */
|
||||
MY_FLOAT input;
|
||||
input = sample + offSet; /* add bias to sample */
|
||||
input *= slope; /* scale it */
|
||||
lastOutput = fabs(input) + 0.75; /* below min delta, friction = 1 */
|
||||
lastOutput = pow(lastOutput,-4.0);
|
||||
// if (lastOutput < 0.0 ) lastOutput = 0.0; /* minimum friction is 0.0 */
|
||||
if (lastOutput > 1.0 ) lastOutput = 1.0; /* maximum friction is 1.0 */
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT BowTabl :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
22
BowTabl.h
22
BowTabl.h
@@ -1,22 +0,0 @@
|
||||
/***********************************************/
|
||||
/* Simple Bow Table Object, after Smith */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/***********************************************/
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class BowTabl : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT offSet;
|
||||
MY_FLOAT slope;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
BowTabl();
|
||||
~BowTabl();
|
||||
void setOffset(MY_FLOAT aValue);
|
||||
void setSlope(MY_FLOAT aValue);
|
||||
MY_FLOAT lookup(MY_FLOAT sample);
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
160
Bowed.cpp
160
Bowed.cpp
@@ -1,160 +0,0 @@
|
||||
/******************************************/
|
||||
/* Bowed String model ala Smith */
|
||||
/* after McIntyre, Schumacher, Woodhouse */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = bowPressure */
|
||||
/* CONTROL2 = bowPosition */
|
||||
/* CONTROL3 = vibrFreq */
|
||||
/* MOD_WHEEL= vibrGain */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "Bowed.h"
|
||||
|
||||
Bowed :: Bowed(MY_FLOAT lowestFreq)
|
||||
{
|
||||
long length;
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
neckDelay = new DLineL(length);
|
||||
length >> 1;
|
||||
bridgeDelay = new DLineL(length);
|
||||
bowTabl = new BowTabl;
|
||||
reflFilt = new OnePole;
|
||||
bodyFilt = new BiQuad;
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
adsr = new ADSR;
|
||||
vibrGain = 0.0;
|
||||
|
||||
neckDelay->setDelay(100.0);
|
||||
bridgeDelay->setDelay(29.0);
|
||||
|
||||
bowTabl->setSlope(3.0);
|
||||
|
||||
reflFilt->setPole(0.6 - (0.1 * RATE_NORM));
|
||||
reflFilt->setGain(0.95);
|
||||
|
||||
bodyFilt->setFreqAndReson(500.0, 0.85);
|
||||
bodyFilt->setEqualGainZeroes();
|
||||
bodyFilt->setGain(0.2);
|
||||
|
||||
vibr->normalize();
|
||||
vibr->setFreq(6.12723);
|
||||
|
||||
adsr->setAll(0.002,0.01,0.9,0.01);
|
||||
|
||||
betaRatio = 0.127236;
|
||||
}
|
||||
|
||||
Bowed :: ~Bowed()
|
||||
{
|
||||
delete neckDelay;
|
||||
delete bridgeDelay;
|
||||
delete bowTabl;
|
||||
delete reflFilt;
|
||||
delete bodyFilt;
|
||||
delete vibr;
|
||||
delete adsr;
|
||||
}
|
||||
|
||||
void Bowed :: clear()
|
||||
{
|
||||
neckDelay->clear();
|
||||
bridgeDelay->clear();
|
||||
}
|
||||
|
||||
void Bowed :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseDelay = (MY_FLOAT) SRATE / frequency - 4.0; /* delay - approx. filter delay */
|
||||
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)
|
||||
{
|
||||
adsr->setRate(rate);
|
||||
adsr->keyOn();
|
||||
maxVelocity = 0.03 + (0.2 * amplitude);
|
||||
}
|
||||
|
||||
void Bowed :: stopBowing(MY_FLOAT rate)
|
||||
{
|
||||
adsr->setRate(rate);
|
||||
adsr->keyOff();
|
||||
}
|
||||
|
||||
void Bowed :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->startBowing(amp,amp * 0.001);
|
||||
this->setFreq(freq);
|
||||
#if defined(_debug_)
|
||||
printf("Bowed : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Bowed :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->stopBowing((1.0 - amp) * 0.005);
|
||||
#if defined(_debug_)
|
||||
printf("Bowed : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Bowed :: setVibrato(MY_FLOAT amount)
|
||||
{
|
||||
vibrGain = amount;
|
||||
}
|
||||
|
||||
MY_FLOAT Bowed :: tick()
|
||||
{
|
||||
MY_FLOAT bowVelocity;
|
||||
MY_FLOAT bridgeRefl=0,nutRefl=0;
|
||||
MY_FLOAT newVel=0,velDiff=0,stringVel=0;
|
||||
|
||||
bowVelocity = maxVelocity * adsr->tick();
|
||||
|
||||
bridgeRefl = -reflFilt->tick(
|
||||
bridgeDelay->lastOut()); /* Bridge Reflection */
|
||||
nutRefl = -neckDelay->lastOut(); /* Nut Reflection */
|
||||
stringVel = bridgeRefl + nutRefl; /* Sum is String Velocity */
|
||||
velDiff = bowVelocity - stringVel; /* Differential Velocity */
|
||||
newVel = velDiff * bowTabl->lookup(velDiff); /* Non-Lin Bow Function */
|
||||
neckDelay->tick(bridgeRefl + newVel); /* Do string */
|
||||
bridgeDelay->tick(nutRefl + newVel); /* propagations */
|
||||
|
||||
if (vibrGain > 0.0) {
|
||||
neckDelay->setDelay((baseDelay * (1.0 - betaRatio)) +
|
||||
(baseDelay * vibrGain*vibr->tick()));
|
||||
}
|
||||
|
||||
lastOutput = bodyFilt->tick(bridgeDelay->lastOut());
|
||||
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
void Bowed :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("Bowed : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == MIDI_control1)
|
||||
bowTabl->setSlope(5.0 - (4.0 * value * NORM_7));
|
||||
else if (number == MIDI_control2) {
|
||||
betaRatio = 0.027236 + (0.2 * value * NORM_7);
|
||||
bridgeDelay->setDelay(baseDelay * betaRatio); /* bow to bridge length */
|
||||
neckDelay->setDelay(baseDelay * (1.0 - betaRatio)); /* bow to nut (finger) length */
|
||||
}
|
||||
else if (number == MIDI_control3)
|
||||
vibr->setFreq((value * NORM_7 * 12.0));
|
||||
else if (number == MIDI_mod_wheel)
|
||||
vibrGain = (value * NORM_7 * 0.4);
|
||||
else if (number == MIDI_after_touch)
|
||||
adsr->setTarget(value * NORM_7);
|
||||
else {
|
||||
printf("Bowed : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
56
Bowed.h
56
Bowed.h
@@ -1,56 +0,0 @@
|
||||
/******************************************/
|
||||
/* Bowed String model ala Smith */
|
||||
/* after McIntyre, Schumacher, Woodhouse */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = bowPressure */
|
||||
/* CONTROL2 = bowPosition */
|
||||
/* CONTROL3 = vibrFreq */
|
||||
/* MOD_WHEEL= vibrGain */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Bowed_h)
|
||||
#define __Bowed_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "DLineL.h"
|
||||
#include "BowTabl.h"
|
||||
#include "OnePole.h"
|
||||
#include "BiQuad.h"
|
||||
#include "RawLoop.h"
|
||||
#include "ADSR.h"
|
||||
|
||||
class Bowed : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
DLineL *neckDelay;
|
||||
DLineL *bridgeDelay;
|
||||
BowTabl *bowTabl;
|
||||
OnePole *reflFilt;
|
||||
BiQuad *bodyFilt;
|
||||
RawLoop *vibr;
|
||||
ADSR *adsr;
|
||||
MY_FLOAT maxVelocity;
|
||||
MY_FLOAT baseDelay;
|
||||
MY_FLOAT vibrGain;
|
||||
MY_FLOAT betaRatio;
|
||||
public:
|
||||
Bowed(MY_FLOAT lowestFreq);
|
||||
~Bowed();
|
||||
void clear();
|
||||
void startBowing(MY_FLOAT amplitude,MY_FLOAT rate);
|
||||
void stopBowing(MY_FLOAT rate);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void setVibrato(MY_FLOAT amount);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
129
Brass.cpp
129
Brass.cpp
@@ -1,129 +0,0 @@
|
||||
/******************************************/
|
||||
/* Waveguide Brass Instrument Model ala */
|
||||
/* Cook (TBone, HosePlayer) */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = lipTension */
|
||||
/* CONTROL2 = slideLength */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#include "Brass.h"
|
||||
|
||||
Brass :: Brass(MY_FLOAT lowestFreq)
|
||||
{
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
delayLine = new DLineA(length);
|
||||
lipFilter = new LipFilt;
|
||||
dcBlock = new DCBlock;
|
||||
adsr = new ADSR;
|
||||
adsr->setAll(0.02, 0.05, 1.0, 0.001);
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
this->clear();
|
||||
|
||||
vibr->normalize();
|
||||
vibr->setFreq(6.137);
|
||||
vibrGain = 0.05; /* breath periodic vibrato component */
|
||||
}
|
||||
|
||||
Brass :: ~Brass()
|
||||
{
|
||||
delete delayLine;
|
||||
delete lipFilter;
|
||||
delete dcBlock;
|
||||
delete adsr;
|
||||
delete vibr;
|
||||
}
|
||||
|
||||
void Brass :: clear()
|
||||
{
|
||||
delayLine->clear();
|
||||
lipFilter->clear();
|
||||
dcBlock->clear();
|
||||
/* adsr->reset(); */
|
||||
}
|
||||
|
||||
void Brass :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
slideTarget = ((MY_FLOAT) SRATE / frequency * 2.0) + 3.0;
|
||||
/* fudge correction for filter delays */
|
||||
delayLine->setDelay(slideTarget); /* we'll play a harmonic */
|
||||
lipTarget = frequency;
|
||||
lipFilter->setFreq(frequency);
|
||||
}
|
||||
|
||||
void Brass :: setLip(MY_FLOAT frequency)
|
||||
{
|
||||
lipFilter->setFreq(frequency);
|
||||
}
|
||||
|
||||
void Brass :: startBlowing(MY_FLOAT amplitude,MY_FLOAT rate)
|
||||
{
|
||||
adsr->setAttackRate(rate);
|
||||
maxPressure = amplitude;
|
||||
adsr->keyOn();
|
||||
}
|
||||
|
||||
void Brass :: stopBlowing(MY_FLOAT rate)
|
||||
{
|
||||
adsr->setReleaseRate(rate);
|
||||
adsr->keyOff();
|
||||
}
|
||||
|
||||
void Brass :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
this->startBlowing(amp, amp * 0.001);
|
||||
#if defined(_debug_)
|
||||
printf("Brass : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Brass :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->stopBlowing(amp * 0.005);
|
||||
#if defined(_debug_)
|
||||
printf("Brass : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
MY_FLOAT Brass :: tick()
|
||||
{
|
||||
MY_FLOAT breathPressure;
|
||||
|
||||
breathPressure = maxPressure * adsr->tick();
|
||||
breathPressure += vibrGain * vibr->tick();
|
||||
lastOutput = delayLine->tick( /* bore delay */
|
||||
dcBlock->tick( /* block DC */
|
||||
lipFilter->tick(0.3 * breathPressure, /* mouth input */
|
||||
0.85 * delayLine->lastOut()))); /* and bore reflection */
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
void Brass :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
#if defined(_debug_)
|
||||
printf("Brass : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == MIDI_control1) {
|
||||
temp = lipTarget * pow(4.0,(2.0*value*NORM_7) - 1.0);
|
||||
this->setLip(temp);
|
||||
}
|
||||
else if (number == MIDI_control2)
|
||||
delayLine->setDelay(slideTarget * (0.5 + (value * NORM_7)));
|
||||
else if (number == MIDI_control3)
|
||||
vibr->setFreq((value * NORM_7 * 12.0));
|
||||
else if (number == MIDI_mod_wheel)
|
||||
vibrGain = (value * NORM_7 * 0.4);
|
||||
else if (number == MIDI_after_touch)
|
||||
adsr->setTarget(value * NORM_7);
|
||||
else {
|
||||
printf("Brass : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
53
Brass.h
53
Brass.h
@@ -1,53 +0,0 @@
|
||||
/******************************************/
|
||||
/* Simple Brass Instrument Model ala */
|
||||
/* Cook (TBone, HosePlayer) */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = lipTension */
|
||||
/* CONTROL2 = slideLength */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Brass_h)
|
||||
#define __Brass_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "DLineA.h"
|
||||
#include "LipFilt.h"
|
||||
#include "DCBlock.h"
|
||||
#include "ADSR.h"
|
||||
#include "RawLoop.h"
|
||||
|
||||
class Brass: public Instrmnt
|
||||
{
|
||||
protected:
|
||||
DLineA *delayLine;
|
||||
LipFilt *lipFilter;
|
||||
DCBlock *dcBlock;
|
||||
ADSR *adsr;
|
||||
RawLoop *vibr;
|
||||
long length;
|
||||
MY_FLOAT lipTarget;
|
||||
MY_FLOAT slideTarget;
|
||||
MY_FLOAT vibrGain;
|
||||
MY_FLOAT maxPressure;
|
||||
public:
|
||||
Brass(MY_FLOAT lowestFreq);
|
||||
~Brass();
|
||||
void clear();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void setLip(MY_FLOAT frequency);
|
||||
void startBlowing(MY_FLOAT amplitude,MY_FLOAT rate);
|
||||
void stopBlowing(MY_FLOAT rate);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
125
Clarinet.cpp
125
Clarinet.cpp
@@ -1,125 +0,0 @@
|
||||
/******************************************/
|
||||
/* Waveguide Clarinet model ala Smith */
|
||||
/* after McIntyre, Schumacher, Woodhouse */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = reedStiffns */
|
||||
/* CONTROL2 = noiseGain */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#include "Clarinet.h"
|
||||
|
||||
Clarinet :: Clarinet(MY_FLOAT lowestFreq)
|
||||
{
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
delayLine = new DLineL(length);
|
||||
reedTable = new ReedTabl;
|
||||
reedTable->setOffset(0.7);
|
||||
reedTable->setSlope(-0.3);
|
||||
filter = new OneZero;
|
||||
envelope = new Envelope;
|
||||
noise = new Noise;
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
vibr->normalize();
|
||||
vibr->setFreq(5.735);
|
||||
outputGain = 1.0;
|
||||
noiseGain = 0.2;
|
||||
vibrGain = 0.1;
|
||||
}
|
||||
|
||||
Clarinet :: ~Clarinet()
|
||||
{
|
||||
delete delayLine;
|
||||
delete reedTable;
|
||||
delete filter;
|
||||
delete envelope;
|
||||
delete noise;
|
||||
delete vibr;
|
||||
}
|
||||
|
||||
void Clarinet :: clear()
|
||||
{
|
||||
delayLine->clear();
|
||||
filter->tick(0.0);
|
||||
}
|
||||
|
||||
void Clarinet :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
delayLine->setDelay /* length - approx filter delay */
|
||||
((SRATE / frequency) * 0.5 - 1.5);
|
||||
}
|
||||
|
||||
void Clarinet :: startBlowing(MY_FLOAT amplitude,MY_FLOAT rate)
|
||||
{
|
||||
envelope->setRate(rate);
|
||||
envelope->setTarget(amplitude);
|
||||
}
|
||||
|
||||
void Clarinet :: stopBlowing(MY_FLOAT rate)
|
||||
{
|
||||
envelope->setRate(rate);
|
||||
envelope->setTarget(0.0);
|
||||
}
|
||||
|
||||
void Clarinet :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
this->startBlowing(0.55 + (amp * 0.30),amp * 0.005);
|
||||
outputGain = amp + 0.001;
|
||||
#if defined(_debug_)
|
||||
printf("Clarinet : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Clarinet :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->stopBlowing(amp * 0.01);
|
||||
#if defined(_debug_)
|
||||
printf("Clarinet : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
MY_FLOAT Clarinet :: tick()
|
||||
{
|
||||
MY_FLOAT pressureDiff;
|
||||
MY_FLOAT breathPressure;
|
||||
|
||||
breathPressure = envelope->tick();
|
||||
breathPressure += breathPressure *
|
||||
noiseGain * noise->tick();
|
||||
breathPressure += breathPressure *
|
||||
vibrGain * vibr->tick();
|
||||
pressureDiff = filter->tick(delayLine->lastOut()); /* differential pressure */
|
||||
pressureDiff = (pressureDiff * -0.95) - breathPressure; /* of reflected and mouth */
|
||||
lastOutput = delayLine->tick(breathPressure + /* perform scattering */
|
||||
pressureDiff * reedTable->lookup(pressureDiff)); /* in economical way */
|
||||
lastOutput *= outputGain;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
void Clarinet :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("Clarinet : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == MIDI_control1)
|
||||
reedTable->setSlope(-0.44 + (0.26 * value * NORM_7));
|
||||
else if (number == MIDI_control2)
|
||||
noiseGain = (value * NORM_7 * 0.4);
|
||||
else if (number == MIDI_control3)
|
||||
vibr->setFreq((value * NORM_7 * 12.0));
|
||||
else if (number == MIDI_mod_wheel)
|
||||
vibrGain = (value * NORM_7 * 0.5);
|
||||
else if (number == MIDI_after_touch) {
|
||||
envelope->setValue(value * NORM_7);
|
||||
}
|
||||
else {
|
||||
printf("Clarinet : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
53
Clarinet.h
53
Clarinet.h
@@ -1,53 +0,0 @@
|
||||
/******************************************/
|
||||
/* Clarinet model ala Smith */
|
||||
/* after McIntyre, Schumacher, Woodhouse */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = reedStiffns */
|
||||
/* CONTROL2 = noiseGain */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Clarinet_h)
|
||||
#define __Clarinet_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "DLineL.h"
|
||||
#include "ReedTabl.h"
|
||||
#include "OneZero.h"
|
||||
#include "Envelope.h"
|
||||
#include "Noise.h"
|
||||
#include "RawLoop.h"
|
||||
|
||||
class Clarinet : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
DLineL *delayLine;
|
||||
ReedTabl *reedTable;
|
||||
OneZero *filter;
|
||||
Envelope *envelope;
|
||||
Noise *noise;
|
||||
RawLoop *vibr;
|
||||
long length;
|
||||
MY_FLOAT outputGain;
|
||||
MY_FLOAT noiseGain;
|
||||
MY_FLOAT vibrGain;
|
||||
public:
|
||||
Clarinet(MY_FLOAT lowestFreq);
|
||||
~Clarinet();
|
||||
void clear();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void startBlowing(MY_FLOAT amplitude,MY_FLOAT rate);
|
||||
void stopBlowing(MY_FLOAT rate);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
virtual MY_FLOAT tick();
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
41
DCBlock.cpp
41
DCBlock.cpp
@@ -1,41 +0,0 @@
|
||||
/*******************************************/
|
||||
/* DC Blocking Filter */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This guy is very helpful in, uh, */
|
||||
/* blocking DC. Needed because a simple */
|
||||
/* low-pass reflection filter allows DC */
|
||||
/* to build up inside recursive */
|
||||
/* structures. */
|
||||
/*******************************************/
|
||||
|
||||
#include "DCBlock.h"
|
||||
|
||||
DCBlock :: DCBlock()
|
||||
{
|
||||
inputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
|
||||
outputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
|
||||
this->clear();
|
||||
|
||||
}
|
||||
|
||||
DCBlock :: ~DCBlock()
|
||||
{
|
||||
free(inputs);
|
||||
free(outputs);
|
||||
}
|
||||
|
||||
void DCBlock :: clear()
|
||||
{
|
||||
outputs[0] = 0.0;
|
||||
inputs[0] = 0.0;
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
MY_FLOAT DCBlock :: tick(MY_FLOAT sample)
|
||||
{
|
||||
outputs[0] = sample - inputs[0] + (0.99 * outputs[0]);
|
||||
inputs[0] = sample;
|
||||
lastOutput = outputs[0];
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
25
DCBlock.h
25
DCBlock.h
@@ -1,25 +0,0 @@
|
||||
/*******************************************/
|
||||
/* DC Blocking Filter */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This guy is very helpful in, uh, */
|
||||
/* blocking DC. Needed because a simple */
|
||||
/* low-pass reflection filter allows DC */
|
||||
/* to build up inside recursive */
|
||||
/* structures. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__DCBlock_h)
|
||||
#define __DCBlock_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class DCBlock : public Filter
|
||||
{
|
||||
public:
|
||||
DCBlock();
|
||||
~DCBlock();
|
||||
void clear();
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
104
DLineA.cpp
104
DLineA.cpp
@@ -1,104 +0,0 @@
|
||||
/*******************************************/
|
||||
/* */
|
||||
/* AllPass Interpolating Delay Line */
|
||||
/* Object by Perry R. Cook 1995-96 */
|
||||
/* This one uses a delay line of maximum */
|
||||
/* length specified on creation, and */
|
||||
/* interpolates fractional length using */
|
||||
/* an all-pass filter. This version is */
|
||||
/* more efficient for computing static */
|
||||
/* length delay lines (alpha and coeff */
|
||||
/* are computed only when the length */
|
||||
/* is set, there probably is a more */
|
||||
/* efficient computational form if alpha */
|
||||
/* is changed often (each sample)). */
|
||||
/* */
|
||||
/*******************************************/
|
||||
|
||||
#include "DLineA.h"
|
||||
|
||||
DLineA :: DLineA(long max_length)
|
||||
{
|
||||
long i;
|
||||
length = max_length;
|
||||
inputs = (MY_FLOAT *) malloc(length * MY_FLOAT_SIZE);
|
||||
for (i=0;i<length;i++) inputs[i] = 0;
|
||||
this->clear();
|
||||
inPoint = 0;
|
||||
outPoint = length >> 1;
|
||||
}
|
||||
|
||||
DLineA :: ~DLineA()
|
||||
{
|
||||
free(inputs);
|
||||
}
|
||||
|
||||
void DLineA :: clear()
|
||||
{
|
||||
long i;
|
||||
for (i=0;i<length;i++) inputs[i] = 0.0;
|
||||
lastIn = 0;
|
||||
lastOutput = 0;
|
||||
}
|
||||
|
||||
void DLineA :: setDelay(MY_FLOAT lag)
|
||||
{
|
||||
MY_FLOAT outputPointer;
|
||||
outputPointer = inPoint - lag + 2; /* outPoint chases inpoint */
|
||||
/* + 2 for interp and other */
|
||||
while (outputPointer<0)
|
||||
outputPointer += length; /* modulo table length */
|
||||
outPoint = (long) outputPointer; /* Integer part of delay */
|
||||
alpha = 1.0 + outPoint - outputPointer; /* fractional part of delay */
|
||||
if (alpha<0.1) {
|
||||
outputPointer += 1.0; /* Hack to avoid pole/zero */
|
||||
outPoint += 1; /* cancellation. Keeps allpass */
|
||||
alpha += 1.0; /* delay in range of .1 to 1.1 */
|
||||
}
|
||||
coeff = (1.0 - alpha) / (1.0 + alpha); /* coefficient for all pass */
|
||||
}
|
||||
|
||||
MY_FLOAT DLineA :: tick(MY_FLOAT sample) /* Take sample, yield sample */
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
inputs[inPoint++] = sample; /* Write input sample */
|
||||
if (inPoint == length) /* Increment input pointer */
|
||||
inPoint -= length; /* modulo length */
|
||||
temp = inputs[outPoint++]; /* filter input */
|
||||
if (outPoint == length) /* Increment output pointer */
|
||||
outPoint -= length; /* modulo length */
|
||||
lastOutput = -coeff * lastOutput; /* delayed output */
|
||||
lastOutput += lastIn + (coeff * temp); /* input + delayed Input */
|
||||
lastIn = temp;
|
||||
return lastOutput; /* save output and return */
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
|
||||
void main()
|
||||
{
|
||||
DLineA delay(140);
|
||||
FILE *fd;
|
||||
MY_FLOAT temp;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
fd = fopen("test.raw","wb");
|
||||
|
||||
delay.setDelay(128);
|
||||
for (i=0;i<4096;i++) {
|
||||
if (i%256 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = (temp + delay.tick(temp)) * 16000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
delay.setDelay(64.5);
|
||||
for (i=0;i<4096;i++) {
|
||||
if (i%256 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = (temp + delay.tick(temp)) * 16000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
41
DLineA.h
41
DLineA.h
@@ -1,41 +0,0 @@
|
||||
/*******************************************/
|
||||
/* */
|
||||
/* AllPass Interpolating Delay Line */
|
||||
/* Object by Perry R. Cook 1995-96 */
|
||||
/* This one uses a delay line of maximum */
|
||||
/* length specified on creation, and */
|
||||
/* interpolates fractional length using */
|
||||
/* an all-pass filter. This version is */
|
||||
/* more efficient for computing static */
|
||||
/* length delay lines (alpha and coeff */
|
||||
/* are computed only when the length */
|
||||
/* is set, there probably is a more */
|
||||
/* efficient computational form if alpha */
|
||||
/* is changed often (each sample)). */
|
||||
/* */
|
||||
/*******************************************/
|
||||
|
||||
|
||||
#if !defined(__DLineA_h)
|
||||
#define __DLineA_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class DLineA : public Filter
|
||||
{
|
||||
protected:
|
||||
long inPoint;
|
||||
long outPoint;
|
||||
long length;
|
||||
MY_FLOAT alpha;
|
||||
MY_FLOAT coeff;
|
||||
MY_FLOAT lastIn;
|
||||
public:
|
||||
DLineA(long max_length);
|
||||
~DLineA();
|
||||
void clear();
|
||||
void setDelay(MY_FLOAT length);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
90
DLineL.cpp
90
DLineL.cpp
@@ -1,90 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Linearly Interpolating Delay Line */
|
||||
/* Object by Perry R. Cook 1995-96 */
|
||||
/* This one uses a delay line of maximum */
|
||||
/* length specified on creation, and */
|
||||
/* linearly interpolates fractional */
|
||||
/* length. It is designed to be more */
|
||||
/* efficient if the delay length is not */
|
||||
/* changed very often. */
|
||||
/*******************************************/
|
||||
|
||||
#include "DLineL.h"
|
||||
|
||||
DLineL :: DLineL(long max_length)
|
||||
{
|
||||
length = max_length;
|
||||
inputs = (MY_FLOAT *) malloc(length * MY_FLOAT_SIZE);
|
||||
this->clear();
|
||||
outPoint = 0;
|
||||
inPoint = length >> 1;
|
||||
}
|
||||
|
||||
DLineL :: ~DLineL()
|
||||
{
|
||||
free(inputs);
|
||||
}
|
||||
|
||||
void DLineL :: clear()
|
||||
{
|
||||
long i;
|
||||
for (i=0;i<length;i++) inputs[i] = 0.0;
|
||||
lastOutput = 0;
|
||||
}
|
||||
|
||||
void DLineL :: setDelay(MY_FLOAT lag)
|
||||
{
|
||||
MY_FLOAT outputPointer;
|
||||
outputPointer = inPoint - lag; /* read chases write, add 1 for interp. */
|
||||
while (outputPointer<0)
|
||||
outputPointer += length; /* modulo maximum length */
|
||||
outPoint = (long) outputPointer; /* integer part */
|
||||
alpha = outputPointer - outPoint; /* fractional part */
|
||||
omAlpha = 1.0 - alpha; /* 1.0 - fractional part (more efficient) */
|
||||
}
|
||||
|
||||
MY_FLOAT DLineL :: tick(MY_FLOAT sample) /* Take one, yield one */
|
||||
{
|
||||
inputs[inPoint++] = sample; /* Input next sample */
|
||||
if (inPoint == length) /* Check for end condition */
|
||||
inPoint -= length;
|
||||
lastOutput = inputs[outPoint++] * omAlpha; /* first 1/2 of interpolation */
|
||||
if (outPoint<length) { /* Check for end condition */
|
||||
lastOutput += inputs[outPoint] * alpha; /* second 1/2 of interpolation */
|
||||
}
|
||||
else { /* if at end . . . */
|
||||
lastOutput += inputs[0] * alpha; /* second 1/2 of interpolation */
|
||||
outPoint -= length;
|
||||
}
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
|
||||
void main()
|
||||
{
|
||||
DLineL delay(140);
|
||||
FILE *fd;
|
||||
MY_FLOAT temp;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
fd = fopen("test.raw","wb");
|
||||
|
||||
delay.setDelay(128);
|
||||
for (i=0;i<4096;i++) {
|
||||
if (i%256 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = (temp + delay.tick(temp)) * 16000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
delay.setDelay(64.5);
|
||||
for (i=0;i<4096;i++) {
|
||||
if (i%256 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = (temp + delay.tick(temp)) * 16000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
33
DLineL.h
33
DLineL.h
@@ -1,33 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Linearly Interpolating Delay Line */
|
||||
/* Object by Perry R. Cook 1995-96 */
|
||||
/* This one uses a delay line of maximum */
|
||||
/* length specified on creation, and */
|
||||
/* linearly interpolates fractional */
|
||||
/* length. It is designed to be more */
|
||||
/* efficient if the delay length is not */
|
||||
/* changed very often. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__DLineL_h)
|
||||
#define __DLineL_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class DLineL : public Filter
|
||||
{
|
||||
protected:
|
||||
long inPoint;
|
||||
long outPoint;
|
||||
long length;
|
||||
MY_FLOAT alpha;
|
||||
MY_FLOAT omAlpha;
|
||||
public:
|
||||
DLineL(long max_length);
|
||||
~DLineL();
|
||||
void clear();
|
||||
void setDelay(MY_FLOAT length);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
80
DLineN.cpp
80
DLineN.cpp
@@ -1,80 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Non-Interpolating Delay Line */
|
||||
/* Object by Perry R. Cook 1995-96 */
|
||||
/* This one uses a delay line of maximum */
|
||||
/* length specified on creation. A non- */
|
||||
/* interpolating delay line should be */
|
||||
/* used in non-time varying (reverb) or */
|
||||
/* non-critical (????) applications. */
|
||||
/*******************************************/
|
||||
|
||||
#include "DLineN.h"
|
||||
|
||||
DLineN :: DLineN(long max_length)
|
||||
{
|
||||
length = max_length;
|
||||
inputs = (MY_FLOAT *) malloc(length * MY_FLOAT_SIZE);
|
||||
this->clear();
|
||||
this->setDelay(length * 0.5);
|
||||
inPoint = 0;
|
||||
outPoint = 0;
|
||||
}
|
||||
|
||||
DLineN :: ~DLineN()
|
||||
{
|
||||
free(inputs);
|
||||
}
|
||||
|
||||
void DLineN :: clear()
|
||||
{
|
||||
long i;
|
||||
for (i=0;i<length;i++) inputs[i] = 0.0;
|
||||
lastOutput = 0;
|
||||
}
|
||||
|
||||
void DLineN :: setDelay(MY_FLOAT lag)
|
||||
{
|
||||
outPoint = inPoint - (long) lag; /* read chases write */
|
||||
while (outPoint<0) outPoint += length; /* modulo maximum length */
|
||||
}
|
||||
|
||||
MY_FLOAT DLineN :: tick(MY_FLOAT sample) /* Take one, yield one */
|
||||
{
|
||||
inputs[inPoint++] = sample; /* Input next sample */
|
||||
if (inPoint == length) /* Check for end condition */
|
||||
inPoint -= length;
|
||||
lastOutput = inputs[outPoint++]; // first 1/2 of interpolation */
|
||||
if (outPoint>=length) { // Check for end condition */
|
||||
outPoint -= length;
|
||||
}
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
DLineN delay(140);
|
||||
FILE *fd;
|
||||
MY_FLOAT temp;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
fd = fopen("test.raw","wb");
|
||||
|
||||
delay.setDelay(128);
|
||||
for (i=0;i<4096;i++) {
|
||||
if (i%256 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = (temp + delay.tick(temp)) * 16000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
delay.setDelay(64.5);
|
||||
for (i=0;i<4096;i++) {
|
||||
if (i%256 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = (temp + delay.tick(temp)) * 16000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
30
DLineN.h
30
DLineN.h
@@ -1,30 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Non-Interpolating Delay Line */
|
||||
/* Object by Perry R. Cook 1995-96 */
|
||||
/* This one uses a delay line of maximum */
|
||||
/* length specified on creation. A non- */
|
||||
/* interpolating delay line should be */
|
||||
/* used in non-time varying (reverb) or */
|
||||
/* non-critical (????) applications. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__DLineN_h)
|
||||
#define __DLineN_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class DLineN : public Filter
|
||||
{
|
||||
protected:
|
||||
long inPoint;
|
||||
long outPoint;
|
||||
long length;
|
||||
public:
|
||||
DLineN(long max_length);
|
||||
~DLineN();
|
||||
void clear();
|
||||
void setDelay(MY_FLOAT length);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
164
DrumSynt.cpp
164
DrumSynt.cpp
@@ -1,164 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Master Class for Drum Synthesizer */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains a bunch of */
|
||||
/* RawWvIn objects (Non-Interpolating, */
|
||||
/* 1 shot players), run through a bunch */
|
||||
/* of one-pole filters. You can specify */
|
||||
/* the maximum Polyphony (maximum number */
|
||||
/* of simultaneous voices) in a #define */
|
||||
/* in the .h file. */
|
||||
/*******************************************/
|
||||
|
||||
#include "DrumSynt.h"
|
||||
#include <string.h>
|
||||
|
||||
char waveNames[DRUM_NUMWAVES][16] = {
|
||||
"bass.raw",
|
||||
"snar.raw",
|
||||
"tomlow.raw",
|
||||
"tommid.raw",
|
||||
"tomhi.raw",
|
||||
"hat.raw",
|
||||
"ride.raw",
|
||||
"crash.raw",
|
||||
"cowbell.raw",
|
||||
"tamb.raw"
|
||||
};
|
||||
|
||||
DrumSynt :: DrumSynt() : Object()
|
||||
{
|
||||
int i;
|
||||
/* char temp[64]; */
|
||||
|
||||
/* for (i=0;i<DRUM_NUMWAVES;i++) { */
|
||||
/* strcpy(temp,"rawwaves/drumwavs/"); */
|
||||
/* strcat(temp,waveNames[i]); */
|
||||
/* waves[i] = new RawWvIn(temp); */
|
||||
/* waves[i]->finish(); */
|
||||
/* waves[i]->normalize(0.2); */
|
||||
/* } */
|
||||
|
||||
for (i=0;i<DRUM_POLYPHONY;i++) {
|
||||
filters[i] = new OnePole;
|
||||
sounding[i] = -1;
|
||||
/* filtSounding[i] = -1; */
|
||||
}
|
||||
numSounding = 0; /* This counts the number */
|
||||
/* of sounding voices */
|
||||
}
|
||||
|
||||
void DrumSynt :: noteOn(int noteNum, int vel)
|
||||
{
|
||||
int i,notDone;
|
||||
char tempString[64];
|
||||
RawWvIn *tempWv;
|
||||
OnePole *tempFilt;
|
||||
|
||||
printf("NoteOn: %s vel=%i\n",waveNames[noteNum],vel);
|
||||
|
||||
notDone = -1;
|
||||
for (i=0;i<DRUM_POLYPHONY;i++) { /* Check first to see */
|
||||
if (sounding[i] == noteNum) notDone = i; /* if there's already */
|
||||
} /* one like this sounding */
|
||||
|
||||
if (notDone<0) { /* If not, then */
|
||||
if (numSounding == DRUM_POLYPHONY) { /* If we're already */
|
||||
delete waves[0]; /* at max polyphony, */
|
||||
filters[0]->clear(); /* then */
|
||||
tempWv = waves[0];
|
||||
tempFilt = filters[0];
|
||||
for (i=0;i<DRUM_POLYPHONY-1;i++) { /* preempt oldest */
|
||||
waves[i] = waves[i+1]; /* oldest voice and */
|
||||
filters[i] = filters[i+1]; /* ripple all down */
|
||||
}
|
||||
waves[DRUM_POLYPHONY-1] = tempWv;
|
||||
filters[DRUM_POLYPHONY-1] = tempFilt;
|
||||
}
|
||||
else {
|
||||
numSounding += 1; /* otherwise just add one */
|
||||
}
|
||||
|
||||
sounding[numSounding-1] = noteNum; /* allocate new wave */
|
||||
strcpy(tempString,"rawwaves/drumwavs/");
|
||||
strcat(tempString,waveNames[noteNum]);
|
||||
waves[numSounding-1] = new RawWvIn(tempString);
|
||||
waves[numSounding-1]->normalize(0.2);
|
||||
filters[numSounding-1]->setPole(0.999 - (vel / 32.0));
|
||||
filters[numSounding-1]->setGain(vel / 128.0);
|
||||
}
|
||||
else {
|
||||
waves[notDone]->reset();
|
||||
filters[notDone]->setPole(0.999 - (vel / 32.0));
|
||||
filters[notDone]->setGain(vel / 128.0);
|
||||
}
|
||||
|
||||
printf("Number Sounding = %i\n",numSounding);
|
||||
for (i=0;i<numSounding;i++) printf(" %i ",sounding[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
MY_FLOAT DrumSynt :: tick()
|
||||
{
|
||||
int i, j, notDone;
|
||||
MY_FLOAT output;
|
||||
OnePole *tempFilt;
|
||||
|
||||
i = 0;
|
||||
notDone = 1;
|
||||
output = 0.0;
|
||||
|
||||
if (numSounding == 0) notDone = 0;
|
||||
while (notDone && (i < numSounding)) {
|
||||
|
||||
output += waves[i]->lastOut();
|
||||
|
||||
if (waves[i]->informTick() == 1) {
|
||||
|
||||
printf("Wave %i %i down here\n",i,sounding[i]);
|
||||
|
||||
delete waves[i];
|
||||
tempFilt = filters[i];
|
||||
|
||||
for (j=i;j<numSounding-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;
|
||||
numSounding -= 1;
|
||||
if (numSounding == 0) notDone = 0;
|
||||
i -= 1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/************** Test Main Program *********************/
|
||||
|
||||
#include "miditabl.h"
|
||||
#include "RawWvOut.h"
|
||||
#include "Reverb.h"
|
||||
#include "Noise.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
long i,j;
|
||||
DrumSynt instrument;
|
||||
RawWvOut output("test.snd");
|
||||
Reverb reverb(2137);
|
||||
Noise noise;
|
||||
|
||||
for (j=0;j<100;j++) {
|
||||
i = (int) (fabs(noise.tick()) * DRUM_NUMWAVES);
|
||||
instrument.noteOn(i,127);
|
||||
for (i=0;i<2000;i++) output.tick(reverb.tick(instrument.tick()));
|
||||
}
|
||||
|
||||
for (i=0;i<22000;i++) output.tick(reverb.tick(instrument.tick()));
|
||||
|
||||
}
|
||||
37
DrumSynt.h
37
DrumSynt.h
@@ -1,37 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Master Class for Drum Synthesizer */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains a bunch of */
|
||||
/* RawWvIn objects (Non-Interpolating, */
|
||||
/* 1 shot players), run through a bunch */
|
||||
/* of one-pole filters. You can specify */
|
||||
/* the maximum Polyphony (maximum number */
|
||||
/* of simultaneous voices) in a #define */
|
||||
/* in the .h file. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__DrumSynt_h)
|
||||
#define __DrumSynt_h
|
||||
|
||||
#include "Object.h"
|
||||
#include "RawWvIn.h"
|
||||
#include "OnePole.h"
|
||||
|
||||
#define DRUM_NUMWAVES 10
|
||||
#define DRUM_POLYPHONY 4
|
||||
|
||||
class DrumSynt : public Object
|
||||
{
|
||||
protected:
|
||||
RawWvIn *waves[DRUM_POLYPHONY];
|
||||
OnePole *filters[DRUM_POLYPHONY];
|
||||
int sounding[DRUM_POLYPHONY];
|
||||
int numSounding;
|
||||
public:
|
||||
DrumSynt();
|
||||
/* ~DrumSynt(); */
|
||||
void noteOn(int noteNum, int vel);
|
||||
MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
113
Envelope.cpp
113
Envelope.cpp
@@ -1,113 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Envelope Class, Perry R. Cook, 1995-96 */
|
||||
/* This is the base class for envelopes. */
|
||||
/* This one is capable of ramping state */
|
||||
/* from where it is to a target value by */
|
||||
/* a rate. It also responds to simple */
|
||||
/* KeyOn and KeyOff messages, ramping to */
|
||||
/* 1.0 on keyon and to 0.0 on keyoff. */
|
||||
/* There are two tick (update value) */
|
||||
/* methods, one returns the value, and */
|
||||
/* other returns 0 if the envelope is at */
|
||||
/* the target value (the state bit). */
|
||||
/*******************************************/
|
||||
|
||||
#include "Envelope.h"
|
||||
|
||||
Envelope :: Envelope() : Object()
|
||||
{
|
||||
target = 0.0;
|
||||
value = 0.0;
|
||||
rate = 0.001;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
Envelope :: ~Envelope()
|
||||
{
|
||||
}
|
||||
|
||||
void Envelope :: keyOn()
|
||||
{
|
||||
target = 1.0;
|
||||
if (value != target) state = 1;
|
||||
}
|
||||
|
||||
void Envelope :: keyOff()
|
||||
{
|
||||
target = 0.0;
|
||||
if (value != target) state = 1;
|
||||
}
|
||||
|
||||
void Envelope :: setRate(MY_FLOAT aRate)
|
||||
{
|
||||
if (aRate < 0.0) {
|
||||
printf("negative rates not allowed!!, correcting\n");
|
||||
rate = -aRate;
|
||||
}
|
||||
else rate = aRate;
|
||||
rate = rate * RATE_NORM; /* SEE Object.h */
|
||||
}
|
||||
|
||||
void Envelope :: setTarget(MY_FLOAT aTarget)
|
||||
{
|
||||
target = aTarget;
|
||||
if (value != target) state = 1;
|
||||
}
|
||||
|
||||
void Envelope :: setValue(MY_FLOAT aValue)
|
||||
{
|
||||
state = 0;
|
||||
target = aValue;
|
||||
value = aValue;
|
||||
}
|
||||
|
||||
MY_FLOAT Envelope :: tick()
|
||||
{
|
||||
if (state) {
|
||||
if (target > value) {
|
||||
value += rate;
|
||||
if (value >= target) {
|
||||
value = target;
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
value -= rate;
|
||||
if (value <= target) {
|
||||
value = target;
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int Envelope :: informTick()
|
||||
{
|
||||
this->tick();
|
||||
return state;
|
||||
}
|
||||
|
||||
MY_FLOAT Envelope :: lastOut()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/************ Test Main ************************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
long i;
|
||||
Envelope test;
|
||||
|
||||
test.setRate(0.15);
|
||||
test.keyOn();
|
||||
for (i=0;i<10;i++) printf("%lf\n",test.tick());
|
||||
test.setRate(0.1);
|
||||
test.setTarget(0.5);
|
||||
while (test.informTick()) printf("%lf\n",test.lastOut());
|
||||
test.setRate(0.05);
|
||||
test.keyOff();
|
||||
while(test.informTick()) printf("%lf\n",test.lastOut());
|
||||
}
|
||||
*/
|
||||
40
Envelope.h
40
Envelope.h
@@ -1,40 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Envelope Class, Perry R. Cook, 1995-96 */
|
||||
/* This is the base class for envelopes. */
|
||||
/* This one is capable of ramping state */
|
||||
/* from where it is to a target value by */
|
||||
/* a rate. It also responds to simple */
|
||||
/* KeyOn and KeyOff messages, ramping to */
|
||||
/* 1.0 on keyon and to 0.0 on keyoff. */
|
||||
/* There are two tick (update value) */
|
||||
/* methods, one returns the value, and */
|
||||
/* other returns 0 if the envelope is at */
|
||||
/* the target value (the state bit). */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Envelope_h)
|
||||
#define __Envelope_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class Envelope : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT value;
|
||||
MY_FLOAT target;
|
||||
MY_FLOAT rate;
|
||||
int state;
|
||||
public:
|
||||
Envelope();
|
||||
~Envelope();
|
||||
void keyOn();
|
||||
void keyOff();
|
||||
void setRate(MY_FLOAT aRate);
|
||||
void setTarget(MY_FLOAT aTarget);
|
||||
void setValue(MY_FLOAT aValue);
|
||||
MY_FLOAT tick();
|
||||
int informTick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
51
FM4Alg3.cpp
51
FM4Alg3.cpp
@@ -1,51 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 3 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Alg 3 is : 4--\ */
|
||||
/* 3-->2-- + -->1-->Out */
|
||||
/* */
|
||||
/* Controls: control1 = total mod index */
|
||||
/* control2 = crossfade of two */
|
||||
/* modulators */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "FM4Alg3.h"
|
||||
|
||||
FM4Alg3 :: FM4Alg3() : FM4Op()
|
||||
{
|
||||
/* We still don't make the waves here yet, because */
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
MY_FLOAT FM4Alg3 :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
|
||||
temp = vibWave->tick() * modDepth * 0.2;
|
||||
waves[0]->setFreq(baseFreq * (1.0 + temp) * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * (1.0 + temp) * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * (1.0 + temp) * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * (1.0 + temp) * ratios[3]);
|
||||
|
||||
temp = gains[2] * adsr[2]->tick() * waves[2]->tick();
|
||||
waves[1]->addPhaseOffset(temp);
|
||||
|
||||
waves[3]->addPhaseOffset(twozero->lastOut());
|
||||
temp = (1.0 - (control2 * 0.5)) * gains[3] * adsr[3]->tick() * waves[3]->tick();
|
||||
twozero->tick(temp);
|
||||
|
||||
temp += control2 * 0.5 * gains[1] * adsr[1]->tick() * waves[1]->tick();
|
||||
temp = temp * control1;
|
||||
|
||||
waves[0]->addPhaseOffset(temp);
|
||||
temp = gains[0] * adsr[0]->tick() * waves[0]->tick();
|
||||
|
||||
lastOutput = temp * 0.5;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
29
FM4Alg3.h
29
FM4Alg3.h
@@ -1,29 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 3 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Alg 3 is : 4--\ */
|
||||
/* 3-->2-- + -->1-->Out */
|
||||
/* */
|
||||
/* Controls: control1 = total mod index */
|
||||
/* control2 = crossfade of two */
|
||||
/* modulators */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__FM4Alg3_h)
|
||||
#define __FM4Alg3_h
|
||||
|
||||
#include "FM4Op.h"
|
||||
|
||||
class FM4Alg3 : public FM4Op
|
||||
{
|
||||
public:
|
||||
FM4Alg3();
|
||||
MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
48
FM4Alg4.cpp
48
FM4Alg4.cpp
@@ -1,48 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 4 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Alg 4 is : 4->3--\ */
|
||||
/* 2-- + -->1-->Out */
|
||||
/* */
|
||||
/* Controls: control1 = total mod index */
|
||||
/* control2 = crossfade of two */
|
||||
/* modulators */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "FM4Alg4.h"
|
||||
|
||||
FM4Alg4 :: FM4Alg4() : FM4Op()
|
||||
{
|
||||
/* We still don't make the waves here yet, because */
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
MY_FLOAT FM4Alg4 :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
|
||||
temp = vibWave->tick() * modDepth * 0.2;
|
||||
waves[0]->setFreq(baseFreq * (1.0 + temp) * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * (1.0 + temp) * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * (1.0 + temp) * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * (1.0 + temp) * ratios[3]);
|
||||
|
||||
waves[3]->addPhaseOffset(twozero->lastOut());
|
||||
temp = gains[3] * adsr[3]->tick() * waves[3]->tick();
|
||||
twozero->tick(temp);
|
||||
waves[2]->addPhaseOffset(temp);
|
||||
temp = (1.0 - (control2 * 0.5)) * gains[2] * adsr[2]->tick() * waves[2]->tick();
|
||||
temp += control2 * 0.5 * gains[1] * adsr[1]->tick() * waves[1]->tick();
|
||||
temp = temp * control1;
|
||||
waves[0]->addPhaseOffset(temp);
|
||||
temp = gains[0] * adsr[0]->tick() * waves[0]->tick();
|
||||
|
||||
lastOutput = temp * 0.5;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
29
FM4Alg4.h
29
FM4Alg4.h
@@ -1,29 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 4 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Alg 4 is : 4->3--\ */
|
||||
/* 2-- + -->1-->Out */
|
||||
/* */
|
||||
/* Controls: control1 = total mod index */
|
||||
/* control2 = crossfade of two */
|
||||
/* modulators */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__FM4Alg4_h)
|
||||
#define __FM4Alg4_h
|
||||
|
||||
#include "FM4Op.h"
|
||||
|
||||
class FM4Alg4 : public FM4Op
|
||||
{
|
||||
public:
|
||||
FM4Alg4();
|
||||
MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
48
FM4Alg5.cpp
48
FM4Alg5.cpp
@@ -1,48 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 5 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This connection topology is 2 simple */
|
||||
/* FM Pairs summed together, like: */
|
||||
/* */
|
||||
/* Alg 5 is : 4->3--\ */
|
||||
/* + --> Out */
|
||||
/* 2->1--/ */
|
||||
/* */
|
||||
/* Controls: control1 = mod index 1 */
|
||||
/* control2 = crossfade of two */
|
||||
/* outputs */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "FM4Alg5.h"
|
||||
|
||||
FM4Alg5 :: FM4Alg5() : FM4Op()
|
||||
{
|
||||
/* We still don't make the waves here yet, because */
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
MY_FLOAT FM4Alg5 :: tick()
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
|
||||
temp = gains[1] * adsr[1]->tick() * waves[1]->tick();
|
||||
temp = temp * control1;
|
||||
waves[0]->addPhaseOffset(temp);
|
||||
waves[3]->addPhaseOffset(twozero->lastOut());
|
||||
temp = gains[3] * adsr[3]->tick() * waves[3]->tick();
|
||||
twozero->tick(temp);
|
||||
waves[2]->addPhaseOffset(temp);
|
||||
temp = (1.0 - (control2 * 0.5)) * gains[0] * adsr[0]->tick() * waves[0]->tick();
|
||||
temp += control2 * 0.5 * gains[2] * adsr[2]->tick() * waves[2]->tick();
|
||||
|
||||
temp2 = vibWave->tick() * modDepth; /* Calculate amplitude mod */
|
||||
temp = temp * (1.0 + temp2); /* and apply it to output */
|
||||
|
||||
lastOutput = temp * 0.5;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
32
FM4Alg5.h
32
FM4Alg5.h
@@ -1,32 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 5 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This connection topology is 2 simple */
|
||||
/* FM Pairs summed together, like: */
|
||||
/* */
|
||||
/* 1 -> 2 -\ */
|
||||
/* +-> Out */
|
||||
/* 3 -> 4 -/ */
|
||||
/* */
|
||||
/* Controls: control1 = mod index 1 */
|
||||
/* control2 = crossfade of two */
|
||||
/* outputs */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__FM4Alg5_h)
|
||||
#define __FM4Alg5_h
|
||||
|
||||
#include "FM4Op.h"
|
||||
|
||||
class FM4Alg5 : public FM4Op
|
||||
{
|
||||
public:
|
||||
FM4Alg5();
|
||||
MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
54
FM4Alg6.cpp
54
FM4Alg6.cpp
@@ -1,54 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 6 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This connection topology is three */
|
||||
/* Carriers and a common Modulator */
|
||||
/* */
|
||||
/* /->1 -\ */
|
||||
/* 4-|-->2 - +-> Out */
|
||||
/* \->3 -/ */
|
||||
/* */
|
||||
/* Controls: control1 = vowel */
|
||||
/* control2 = spectral tilt */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "FM4Alg6.h"
|
||||
|
||||
FM4Alg6 :: FM4Alg6() : FM4Op()
|
||||
{
|
||||
/* We still don't make the waves here yet, because */
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
MY_FLOAT FM4Alg6 :: tick()
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
|
||||
temp = gains[3] * adsr[3]->tick() * waves[3]->tick();
|
||||
temp2 = vibWave->tick() * modDepth * 0.1; /* Calculate frequency mod */
|
||||
|
||||
waves[0]->setFreq(baseFreq * (1.0 + temp2) * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * (1.0 + temp2) * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * (1.0 + temp2) * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * (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;
|
||||
}
|
||||
|
||||
void FM4Alg6 :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
|
||||
}
|
||||
35
FM4Alg6.h
35
FM4Alg6.h
@@ -1,35 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 6 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This connection topology is three */
|
||||
/* Carriers and a common Modulator */
|
||||
/* */
|
||||
/* /->1 -\ */
|
||||
/* 4-|-->2 - +-> Out */
|
||||
/* \->3 -/ */
|
||||
/* */
|
||||
/* Controls: control1 = vowel */
|
||||
/* control2 = spectral tilt */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__FM4Alg6_h)
|
||||
#define __FM4Alg6_h
|
||||
|
||||
#include "FM4Op.h"
|
||||
|
||||
class FM4Alg6 : public FM4Op
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT tilt[3];
|
||||
MY_FLOAT mods[3];
|
||||
public:
|
||||
FM4Alg6();
|
||||
MY_FLOAT tick();
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
43
FM4Alg8.cpp
43
FM4Alg8.cpp
@@ -1,43 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 8 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This connection topology is simple */
|
||||
/* Additive Synthesis, like: */
|
||||
/* */
|
||||
/* 1 --. */
|
||||
/* 2 -\| */
|
||||
/* +-> Out */
|
||||
/* 3 -/| */
|
||||
/* 4 -- */
|
||||
/* */
|
||||
/* Controls: control1 = op4 (fb) gain */
|
||||
/* control2 = op3 gain */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "FM4Alg8.h"
|
||||
|
||||
FM4Alg8 :: FM4Alg8() : FM4Op()
|
||||
{
|
||||
/* We still don't make the waves here yet, because */
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
MY_FLOAT FM4Alg8 :: tick()
|
||||
{
|
||||
MY_FLOAT 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();
|
||||
|
||||
lastOutput = temp * 0.125;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
33
FM4Alg8.h
33
FM4Alg8.h
@@ -1,33 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 8 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This connection topology is simple */
|
||||
/* Additive Synthesis, like: */
|
||||
/* */
|
||||
/* 1 --. */
|
||||
/* 2 -\| */
|
||||
/* +-> Out */
|
||||
/* 3 -/| */
|
||||
/* 4 -- */
|
||||
/* */
|
||||
/* Controls: control1 = op4 (fb) gain */
|
||||
/* control2 = op3 gain */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__FM4Alg8_h)
|
||||
#define __FM4Alg8_h
|
||||
|
||||
#include "FM4Op.h"
|
||||
|
||||
class FM4Alg8 : public FM4Op
|
||||
{
|
||||
public:
|
||||
FM4Alg8();
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
179
FM4Op.cpp
179
FM4Op.cpp
@@ -1,179 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Master Class for 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains 4 waves, */
|
||||
/* 4 adsr, and various state vars. */
|
||||
/* */
|
||||
/* The basic Chowning/Stanford FM patent */
|
||||
/* expired April 1995, but there exist */
|
||||
/* follow-on patents, mostly assigned to */
|
||||
/* Yamaha. If you are of the type who */
|
||||
/* should worry about this (making money) */
|
||||
/* worry away. */
|
||||
/* */
|
||||
/*******************************************/
|
||||
|
||||
#include "FM4Op.h"
|
||||
|
||||
FM4Op :: FM4Op()
|
||||
{
|
||||
int i;
|
||||
MY_FLOAT temp;
|
||||
MY_FLOAT tempCoeffs[2] = {0.0, -1.0};
|
||||
adsr[0] = new ADSR;
|
||||
adsr[1] = new ADSR;
|
||||
adsr[2] = new ADSR;
|
||||
adsr[3] = new ADSR;
|
||||
twozero = new TwoZero;
|
||||
vibWave = new RawLoop("rawwaves/sinewave.raw");
|
||||
vibWave->normalize();
|
||||
vibWave->setFreq(6.0); /* should make this random?? */
|
||||
modDepth = 0.0;
|
||||
/* We don't make the waves here yet, because */
|
||||
/* we don't know what they will be. */
|
||||
baseFreq = 440.0;
|
||||
ratios[0] = 1.0;
|
||||
ratios[1] = 1.0;
|
||||
ratios[2] = 1.0;
|
||||
ratios[3] = 1.0;
|
||||
gains[0] = 1.0;
|
||||
gains[1] = 1.0;
|
||||
gains[2] = 1.0;
|
||||
gains[3] = 1.0;
|
||||
twozero->setZeroCoeffs(tempCoeffs);
|
||||
twozero->setGain(0.0);
|
||||
control1 = 1.0;
|
||||
control2 = 1.0;
|
||||
temp = 1.0;
|
||||
for (i=99;i>=0;i--) {
|
||||
__FM4Op_gains[i] = temp;
|
||||
temp *= 0.933033;
|
||||
}
|
||||
temp = 1.0;
|
||||
for (i=15;i>=0;i--) {
|
||||
__FM4Op_susLevels[i] = temp;
|
||||
temp *= 0.707101;
|
||||
}
|
||||
temp = 8.498186;
|
||||
for (i=0;i<32;i++) {
|
||||
__FM4Op_attTimes[i] = temp;
|
||||
temp *= 0.707101;
|
||||
}
|
||||
}
|
||||
|
||||
FM4Op :: ~FM4Op()
|
||||
{
|
||||
delete adsr[0];
|
||||
delete adsr[1];
|
||||
delete adsr[2];
|
||||
delete adsr[3];
|
||||
delete waves[0];
|
||||
delete waves[1];
|
||||
delete waves[2];
|
||||
delete waves[3];
|
||||
delete vibWave;
|
||||
delete twozero;
|
||||
}
|
||||
|
||||
void FM4Op :: loadWaves(char* wave1, char* wave2, char* wave3, char* wave4)
|
||||
{
|
||||
int i;
|
||||
waves[0] = new RawLoop(wave1);
|
||||
waves[1] = new RawLoop(wave2);
|
||||
waves[2] = new RawLoop(wave3);
|
||||
waves[3] = new RawLoop(wave4);
|
||||
for (i=0;i<4;i++) {
|
||||
waves[i]->normalize();
|
||||
}
|
||||
}
|
||||
void FM4Op :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
waves[0]->setFreq(baseFreq * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * ratios[3]);
|
||||
}
|
||||
|
||||
void FM4Op :: setRatio(int whichOne, MY_FLOAT ratio)
|
||||
{
|
||||
ratios[whichOne] = ratio;
|
||||
if (ratio>0.0)
|
||||
waves[whichOne]->setFreq(baseFreq * ratio);
|
||||
else
|
||||
waves[whichOne]->setFreq(ratio);
|
||||
}
|
||||
|
||||
void FM4Op :: setGain(int whichOne, MY_FLOAT gain)
|
||||
{
|
||||
gains[whichOne]=gain;
|
||||
}
|
||||
|
||||
void FM4Op :: keyOn()
|
||||
{
|
||||
adsr[0]->keyOn();
|
||||
adsr[1]->keyOn();
|
||||
adsr[2]->keyOn();
|
||||
adsr[3]->keyOn();
|
||||
}
|
||||
|
||||
void FM4Op :: keyOff()
|
||||
{
|
||||
adsr[0]->keyOff();
|
||||
adsr[1]->keyOff();
|
||||
adsr[2]->keyOff();
|
||||
adsr[3]->keyOff();
|
||||
}
|
||||
|
||||
void FM4Op :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->keyOff();
|
||||
#if defined(_debug_)
|
||||
printf("FM4Op : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FM4Op :: setModulationSpeed(MY_FLOAT mSpeed)
|
||||
{
|
||||
vibWave->setFreq(mSpeed);
|
||||
}
|
||||
|
||||
void FM4Op :: setModulationDepth(MY_FLOAT mDepth)
|
||||
{
|
||||
modDepth = mDepth;
|
||||
}
|
||||
|
||||
void FM4Op :: setControl1(MY_FLOAT cVal)
|
||||
{
|
||||
control1 = cVal*2.0;
|
||||
}
|
||||
|
||||
void FM4Op :: setControl2(MY_FLOAT cVal)
|
||||
{
|
||||
control2 = cVal*2.0;
|
||||
}
|
||||
|
||||
void FM4Op :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("FM4Op : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == MIDI_control1)
|
||||
this->setControl1(value * NORM_7);
|
||||
else if (number == MIDI_control2)
|
||||
this->setControl2(value * NORM_7);
|
||||
else if (number == MIDI_control3)
|
||||
this->setModulationSpeed(value * NORM_7 * 12.0); /* 0 to 12 Hz */
|
||||
else if (number == MIDI_mod_wheel)
|
||||
this->setModulationDepth(value * NORM_7);
|
||||
else if (number == MIDI_after_touch) {
|
||||
adsr[0]->setTarget(value * NORM_7);
|
||||
adsr[1]->setTarget(value * NORM_7);
|
||||
adsr[2]->setTarget(value * NORM_7);
|
||||
adsr[3]->setTarget(value * NORM_7);
|
||||
}
|
||||
else {
|
||||
printf("FM4Op : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
59
FM4Op.h
59
FM4Op.h
@@ -1,59 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Master Class for 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains an 4 waves, */
|
||||
/* 4 envelopes, and various state vars. */
|
||||
/* */
|
||||
/* The basic Chowning/Stanford FM patent */
|
||||
/* expired April 1995, but there exist */
|
||||
/* follow-on patents, mostly assigned to */
|
||||
/* Yamaha. If you are of the type who */
|
||||
/* should worry about this (making money) */
|
||||
/* worry away. */
|
||||
/* */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__FM4Op_h)
|
||||
#define __FM4Op_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "ADSR.h"
|
||||
#include "RawLoop.h"
|
||||
#include "TwoZero.h"
|
||||
|
||||
class FM4Op : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
ADSR *adsr[4];
|
||||
RawLoop *waves[4];
|
||||
RawLoop *vibWave;
|
||||
TwoZero *twozero;
|
||||
MY_FLOAT baseFreq;
|
||||
MY_FLOAT ratios[4];
|
||||
MY_FLOAT gains[4];
|
||||
MY_FLOAT modDepth;
|
||||
MY_FLOAT control1;
|
||||
MY_FLOAT control2;
|
||||
MY_FLOAT __FM4Op_gains[100];
|
||||
MY_FLOAT __FM4Op_susLevels[16];
|
||||
MY_FLOAT __FM4Op_attTimes[32];
|
||||
public:
|
||||
FM4Op();
|
||||
~FM4Op();
|
||||
void loadWaves(char* wave1, char* wave2, char* wave3, char* wave4);
|
||||
void clear();
|
||||
void setFreq(MY_FLOAT frequency);
|
||||
void setRatio(int whichOne, MY_FLOAT ratio);
|
||||
void setGain(int whichOne, MY_FLOAT gain);
|
||||
void keyOn();
|
||||
void keyOff();
|
||||
void noteOff(MY_FLOAT amp);
|
||||
/* There's no tick() method here, because that depends on the algorithm */
|
||||
void setModulationSpeed(MY_FLOAT mSpeed);
|
||||
void setModulationDepth(MY_FLOAT mDepth);
|
||||
void setControl1(MY_FLOAT cVal);
|
||||
void setControl2(MY_FLOAT cVal);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
118
FMVoices.cpp
118
FMVoices.cpp
@@ -1,118 +0,0 @@
|
||||
/******************************************/
|
||||
/* Singing Voice Synthesis Subclass */
|
||||
/* of Algorithm 6 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1996 */
|
||||
/******************************************/
|
||||
|
||||
#include "FMVoices.h"
|
||||
|
||||
FMVoices :: FMVoices() : FM4Alg6()
|
||||
{
|
||||
this->loadWaves("rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw");
|
||||
|
||||
this->setRatio(0,2.00);
|
||||
this->setRatio(1,4.00);
|
||||
this->setRatio(2,12.0);
|
||||
this->setRatio(3,1.00);
|
||||
gains[3] = __FM4Op_gains[80];
|
||||
adsr[0]->setAll(0.001,0.001,__FM4Op_susLevels[15],0.001);
|
||||
adsr[1]->setAll(0.001,0.001,__FM4Op_susLevels[15],0.001);
|
||||
adsr[2]->setAll(0.001,0.001,__FM4Op_susLevels[15],0.001);
|
||||
adsr[3]->setAll(0.05,0.05,__FM4Op_susLevels[15],0.0001);
|
||||
twozero->setGain(0.0);
|
||||
modDepth = 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;
|
||||
baseFreq = 110.0;
|
||||
this->setFreq(110.0);
|
||||
}
|
||||
|
||||
#include "phonTabl.h"
|
||||
|
||||
void FMVoices :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
int tempi,tempi2;
|
||||
|
||||
if (currentVowel < 16) {
|
||||
tempi2 = currentVowel;
|
||||
temp2 = 0.9;
|
||||
}
|
||||
else if (currentVowel < 32) {
|
||||
tempi2 = currentVowel - 16;
|
||||
temp2 = 1.0;
|
||||
}
|
||||
else if (currentVowel < 48) {
|
||||
tempi2 = currentVowel - 32;
|
||||
temp2 = 1.1;
|
||||
}
|
||||
else if (currentVowel < 64) {
|
||||
tempi2 = currentVowel - 48;
|
||||
temp2 = 1.2;
|
||||
}
|
||||
baseFreq = frequency;
|
||||
temp = (temp2 * phonParams[tempi2][0][0] / baseFreq) + 0.5;
|
||||
tempi = (int) temp;
|
||||
this->setRatio(0,(MY_FLOAT) tempi);
|
||||
temp = (temp2 * phonParams[tempi2][1][0] / baseFreq) + 0.5;
|
||||
tempi = (int) temp;
|
||||
this->setRatio(1,(MY_FLOAT) tempi);
|
||||
temp = (temp2 * phonParams[tempi2][2][0] / baseFreq) + 0.5;
|
||||
tempi = (int) temp;
|
||||
this->setRatio(2,(MY_FLOAT) tempi);
|
||||
gains[0] = 1.0; // pow(10.0,phonParams[tempi2][0][2] * 0.05);
|
||||
gains[1] = 1.0; // pow(10.0,phonParams[tempi2][1][2] * 0.05);
|
||||
gains[2] = 1.0; // pow(10.0,phonParams[tempi2][2][2] * 0.05);
|
||||
}
|
||||
|
||||
void FMVoices :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
tilt[0] = amp;
|
||||
tilt[1] = amp * amp;
|
||||
tilt[2] = amp * amp * amp;
|
||||
this->keyOn();
|
||||
#if defined(_debug_)
|
||||
printf("FMVoices : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FMVoices :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
int tempi;
|
||||
|
||||
#if defined(_debug_)
|
||||
printf("FM4Op : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == MIDI_control1)
|
||||
gains[3] = __FM4Op_gains[(int) (value * 0.78125)];
|
||||
else if (number == MIDI_control2) {
|
||||
tempi = (int) (value / 2);
|
||||
currentVowel = tempi;
|
||||
this->setFreq(baseFreq);
|
||||
}
|
||||
else if (number == MIDI_control3)
|
||||
this->setModulationSpeed(value * NORM_7 * 12.0); /* 0 to 12 Hz */
|
||||
else if (number == MIDI_mod_wheel)
|
||||
this->setModulationDepth(value * NORM_7);
|
||||
else if (number == MIDI_after_touch) {
|
||||
temp = value * NORM_7;
|
||||
tilt[0] = temp;
|
||||
tilt[1] = temp * temp;
|
||||
tilt[2] = temp * temp * temp;
|
||||
}
|
||||
else {
|
||||
printf("FM4Op : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
24
FMVoices.h
24
FMVoices.h
@@ -1,24 +0,0 @@
|
||||
/******************************************/
|
||||
/* Singing Voice Synthesis Subclass */
|
||||
/* of Algorithm 6 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1996 */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__FMVoices_h)
|
||||
#define __FMVoices_h
|
||||
|
||||
#include "FM4Alg6.h"
|
||||
|
||||
class FMVoices : public FM4Alg6
|
||||
{
|
||||
protected:
|
||||
int currentVowel;
|
||||
public:
|
||||
FMVoices();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
24
Filter.cpp
24
Filter.cpp
@@ -1,24 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Filter Class, by Perry R. Cook, 1995-96*/
|
||||
/* This is the base class for all filters.*/
|
||||
/* To me, most anything is a filter, but */
|
||||
/* I'll be a little less general here, and*/
|
||||
/* define a filter as something which has */
|
||||
/* input(s), output(s), and gain. */
|
||||
/*******************************************/
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
Filter :: Filter() : Object()
|
||||
{
|
||||
}
|
||||
|
||||
Filter :: ~Filter()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT Filter :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
28
Filter.h
28
Filter.h
@@ -1,28 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Filter Class, by Perry R. Cook, 1995-96*/
|
||||
/* This is the base class for all filters.*/
|
||||
/* To me, most anything is a filter, but */
|
||||
/* I'll be a little less general here, and*/
|
||||
/* define a filter as something which has */
|
||||
/* input(s), output(s), and gain. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Filter_h)
|
||||
#define __Filter_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class Filter : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT gain;
|
||||
MY_FLOAT *outputs;
|
||||
MY_FLOAT *inputs;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Filter();
|
||||
~Filter();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
172
Flute.cpp
172
Flute.cpp
@@ -1,172 +0,0 @@
|
||||
/******************************************/
|
||||
/* WaveGuide Flute ala Karjalainen, */
|
||||
/* Smith, Waryznyk, etc. */
|
||||
/* with polynomial Jet ala Cook */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = jetDelay */
|
||||
/* CONTROL2 = noiseGain */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#include "Flute.h"
|
||||
|
||||
Flute :: Flute(MY_FLOAT lowestFreq)
|
||||
{
|
||||
long length;
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
boreDelay = new DLineL(length);
|
||||
length >> 1;
|
||||
jetDelay = new DLineL(length);
|
||||
jetTable = new JetTabl;
|
||||
filter = new OnePole;
|
||||
dcBlock = new DCBlock;
|
||||
noise = new Noise;
|
||||
adsr = new ADSR;
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
this->clear();
|
||||
|
||||
boreDelay->setDelay(100.0);
|
||||
jetDelay->setDelay(49.0);
|
||||
|
||||
filter->setPole(0.7 - (0.1 * RATE_NORM));
|
||||
filter->setGain(-1.0);
|
||||
vibr->normalize();
|
||||
vibr->setFreq(5.925);
|
||||
adsr->setAll(0.02, 0.05, 0.8, 0.001);
|
||||
endRefl = 0.5;
|
||||
jetRefl = 0.5;
|
||||
noiseGain = 0.15; /* Breath pressure random component */
|
||||
vibrGain = 0.05; /* breath periodic vibrato component */
|
||||
jetRatio = 0.32;
|
||||
}
|
||||
|
||||
Flute :: ~Flute()
|
||||
{
|
||||
delete jetDelay;
|
||||
delete boreDelay;
|
||||
delete jetTable;
|
||||
delete filter;
|
||||
delete dcBlock;
|
||||
delete noise;
|
||||
delete adsr;
|
||||
delete vibr;
|
||||
}
|
||||
|
||||
void Flute :: clear()
|
||||
{
|
||||
jetDelay->clear();
|
||||
boreDelay->clear();
|
||||
filter->clear();
|
||||
dcBlock->clear();
|
||||
/* adsr->reset(); */
|
||||
}
|
||||
|
||||
void Flute :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
lastFreq = frequency * 0.66666; /* we're overblowing here */
|
||||
temp = SRATE / lastFreq - 2.0; /* Length - approx. filter delay */
|
||||
boreDelay->setDelay(temp); /* Length of bore tube */
|
||||
jetDelay->setDelay(temp * jetRatio); /* jet delay shorter */
|
||||
}
|
||||
|
||||
void Flute :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate)
|
||||
{
|
||||
adsr->setAttackRate(rate);
|
||||
maxPressure = amplitude / 0.8;
|
||||
adsr->keyOn();
|
||||
}
|
||||
|
||||
void Flute :: stopBlowing(MY_FLOAT rate)
|
||||
{
|
||||
adsr->setReleaseRate(rate);
|
||||
adsr->keyOff();
|
||||
}
|
||||
|
||||
void Flute :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
this->startBlowing(1.1 + (amp * 0.20),amp * 0.02);
|
||||
outputGain = amp + 0.001;
|
||||
#if defined(_debug_)
|
||||
printf("Flute : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Flute :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->stopBlowing(amp * 0.02);
|
||||
#if defined(_debug_)
|
||||
printf("Flute : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Flute :: setJetRefl(MY_FLOAT refl)
|
||||
{
|
||||
jetRefl = refl;
|
||||
}
|
||||
|
||||
void Flute :: setEndRefl(MY_FLOAT refl)
|
||||
{
|
||||
endRefl = refl;
|
||||
}
|
||||
|
||||
void Flute :: setJetDelay(MY_FLOAT aRatio)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
temp = SRATE / lastFreq - 2.0; /* Length - approx. filter delay */
|
||||
jetRatio = aRatio;
|
||||
jetDelay->setDelay(temp * aRatio); /* Scaled by ratio */
|
||||
}
|
||||
|
||||
MY_FLOAT Flute :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
MY_FLOAT pressureDiff;
|
||||
MY_FLOAT randPressure;
|
||||
MY_FLOAT breathPressure;
|
||||
|
||||
breathPressure = maxPressure * adsr->tick(); /* Breath Pressure */
|
||||
randPressure = noiseGain * noise->tick(); /* Random Deviation */
|
||||
randPressure += vibrGain * vibr->tick(); /* + breath vibrato */
|
||||
randPressure *= breathPressure; /* All scaled by Breath Pressure */
|
||||
|
||||
temp = filter->tick(boreDelay->lastOut());
|
||||
temp = dcBlock->tick(temp); /* Block DC on reflection */
|
||||
pressureDiff = breathPressure + randPressure - /* Breath Pressure */
|
||||
(jetRefl * temp); /* - reflected */
|
||||
pressureDiff = jetDelay->tick(pressureDiff); /* Jet Delay Line */
|
||||
pressureDiff = jetTable->lookup(pressureDiff) /* Non-Lin Jet + reflected */
|
||||
+ (endRefl * temp);
|
||||
lastOutput = 0.3 * boreDelay->tick(pressureDiff); /* Bore Delay and "bell" filter */
|
||||
|
||||
lastOutput *= outputGain;
|
||||
return lastOutput;
|
||||
|
||||
}
|
||||
|
||||
void Flute :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("Flute : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == MIDI_control1)
|
||||
this->setJetDelay(0.08 + (0.48 * value * NORM_7));
|
||||
else if (number == MIDI_control2)
|
||||
noiseGain = (value * NORM_7 * 0.4);
|
||||
else if (number == MIDI_control3)
|
||||
vibr->setFreq((value * NORM_7 * 12.0));
|
||||
else if (number == MIDI_mod_wheel)
|
||||
vibrGain = (value * NORM_7 * 0.4);
|
||||
else if (number == MIDI_after_touch)
|
||||
adsr->setTarget(value * NORM_7);
|
||||
else {
|
||||
printf("Flute : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
64
Flute.h
64
Flute.h
@@ -1,64 +0,0 @@
|
||||
/******************************************/
|
||||
/* WaveGuide Flute ala Karjalainen, */
|
||||
/* Smith, Waryznyk, etc. */
|
||||
/* with polynomial Jet ala Cook */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = jetDelay */
|
||||
/* CONTROL2 = noiseGain */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Flute_h)
|
||||
#define __Flute_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "JetTabl.h"
|
||||
#include "DLineL.h"
|
||||
#include "OnePole.h"
|
||||
#include "DCBlock.h"
|
||||
#include "Noise.h"
|
||||
#include "ADSR.h"
|
||||
#include "RawLoop.h"
|
||||
|
||||
class Flute : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
DLineL *jetDelay;
|
||||
DLineL *boreDelay;
|
||||
JetTabl *jetTable;
|
||||
OnePole *filter;
|
||||
DCBlock *dcBlock;
|
||||
Noise *noise;
|
||||
ADSR *adsr;
|
||||
RawLoop *vibr;
|
||||
MY_FLOAT lastFreq;
|
||||
MY_FLOAT maxPressure;
|
||||
MY_FLOAT jetRefl;
|
||||
MY_FLOAT endRefl;
|
||||
MY_FLOAT noiseGain;
|
||||
MY_FLOAT vibrGain;
|
||||
MY_FLOAT outputGain;
|
||||
MY_FLOAT jetRatio;
|
||||
public:
|
||||
Flute(MY_FLOAT lowestFreq);
|
||||
~Flute();
|
||||
void clear();
|
||||
void startBlowing(MY_FLOAT amplitude,MY_FLOAT rate);
|
||||
void stopBlowing(MY_FLOAT rate);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
void setJetRefl(MY_FLOAT refl);
|
||||
void setEndRefl(MY_FLOAT refl);
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual MY_FLOAT tick();
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
void setJetDelay(MY_FLOAT aLength);
|
||||
};
|
||||
|
||||
#endif
|
||||
170
FormSwep.cpp
170
FormSwep.cpp
@@ -1,170 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Sweepable Formant (2-pole) */
|
||||
/* Filter Class, by Perry R. Cook, 1995-96*/
|
||||
/* See books on filters to understand */
|
||||
/* more about how this works. This drives*/
|
||||
/* to a target at speed set by rate. */
|
||||
/*******************************************/
|
||||
|
||||
#include "FormSwep.h"
|
||||
|
||||
FormSwep :: FormSwep() : Filter()
|
||||
{
|
||||
outputs = (MY_FLOAT *) malloc(2 * MY_FLOAT_SIZE);
|
||||
poleCoeffs[0] = 0.0;
|
||||
poleCoeffs[1] = 0.0;
|
||||
gain = 1.0;
|
||||
freq = 0.0;
|
||||
reson = 0.0;
|
||||
currentGain = 1.0;
|
||||
currentFreq = 0.0;
|
||||
currentReson = 0.0;
|
||||
targetGain = 1.0;
|
||||
targetFreq = 0.0;
|
||||
targetReson = 0.0;
|
||||
deltaGain = 0.0;
|
||||
deltaFreq = 0.0;
|
||||
deltaReson = 0.0;
|
||||
sweepState = 0;
|
||||
sweepRate = 0.002;
|
||||
dirty = 0;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
FormSwep :: ~FormSwep()
|
||||
{
|
||||
free(outputs);
|
||||
}
|
||||
|
||||
void FormSwep :: clear()
|
||||
{
|
||||
outputs[0] = 0.0;
|
||||
outputs[1] = 0.0;
|
||||
}
|
||||
|
||||
void FormSwep :: setPoleCoeffs(MY_FLOAT *coeffs)
|
||||
{
|
||||
dirty = 0;
|
||||
poleCoeffs[0] = coeffs[0];
|
||||
poleCoeffs[1] = coeffs[1];
|
||||
}
|
||||
|
||||
void FormSwep :: setFreqAndReson(MY_FLOAT aFreq, MY_FLOAT aReson)
|
||||
{
|
||||
dirty = 0;
|
||||
reson = aReson;
|
||||
freq = aFreq;
|
||||
currentReson = aReson;
|
||||
currentFreq = aFreq;
|
||||
poleCoeffs[1] = - (reson * reson);
|
||||
poleCoeffs[0] = 2.0 * reson * cos(TWO_PI * freq / SRATE);
|
||||
}
|
||||
|
||||
void FormSwep :: setStates(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain)
|
||||
{
|
||||
dirty = 0;
|
||||
freq = aFreq;
|
||||
reson = aReson;
|
||||
gain = aGain;
|
||||
targetFreq = aFreq;
|
||||
targetReson = aReson;
|
||||
targetGain = aGain;
|
||||
currentFreq = aFreq;
|
||||
currentReson = aReson;
|
||||
currentGain = aGain;
|
||||
}
|
||||
|
||||
void FormSwep :: setTargets(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain)
|
||||
{
|
||||
dirty = 1;
|
||||
targetFreq = aFreq;
|
||||
targetReson = aReson;
|
||||
targetGain = aGain;
|
||||
deltaFreq = aFreq - currentFreq;
|
||||
deltaReson = aReson - currentReson;
|
||||
deltaGain = aGain - currentGain;
|
||||
sweepState = 0.0;
|
||||
}
|
||||
|
||||
void FormSwep :: setSweepRate(MY_FLOAT aRate)
|
||||
{
|
||||
sweepRate = aRate;
|
||||
}
|
||||
|
||||
void FormSwep :: setGain(MY_FLOAT aValue)
|
||||
{
|
||||
gain = aValue;
|
||||
}
|
||||
|
||||
MY_FLOAT FormSwep :: tick(MY_FLOAT sample) /* Perform Filter Operation */
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
|
||||
if (dirty) {
|
||||
sweepState += sweepRate;
|
||||
if (sweepState>= 1.0) {
|
||||
sweepState = 1.0;
|
||||
dirty = 0;
|
||||
currentReson = targetReson;
|
||||
reson = targetReson;
|
||||
currentFreq = targetFreq;
|
||||
freq = targetFreq;
|
||||
currentGain = targetGain;
|
||||
gain = targetGain;
|
||||
}
|
||||
else {
|
||||
currentReson = reson + (deltaReson * sweepState);
|
||||
currentFreq = freq + (deltaFreq * sweepState);
|
||||
currentGain = gain + (deltaGain * sweepState);
|
||||
}
|
||||
poleCoeffs[1] = - (currentReson * currentReson);
|
||||
poleCoeffs[0] = 2.0 * currentReson * cos(TWO_PI * currentFreq / SRATE);
|
||||
}
|
||||
|
||||
temp = currentGain * sample;
|
||||
temp += poleCoeffs[0] * outputs[0];
|
||||
temp += poleCoeffs[1] * outputs[1];
|
||||
outputs[1] = outputs[0];
|
||||
outputs[0] = temp;
|
||||
lastOutput = outputs[0];
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
|
||||
void main()
|
||||
{
|
||||
FormSwep filter;
|
||||
FILE *fd;
|
||||
MY_FLOAT temp;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
fd = fopen("test.raw","wb");
|
||||
|
||||
filter.setTargets(100.0,0.99,0.01);
|
||||
for (i=0;i<20000;i++) {
|
||||
if (i%100 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = filter.tick(temp) * 32000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
filter.setTargets(1000.0,0.99,0.01);
|
||||
for (i=0;i<20000;i++) {
|
||||
if (i%100 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = filter.tick(temp) * 32000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
filter.setTargets(500.0,0.9999,0.001);
|
||||
for (i=0;i<20000;i++) {
|
||||
if (i%100 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = filter.tick(temp) * 32000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
|
||||
45
FormSwep.h
45
FormSwep.h
@@ -1,45 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Sweepable Formant (2-pole) */
|
||||
/* Filter Class, by Perry R. Cook, 1995-96*/
|
||||
/* See books on filters to understand */
|
||||
/* more about how this works. Nothing */
|
||||
/* out of the ordinary in this version. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__FormSwep_h)
|
||||
#define __FormSwep_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class FormSwep : public Filter
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT poleCoeffs[2];
|
||||
MY_FLOAT freq;
|
||||
MY_FLOAT reson;
|
||||
int dirty;
|
||||
MY_FLOAT targetFreq;
|
||||
MY_FLOAT targetReson;
|
||||
MY_FLOAT targetGain;
|
||||
MY_FLOAT currentFreq;
|
||||
MY_FLOAT currentReson;
|
||||
MY_FLOAT currentGain;
|
||||
MY_FLOAT deltaFreq;
|
||||
MY_FLOAT deltaReson;
|
||||
MY_FLOAT deltaGain;
|
||||
MY_FLOAT sweepState;
|
||||
MY_FLOAT sweepRate;
|
||||
public:
|
||||
FormSwep();
|
||||
~FormSwep();
|
||||
void clear();
|
||||
void setPoleCoeffs(MY_FLOAT *coeffs);
|
||||
void setGain(MY_FLOAT aValue);
|
||||
void setFreqAndReson(MY_FLOAT aFreq, MY_FLOAT aReson);
|
||||
void setStates(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain);
|
||||
void setTargets(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain);
|
||||
void setSweepRate(MY_FLOAT aRate);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
125
HIERARCH.txt
125
HIERARCH.txt
@@ -1,125 +0,0 @@
|
||||
Brief Descriptions of Classes in TK96CPP
|
||||
A ToolKit of Sound Synthesis Classes
|
||||
and Instruments in C++
|
||||
Perry Cook, 1995-96, free distribution for
|
||||
academic, instructional, tutorial, etc. purposes.
|
||||
Please read README.txt for more information.
|
||||
|
||||
<-----Building Blocks----->|<----------------Instruments------------------>
|
||||
|
||||
SourcSink Filters Non-Lin ModalSyn FM Physical Sampling PhISM
|
||||
& Formant
|
||||
|
||||
Object---------------------------Instrmnt----------.
|
||||
| | | | | |
|
||||
Envelope| Filter BowTabl | .------------------|---------------------.
|
||||
| | | JetTabl | | | | | | | | |
|
||||
ADSR | OneZero ReedTabl| Modal4 | FM4Op---.| | | | PhISEM
|
||||
| OnePole | | | | || | | | |
|
||||
._____| TwoZero .____| Marimba | FM4Alg3 || Plucked Sampler | Maracha
|
||||
| | TwoPole | Vibraphn| | || Clarinet | | Whistle
|
||||
Noise | DCBlock LipFilt AgogoBel| HeavyMtl|| Brass SamplFlt| VibraSlp
|
||||
| | BiQuad | || Flute | | Tambourn
|
||||
SubNoise| AllPass1 .____| .____|| Bowed Moog1 |
|
||||
| DLineA | | || |
|
||||
._____| DLineL VoicForm FM4Alg4 ||____. |
|
||||
| | DLineN | | | |
|
||||
RawWave | FormSwep PercFlut| Plucked2 |
|
||||
| | | |
|
||||
._____| .____| Mandolin .____|
|
||||
| | | | |
|
||||
RawLoop | FM4Alg5 | DrumSynt
|
||||
| | |
|
||||
._____| Rhodey |
|
||||
| | Wurley |
|
||||
NiWave1S| TubeBell |
|
||||
| .____|
|
||||
._____| | |
|
||||
| | FM4Alg6 |
|
||||
Modulatr| | |
|
||||
| FMVoices|
|
||||
._____| |
|
||||
| | .____|
|
||||
SingWave| |
|
||||
| FM4Alg8
|
||||
._____| |
|
||||
| | BeeThree
|
||||
RawWvOut|
|
||||
|
|
||||
._____|
|
||||
| |
|
||||
RawWvIn |
|
||||
._____|
|
||||
|
|
||||
NIFileIn
|
||||
|
||||
********** Instruments and Algorithms **************
|
||||
Each Class will be listed either with all UGs it uses,
|
||||
or the <<Algorithm>> of which it is a flavor.
|
||||
All inherit from Instrmnt, which inherits from Object.
|
||||
|
||||
Plucked.cpp Basic Plucked String DLineA,OneZero,OnePole,Noise
|
||||
Plucked2.cpp Not so Basic Pluck DLineL,DlineA,OneZero
|
||||
Mandolin.cpp My Own Mandolin <<flavor of PLUCKED2>>
|
||||
Bowed.cpp Not Hideous Bowed String DlineL,BowTabl,OnePole,BiQuad,RawWave,ADSR
|
||||
Brass.cpp Not So Bad Brass Inst. DLineA,LipFilt,DCBlock,ADSR,BiQuad
|
||||
Clarinet.cpp Pretty Good Clarinet DLineL,ReedTabl,OneZero,Envelope,Noise.h
|
||||
Flute.cpp Pretty Good Flute JetTabl,DLineL,OnePole,DCBlock,Noise,ADSR,RawWave
|
||||
Modal4.cpp 4 Resonances Envelope,RawWave,BiQuad,OnePole
|
||||
Marimba.cpp <<flavor of MODAL4>>
|
||||
Vibraphn.cpp <<flavor of MODAL4>>
|
||||
Agogobel.cpp <<flavor of MODAL4>>
|
||||
FM4Op.cpp 4 Operator FM Master ADSR,RawLoop,TwoZero
|
||||
FM4Alg3.cpp 3 Cascade w/ FB Mod. <<flavor of FM4OP>>
|
||||
FM4Alg4.cpp Like Alg3 but diff. <<flavor of FM4OP>>
|
||||
FM4Alg5.cpp 2 Parallel Simple FMs <<flavor of FM4OP>>
|
||||
FM4Alg6.cpp 3 Carr. with 1 Mod. <<flavor of FM4OP>>
|
||||
FM4Alg8.cpp 4 Osc. Additive <<flavor of FM4OP>>
|
||||
HeavyMtl.cpp Distorted Synth <<flavor of FM4Alg3>>
|
||||
PercFlut.cpp Perc. Flute <<flavor of FM4Alg4>>
|
||||
Rhodey.cpp Rhodes-Like Elec. Piano <<flavor of FM4Alg5>>
|
||||
Wurley.cpp Wurlitz. Elec. Piano <<flavor of FM4Alg5>>
|
||||
TubeBell.cpp Classic FM Bell <<flavor of FM4Alg5>>
|
||||
FMVoices.cpp 3-Formant Voice Synth. <<flavor of FM4Alg6>>
|
||||
BeeThree.cpp Cheezy Organ for Paul <<flavor of FM4Alg8>>
|
||||
Sampler.cpp Sampling Synth. 4 each ADSR, RawWave (att), RawWave (loop), OnePole
|
||||
SamplFlt.cpp Sampler with Swept Filt.<<flavor of Sampler>>
|
||||
Moog1.cpp Swept filter flavor of <<flavor of SamplFlt>>
|
||||
Voicform.cpp Source/Filter Voice Envelope,Noise,SingWave,FormSwep,OnePole,OneZero
|
||||
DrumSynt.cpp Drum Synthesizer bunch of NIFileIn, and OnePole
|
||||
|
||||
*********** Basic Unit Generators **************
|
||||
|
||||
Master Object: Object.cpp for compatibility with Objective C
|
||||
|
||||
Source&Sink: RawWave.cpp Lin-Interp Wavetable, Looped or 1 Shot
|
||||
NIWave1S.cpp Non-Interp Wavetable, 1 Shot
|
||||
RawLoop.cpp Lin-Interp Wavetable, Looping
|
||||
RawWvIn.cpp Lin-Interp Wave In streaming 'device'
|
||||
NIFileIn.cpp Non-Interp Wave In streamer, closes & opens
|
||||
RawWvOut.cpp Non-Interp Wave Out streaming 'device'
|
||||
Envelope.cpp Linearly Goes to Target by Rate, + noteOn/Off
|
||||
ADSR.cpp ADSR Flavor of Envelope
|
||||
Noise.cpp Random Number Generator
|
||||
SubNoise.cpp Random Numbers each N samples
|
||||
|
||||
Filters: Filter.cpp Filter Master Class
|
||||
OneZero.cpp One Zero Filter
|
||||
OnePole.cpp One Pole Filter
|
||||
AllPass1.cpp 1st Order All-Pass (phase) Filter
|
||||
DCBlock.cpp DC Blocking 1Pole/1Zero Filter
|
||||
TwoZero.cpp Two Zero Filter
|
||||
TwoPole.cpp Two Pole Filter
|
||||
BiQuad.cpp 2Pole/2Zero Filter
|
||||
FormSwep.cpp Sweepable 2Pole filter, go to target by rate
|
||||
DLineL.cpp Linearly Interpolating Delay Line
|
||||
DLineA.cpp AllPass Interpolating Delay Line
|
||||
DLineN.cpp Non Interpolating Delay Line
|
||||
|
||||
NonLin&Lookup: JetTabl.cpp Cubic Jet NonLinearity
|
||||
BowTabl.cpp 1/x^3-like Bow NonLinearity
|
||||
ReedTabl.cpp 1 break point Reed NonLinearity
|
||||
LipFilt.cpp Pressure Controlled BiQuad with NonLin
|
||||
|
||||
Derived: Modulatr.cpp Per. and Rnd. Vibrato: RawWave,SubNoise,OnePole
|
||||
SingWave.cpp Looping Wavetable with: Modulatr,Envelope
|
||||
60
HeavyMtl.cpp
60
HeavyMtl.cpp
@@ -1,60 +0,0 @@
|
||||
/******************************************/
|
||||
/* Heavy Metal Synth Subclass */
|
||||
/* of Algorithm 3 (TX81Z) Subclass of */
|
||||
/* 3 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/******************************************/
|
||||
|
||||
#include "HeavyMtl.h"
|
||||
|
||||
HeavyMtl :: HeavyMtl() : FM4Alg3()
|
||||
{
|
||||
this->loadWaves("rawwaves/sinewave.raw",
|
||||
"rawwaves/twopeaks.raw",
|
||||
"rawwaves/twopeaks.raw",
|
||||
"rawwaves/sinewave.raw");
|
||||
|
||||
this->setRatio(0,1.00 );
|
||||
this->setRatio(1,4.00 * 0.999);
|
||||
this->setRatio(2,3.00 * 1.001);
|
||||
this->setRatio(3,0.50 * 1.002);
|
||||
gains[0] = __FM4Op_gains[92];
|
||||
gains[1] = __FM4Op_gains[76];
|
||||
gains[2] = __FM4Op_gains[91];
|
||||
gains[3] = __FM4Op_gains[68];
|
||||
adsr[0]->setAll(0.050,0.0100,1.0,0.001);
|
||||
adsr[1]->setAll(0.050,0.0010,1.0,0.0001);
|
||||
adsr[2]->setAll(0.001,0.0020,1.0,0.0002);
|
||||
adsr[3]->setAll(0.050,0.0010,0.2,0.0002);
|
||||
twozero->setGain(2.0);
|
||||
vibWave->setFreq(5.5);
|
||||
modDepth = 0.00;
|
||||
}
|
||||
|
||||
HeavyMtl :: ~HeavyMtl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void HeavyMtl :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
waves[0]->setFreq(baseFreq * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * ratios[3]);
|
||||
}
|
||||
|
||||
void HeavyMtl :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
gains[0] = amp * __FM4Op_gains[92];
|
||||
gains[1] = amp * __FM4Op_gains[76];
|
||||
gains[2] = amp * __FM4Op_gains[91];
|
||||
gains[3] = amp * __FM4Op_gains[68];
|
||||
this->setFreq(freq);
|
||||
this->keyOn();
|
||||
#if defined(_debug_)
|
||||
printf("HeavyMtl : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
22
HeavyMtl.h
22
HeavyMtl.h
@@ -1,22 +0,0 @@
|
||||
/******************************************/
|
||||
/* Heavy Metal Synth Subclass */
|
||||
/* of Algorithm 3 (TX81Z) Subclass of */
|
||||
/* 3 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__HeavyMtl_h)
|
||||
#define __HeavyMtl_h
|
||||
|
||||
#include "FM4Alg3.h"
|
||||
|
||||
class HeavyMtl : public FM4Alg3
|
||||
{
|
||||
public:
|
||||
HeavyMtl();
|
||||
~HeavyMtl();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
};
|
||||
|
||||
#endif
|
||||
40
INSTALL
Normal file
40
INSTALL
Normal file
@@ -0,0 +1,40 @@
|
||||
The Synthesis ToolKit in C++ (STK)
|
||||
|
||||
By Perry R. Cook and Gary P. Scavone, 1995-2002.
|
||||
|
||||
The Synthesis ToolKit in C++ can be used in a variety of ways, depending on your particular needs. Some people just choose the classes they need for a particular project and copy those to their project directory. Others like to compile and link to a library of object files. STK was not designed with one particular style of use in mind.
|
||||
|
||||
To configure and compile (on Unix systems):
|
||||
|
||||
1. Unpack the STK distribution (tar -xzf stk-4.x.tar.gz).
|
||||
2. From within the directory containing this file, run configure:
|
||||
|
||||
./configure
|
||||
|
||||
3. From within each project directory, type "make".
|
||||
4. To compile a library of objects, type "make" from within the src directory.
|
||||
|
||||
Several options can be passed to configure, including:
|
||||
|
||||
--disable-realtime = only compile generic non-realtime classes
|
||||
--enable-debug = enable various debug output
|
||||
--with-alsa = choose native ALSA API support (linux only)
|
||||
--enable-midiator = enable native MS-124W MIDI support (linux only)
|
||||
|
||||
Typing "./configure --help" will display all the available options. In addition, it is possible to specify the RAWWAVES and INCLUDE paths to configure as (ex. to set to /home/gary/rawwaves and /home/gary/include):
|
||||
|
||||
./configure RAWWAVE_PATH="/home/gary/rawwaves/"
|
||||
./configure INCLUDE_PATH="/home/gary/include/"
|
||||
|
||||
The ending "/" is required for the RAWWAVES path. The default behavior will set a relative path that works for the project files included with the distribution (assuming they are not moved).
|
||||
|
||||
If you wish to use a different compiler than that selected by configure, specify that compiler in the command line (ex. to use CC):
|
||||
|
||||
./configure CXX=CC
|
||||
|
||||
In addition, a linux RPM is available from the STK WWW site (http://www-ccrma.stanford.edu/software/stk/).
|
||||
|
||||
|
||||
For Windows Users:
|
||||
|
||||
An STK distribution is available which contains precompiled executables. In addition, Visual C++ project files are included for each of the example STK projects.
|
||||
35
Instrmnt.cpp
35
Instrmnt.cpp
@@ -1,35 +0,0 @@
|
||||
/******************************************/
|
||||
/* Instrument SuperClass for Toolkit96 */
|
||||
/* Perry R. Cook, Princeton University */
|
||||
/******************************************/
|
||||
|
||||
#include "Instrmnt.h"
|
||||
|
||||
Instrmnt :: Instrmnt()
|
||||
{
|
||||
}
|
||||
|
||||
void Instrmnt :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
}
|
||||
|
||||
void Instrmnt :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
}
|
||||
|
||||
void Instrmnt :: setFreq(MY_FLOAT freq)
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT Instrmnt :: tick()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT Instrmnt :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
void Instrmnt :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
}
|
||||
25
Instrmnt.h
25
Instrmnt.h
@@ -1,25 +0,0 @@
|
||||
/******************************************/
|
||||
/* Instrument SuperClass for Toolkit96 */
|
||||
/* Perry R. Cook, Princeton University */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Instrmnt_h)
|
||||
#define __Instrmnt_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class Instrmnt : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Instrmnt();
|
||||
MY_FLOAT lastOut();
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual MY_FLOAT tick();
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
36
JetTabl.cpp
36
JetTabl.cpp
@@ -1,36 +0,0 @@
|
||||
/**********************************************/
|
||||
/* Jet Table Object by Perry R. Cook, 1995-96 */
|
||||
/* Consult Fletcher and Rossing, Karjalainen, */
|
||||
/* Cook, more, for information. */
|
||||
/* This, as with many other of my "tables", */
|
||||
/* is not a table, but is computed by poly- */
|
||||
/* nomial calculation. */
|
||||
/**********************************************/
|
||||
|
||||
#include "JetTabl.h"
|
||||
|
||||
JetTabl :: JetTabl()
|
||||
{
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
JetTabl :: ~JetTabl()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT JetTabl :: lookup(double sample) /* Perform "Table Lookup" */
|
||||
{ /* By Polynomial Calculation */
|
||||
lastOutput = sample *
|
||||
(sample*sample - 1.0); /* (x^3 - x) approximates sigmoid of jet */
|
||||
if (lastOutput > 1.0)
|
||||
lastOutput = 1.0; /* Saturation at +/- 1.0 */
|
||||
if (lastOutput < -1.0)
|
||||
lastOutput = -1.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT JetTabl :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
22
JetTabl.h
22
JetTabl.h
@@ -1,22 +0,0 @@
|
||||
/**********************************************/
|
||||
/* Jet Table Object by Perry R. Cook, 1995-96 */
|
||||
/* Consult Fletcher and Rossing, Karjalainen, */
|
||||
/* Cook, more, for information. */
|
||||
/* This, as with many other of my "tables", */
|
||||
/* is not a table, but is computed by poly- */
|
||||
/* nomial calculation. */
|
||||
/**********************************************/
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class JetTabl : public Object
|
||||
{
|
||||
protected:
|
||||
double lastOutput;
|
||||
public:
|
||||
JetTabl();
|
||||
~JetTabl();
|
||||
double lookup(double deltaP);
|
||||
double lastOut();
|
||||
};
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
time textVoic =100.00 lll ahh ...... =133 .... xxx rrr + + eee .. mmm + ohh ..... sss ahh ..... ddd - eee .. - - ... + + ehh .. + ... sss - - - eee ..... lll =100.0 ahh .......
|
||||
66
LipFilt.cpp
66
LipFilt.cpp
@@ -1,66 +0,0 @@
|
||||
/**********************************************/
|
||||
/* Lip Filter Object by Perry R. Cook, 1995-96*/
|
||||
/* The lip of the brass player has dynamics */
|
||||
/* which are controlled by the mass, spring */
|
||||
/* constant, and damping of the lip. This */
|
||||
/* filter simulates that behavior and the */
|
||||
/* transmission/reflection properties as */
|
||||
/* well. See Cook TBone and HosePlayer */
|
||||
/* instruments and articles. */
|
||||
/**********************************************/
|
||||
|
||||
#include "LipFilt.h"
|
||||
|
||||
LipFilt :: LipFilt()
|
||||
{
|
||||
MY_FLOAT coeffs[2];
|
||||
filter = new BiQuad;
|
||||
coeffs[0] = 0.0;
|
||||
coeffs[1] = 0.0;
|
||||
filter->setZeroCoeffs(coeffs);
|
||||
this->clear();
|
||||
}
|
||||
|
||||
LipFilt :: ~LipFilt()
|
||||
{
|
||||
delete filter;
|
||||
}
|
||||
|
||||
void LipFilt :: clear()
|
||||
{
|
||||
filter->clear();
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
void LipFilt :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
MY_FLOAT coeffs[2];
|
||||
coeffs[0] = 2.0 * 0.997 *
|
||||
cos(TWO_PI * frequency / SRATE); /* damping should change with */
|
||||
coeffs[1] = -0.997 * 0.997; /* lip parameters, but not yet.*/
|
||||
filter->setPoleCoeffs(coeffs);
|
||||
filter->setGain(0.03);
|
||||
}
|
||||
|
||||
/* NOTE: Here we should add lip tension */
|
||||
/* settings based on Mass/Spring/Damping */
|
||||
/* Maybe in TookKit97 */
|
||||
|
||||
MY_FLOAT LipFilt :: tick(MY_FLOAT mouthSample,MY_FLOAT boreSample)
|
||||
/* Perform "Table Lookup" By Polynomial Calculation */
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
temp = mouthSample - boreSample; /* Differential pressure */
|
||||
temp = filter->tick(temp); /* Force -> position */
|
||||
temp = temp*temp; /* Simple position to area mapping */
|
||||
if (temp > 1.0) temp = 1.0; /* Saturation at + 1.0 */
|
||||
lastOutput = temp * mouthSample; /* Assume mouth input = area */
|
||||
lastOutput += (1.0 - temp) * boreSample; /* and Bore reflection is compliment. */
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT LipFilt :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
28
LipFilt.h
28
LipFilt.h
@@ -1,28 +0,0 @@
|
||||
/**********************************************/
|
||||
/* Lip Filter Object by Perry R. Cook, 1995-96*/
|
||||
/* The lip of the brass player has dynamics */
|
||||
/* which are controlled by the mass, spring */
|
||||
/* constant, and damping of the lip. This */
|
||||
/* filter simulates that behavior and the */
|
||||
/* transmission/reflection properties as */
|
||||
/* well. See Cook TBone and HosePlayer */
|
||||
/* instruments and articles. */
|
||||
/**********************************************/
|
||||
|
||||
#include "Object.h"
|
||||
#include "BiQuad.h"
|
||||
|
||||
class LipFilt : public Object
|
||||
{
|
||||
protected:
|
||||
BiQuad *filter;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
LipFilt();
|
||||
~LipFilt();
|
||||
void clear();
|
||||
void setFreq(MY_FLOAT frequency);
|
||||
MY_FLOAT tick(MY_FLOAT mouthSample,MY_FLOAT boreSample);
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
188
MIDIInpt.cpp
188
MIDIInpt.cpp
@@ -1,188 +0,0 @@
|
||||
/******************************************/
|
||||
/* Simple RealTime MIDI Input Object, */
|
||||
/* by Perry R. Cook, 1996 */
|
||||
/* */
|
||||
/* This object takes MIDI from the input */
|
||||
/* , parses it, turns it into TSIDI */
|
||||
/* messages, and buffers it up for use by*/
|
||||
/* any object that asks for it later. */
|
||||
/* */
|
||||
/* TSIDI (ToolKit Synthesis Instrument */
|
||||
/* Digital Interfaceis like MIDI, but */
|
||||
/* allows for floating point control */
|
||||
/* changes, note numbers, etc. Example: */
|
||||
/* noteOn(1,60.01,111.132) plays a sharp */
|
||||
/* middle C with a velocity of 111.132 */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "MIDIInpt.h"
|
||||
|
||||
int onePending;
|
||||
MDport inport;
|
||||
MDevent lastEvent;
|
||||
|
||||
|
||||
// void pollMessage(void *)
|
||||
// {
|
||||
// int status;
|
||||
// while (1) {
|
||||
// while (onePending == 0) {
|
||||
// mdReceive(inport, &lastEvent, 1);
|
||||
// status = mdGetStatus(lastEvent.msg);
|
||||
// if (status==MD_NOTEON || status==MD_NOTEOFF)
|
||||
// onePending = 1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
MIDIInpt :: MIDIInpt()
|
||||
{
|
||||
int nports;
|
||||
nports = mdInit();
|
||||
printf("%d MIDI devices available\n", nports);
|
||||
inport = mdOpenInPort(0);
|
||||
if (inport == NULL) {
|
||||
printf("open failed\n");
|
||||
exit(0);
|
||||
}
|
||||
mdSetStampMode(inport, MD_NOSTAMP);
|
||||
onePending = 0;
|
||||
// midi_pid = sproc(pollMessage, PR_SALL);
|
||||
// if (midi_pid == -1)
|
||||
// {
|
||||
// fprintf(stderr, "unable to create midi input thread...aborting.\n");
|
||||
// exit(-1);
|
||||
// }
|
||||
}
|
||||
|
||||
#define _BSD_SIGNALS
|
||||
#include <signal.h>
|
||||
|
||||
MIDIInpt :: ~MIDIInpt()
|
||||
{
|
||||
mdClosePort(inport);
|
||||
// kill(midi_pid, SIGKILL);
|
||||
}
|
||||
|
||||
/* MIDI File Code
|
||||
if (byte > 15) {
|
||||
if (byte == 248) printf("MIDI Clock,");
|
||||
else if (byte == 249) printf("Undefined,");
|
||||
else if (byte == 250) printf("Song Start,");
|
||||
else if (byte == 251) printf("Continue,");
|
||||
else if (byte == 252) printf("Song Stop,");
|
||||
else if (byte == 253) printf("Undefined,");
|
||||
else if (byte == 254) printf("ActiveSen,");
|
||||
else if (byte == 255) printf("SystReset,");
|
||||
else printf("BEATSME");
|
||||
}
|
||||
else {
|
||||
if (byte == 8) printf("NoteOff");
|
||||
if (byte == 9) printf("NoteOn");
|
||||
if (byte == 10) printf("Poly Pressure");
|
||||
if (byte == 11) printf("Control Change");
|
||||
if (byte == 12) printf("Program Change");
|
||||
if (byte == 13) printf("Channel Pressure");
|
||||
if (byte == 14) printf("Pitch Wheel");
|
||||
}
|
||||
*/
|
||||
|
||||
int MIDIInpt :: nextMessage()
|
||||
{
|
||||
int status;
|
||||
int byte1;
|
||||
int byte2;
|
||||
|
||||
messageType = -1;
|
||||
|
||||
mdReceive(inport, &lastEvent, 1);
|
||||
|
||||
// if (onePending == 1) {
|
||||
|
||||
status = mdGetStatus(lastEvent.msg);
|
||||
byte1 = mdGetByte1(lastEvent.msg);
|
||||
byte2 = mdGetByte2(lastEvent.msg);
|
||||
channel = mdGetChannel(lastEvent.msg);
|
||||
|
||||
if (status==MD_NOTEON) {
|
||||
byteTwo = (float) byte1;
|
||||
byteThree = (float) byte2;
|
||||
if (byte2==0)
|
||||
messageType = 8;
|
||||
else
|
||||
messageType = 9;
|
||||
}
|
||||
else if (status==MD_NOTEOFF) {
|
||||
byteTwo = (float) byte1;
|
||||
byteThree = (float) byte2;
|
||||
messageType = 8;
|
||||
}
|
||||
else if (status==MD_CONTROLCHANGE) {
|
||||
byteTwo = (float) byte1;
|
||||
byteThree = (float) byte2;
|
||||
messageType = 11;
|
||||
}
|
||||
else if (status==MD_PROGRAMCHANGE) {
|
||||
byteTwo = (float) byte1;
|
||||
messageType = 12;
|
||||
}
|
||||
else if (status==MD_CHANNELPRESSURE) {
|
||||
byteTwo = (float) byte1;
|
||||
messageType = 13;
|
||||
}
|
||||
else if (status==MD_PITCHBENDCHANGE) {
|
||||
byteTwo = (float) byte1;
|
||||
byteTwo += (float) byte2 * NORM_7;
|
||||
messageType = 14;
|
||||
}
|
||||
else {
|
||||
messageType = -1;
|
||||
}
|
||||
// onePending = 0;
|
||||
|
||||
// }
|
||||
|
||||
return messageType;
|
||||
}
|
||||
|
||||
void MIDIInpt :: printMessage()
|
||||
{
|
||||
char buffer[128];
|
||||
mdPrintEvent(buffer,&lastEvent,1);
|
||||
printf(buffer);
|
||||
}
|
||||
|
||||
int MIDIInpt :: getType()
|
||||
{
|
||||
return messageType;
|
||||
}
|
||||
|
||||
int MIDIInpt :: getChannel()
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
|
||||
MY_FLOAT MIDIInpt :: getByteTwo()
|
||||
{
|
||||
return byteTwo;
|
||||
}
|
||||
|
||||
MY_FLOAT MIDIInpt :: getByteThree()
|
||||
{
|
||||
return byteThree;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
void main(int argc,char *argv[])
|
||||
{
|
||||
MIDIInpt testMIDI;
|
||||
|
||||
while(1) {
|
||||
if (testMIDI.nextMessage() > 0)
|
||||
testMIDI.printMessage();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
48
MIDIInpt.h
48
MIDIInpt.h
@@ -1,48 +0,0 @@
|
||||
/******************************************/
|
||||
/* Simple MIDI Text File Reader Class, */
|
||||
/* by Perry R. Cook, 1996 */
|
||||
/* This Object can open a MIDI Text File */
|
||||
/* and parse it. The file spec is mine */
|
||||
/* and mine alone, but it's all text so */
|
||||
/* you should be able to figure it out. */
|
||||
/* */
|
||||
/* TSIDI (ToolKit Synthesis Instrument */
|
||||
/* Digital Interfaceis like MIDI, but */
|
||||
/* allows for floating point control */
|
||||
/* changes, note numbers, etc. Example: */
|
||||
/* noteOn(1,60.01,111.132) plays a sharp */
|
||||
/* middle C with a velocity of 111.132 */
|
||||
/* */
|
||||
/* Warning: Obey column spacing in the */
|
||||
/* text file if you try to edit it or */
|
||||
/* create your own files. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__MIDIInpt_h)
|
||||
#define __MIDIInpt_h
|
||||
|
||||
#include "Object.h"
|
||||
#include "dmedia/midi.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
class MIDIInpt : public Object
|
||||
{
|
||||
protected:
|
||||
int midi_pid;
|
||||
int messageType;
|
||||
int channel;
|
||||
float byteTwo;
|
||||
float byteThree;
|
||||
public:
|
||||
MIDIInpt();
|
||||
~MIDIInpt();
|
||||
void printMessage();
|
||||
int nextMessage();
|
||||
int getType();
|
||||
int getChannel();
|
||||
MY_FLOAT getByteTwo();
|
||||
MY_FLOAT getByteThree();
|
||||
};
|
||||
|
||||
#endif
|
||||
133
MIDIText.cpp
133
MIDIText.cpp
@@ -1,133 +0,0 @@
|
||||
/******************************************/
|
||||
/* Simple MIDI Text File Reader Class, */
|
||||
/* by Perry R. Cook, 1996 */
|
||||
/* This Object can open a MIDI Text File */
|
||||
/* and parse it. The file spec is mine */
|
||||
/* and mine alone, but it's all text so */
|
||||
/* you should be able to figure it out. */
|
||||
/* */
|
||||
/* SKINI (Synthesis toolKit Instrument */
|
||||
/* Network Interface) is like MIDI, but */
|
||||
/* allows for floating point control */
|
||||
/* changes, note numbers, etc. Example: */
|
||||
/* noteOn 60.01 111.132 plays a sharp */
|
||||
/* middle C with a velocity of 111.132 */
|
||||
/* See SKINI.txt for more information */
|
||||
/* Warning: Obey columns in the text */
|
||||
/* file if you try to edit it or create */
|
||||
/* your own files. */
|
||||
/******************************************/
|
||||
|
||||
#include "MIDIText.h"
|
||||
|
||||
MIDIText :: MIDIText(char *fileName)
|
||||
{
|
||||
myFile = fopen(fileName,"r");
|
||||
this->nextMessage();
|
||||
}
|
||||
|
||||
MIDIText :: ~MIDIText()
|
||||
{
|
||||
}
|
||||
|
||||
/* MIDI File Codes
|
||||
if (byte > 15) {
|
||||
if (byte == 248) printf("MIDI Clock,");
|
||||
else if (byte == 249) printf("Undefined,");
|
||||
else if (byte == 250) printf("Song Start,");
|
||||
else if (byte == 251) printf("Continue,");
|
||||
else if (byte == 252) printf("Song Stop,");
|
||||
else if (byte == 253) printf("Undefined,");
|
||||
else if (byte == 254) printf("ActiveSen,");
|
||||
else if (byte == 255) printf("SystReset,");
|
||||
else printf("BEATSME");
|
||||
}
|
||||
else { // these are all nybbles of status bytes //
|
||||
if (byte == 8) printf("NoteOff");
|
||||
if (byte == 9) printf("NoteOn");
|
||||
if (byte == 10) printf("Poly Pressure");
|
||||
if (byte == 11) printf("Control Change");
|
||||
if (byte == 12) printf("Program Change");
|
||||
if (byte == 13) printf("Channel Pressure");
|
||||
if (byte == 14) printf("Pitch Wheel");
|
||||
}
|
||||
*/
|
||||
|
||||
int MIDIText :: nextMessage()
|
||||
{
|
||||
int notDone = 1,point;
|
||||
char inputString[1024];
|
||||
char tempString[32];
|
||||
|
||||
while (notDone) {
|
||||
notDone = 0;
|
||||
if (fgets(inputString,1000,myFile)) {
|
||||
sscanf(inputString,"%s %lf %i %f %f",tempString,&deltaTime,&channel,&byteTwo,&byteThree);
|
||||
point = 5;
|
||||
if (tempString[0]=='%') point = 1;
|
||||
if (tempString[point] == 'n') { // NoteO'n'
|
||||
messageType = 9;
|
||||
}
|
||||
else if (inputString[point] == 'f') { // NoteO'f'f
|
||||
messageType = 8;
|
||||
}
|
||||
else if (inputString[point] == 'B') { // Pitch'B'end
|
||||
byteThree = byteTwo;
|
||||
messageType = 14;
|
||||
}
|
||||
else if (inputString[point] == 'a') { // Progr'a'mChange
|
||||
messageType = 12;
|
||||
}
|
||||
else if (inputString[point] == 'T') { // After'T'ouch
|
||||
messageType = 11;
|
||||
}
|
||||
else if (inputString[point] == 'o') { // Contr'o'lChange
|
||||
messageType = 11;
|
||||
}
|
||||
else if (inputString[0] == '/' || inputString[0] == ' ') {
|
||||
notDone = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
messageType = -1;
|
||||
}
|
||||
}
|
||||
return messageType;
|
||||
}
|
||||
|
||||
int MIDIText :: getType()
|
||||
{
|
||||
return messageType;
|
||||
}
|
||||
|
||||
int MIDIText :: getChannel()
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
|
||||
MY_FLOAT MIDIText :: getDelta()
|
||||
{
|
||||
return deltaTime;
|
||||
}
|
||||
|
||||
MY_FLOAT MIDIText :: getByteTwo()
|
||||
{
|
||||
return byteTwo;
|
||||
}
|
||||
|
||||
MY_FLOAT MIDIText :: getByteThree()
|
||||
{
|
||||
return byteThree;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
void main(int argc,char *argv[])
|
||||
{
|
||||
MIDIText testFile(argv[1]);
|
||||
|
||||
while(testFile.nextMessage() > 0) ;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
46
MIDIText.h
46
MIDIText.h
@@ -1,46 +0,0 @@
|
||||
/******************************************/
|
||||
/* Simple MIDI Text File Reader Class, */
|
||||
/* by Perry R. Cook, 1996 */
|
||||
/* This Object can open a MIDI Text File */
|
||||
/* and parse it. The file spec is mine */
|
||||
/* and mine alone, but it's all text so */
|
||||
/* you should be able to figure it out. */
|
||||
/* */
|
||||
/* SKINI (Synthesis toolKit Instrument */
|
||||
/* Network Interface) is like MIDI, but */
|
||||
/* allows for floating point control */
|
||||
/* changes, note numbers, etc. Example: */
|
||||
/* noteOn 60.01 111.132 plays a sharp */
|
||||
/* middle C with a velocity of 111.132 */
|
||||
/* See SKINI.txt for more information */
|
||||
/* Warning: Obey columns in the text */
|
||||
/* file if you try to edit it or create */
|
||||
/* your own files. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__MIDIText_h)
|
||||
#define __MIDIText_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class MIDIText : public Object
|
||||
{
|
||||
protected:
|
||||
FILE *myFile;
|
||||
int messageType;
|
||||
int channel;
|
||||
MY_FLOAT deltaTime;
|
||||
float byteTwo;
|
||||
float byteThree;
|
||||
public:
|
||||
MIDIText(char *fileName);
|
||||
~MIDIText();
|
||||
int nextMessage();
|
||||
int getType();
|
||||
int getChannel();
|
||||
MY_FLOAT getDelta();
|
||||
MY_FLOAT getByteTwo();
|
||||
MY_FLOAT getByteThree();
|
||||
};
|
||||
|
||||
#endif
|
||||
247
Makefile
247
Makefile
@@ -1,247 +0,0 @@
|
||||
O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o RawWave.o RawLoop.o \
|
||||
NIWave1S.o Modulatr.o SingWave.o RawWvOut.o RawWvIn.o Filter.o \
|
||||
OneZero.o OnePole.o TwoZero.o TwoPole.o DCBlock.o BiQuad.o AllPass1.o \
|
||||
DLineA.o DLineL.o DLineN.o FormSwep.o BowTabl.o JetTabl.o ReedTabl.o \
|
||||
LipFilt.o Modal4.o FM4Op.o FM4Alg3.o FM4Alg4.o FM4Alg5.o FM4Alg6.o \
|
||||
FM4Alg8.o Plucked2.o SamplFlt.o Sampler.o VoicForm.o\
|
||||
MIDIText.o Reverb.o VoicMang.o \
|
||||
\
|
||||
Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Plucked.o Mandolin.o \
|
||||
Clarinet.o Flute.o Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \
|
||||
HeavyMtl.o PercFlut.o BeeThree.o FMVoices.o Moog1.o
|
||||
|
||||
RM = /bin/rm
|
||||
|
||||
# This is for NeXT
|
||||
# CC = cc -O
|
||||
# INSTR = testMono testMult DrumSynt textVoic
|
||||
|
||||
|
||||
# These are for SGI
|
||||
INSTR = testTextIn testMono testMIDI testMult DrumSynt textVoic
|
||||
CC = gcc -O
|
||||
MEDIALINK = -lmd
|
||||
TCLLIB = /usr/local/lib/libtcl.so.7.4 /usr/local/lib/libtk.so.4.0 /usr/lib/libX11.so
|
||||
LIBRARY = /usr/lib/libmx.so /usr/lib/libaudio.a
|
||||
|
||||
# .cpp.o:
|
||||
# $(CC) -c $*.cpp
|
||||
|
||||
all: $(INSTR)
|
||||
|
||||
testTextIn: $(LIBRARY) testTextIn.cpp $(O_FILES) MIDIInpt.o
|
||||
$(CC) $(MEDIALINK) -o testTextIn testTextIn.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
testMono: $(LIBRARY) testMono.cpp $(O_FILES)
|
||||
$(CC) $(MEDIALINK) -o testMono testMono.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
testMIDI: $(LIBRARY) testMIDI.cpp Object.o MIDIInpt.o
|
||||
$(CC) $(MEDIALINK) -o testMIDI testMIDI.cpp Object.o MIDIInpt.o $(LIBRARY) /usr/lib/libmidi.so
|
||||
|
||||
testMult: $(LIBRARY) testMult.cpp $(O_FILES)
|
||||
$(CC) $(MEDIALINK) -o testMult testMult.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
textVoic: $(LIBRARY) textVoic.cpp $(O_FILES)
|
||||
$(CC) $(MEDIALINK) -o textVoic textVoic.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
Instrmnt.o: Instrmnt.cpp
|
||||
$(CC) -c Instrmnt.cpp
|
||||
|
||||
Marimba.o: Marimba.cpp
|
||||
$(CC) -c Marimba.cpp
|
||||
|
||||
Vibraphn.o: Vibraphn.cpp
|
||||
$(CC) -c Vibraphn.cpp
|
||||
|
||||
AgogoBel.o: AgogoBel.cpp
|
||||
$(CC) -c AgogoBel.cpp
|
||||
|
||||
Plucked.o: Plucked.cpp
|
||||
$(CC) -c Plucked.cpp
|
||||
|
||||
Mandolin.o: Mandolin.cpp
|
||||
$(CC) -c Mandolin.cpp
|
||||
|
||||
Clarinet.o: Clarinet.cpp
|
||||
$(CC) -c Clarinet.cpp
|
||||
|
||||
Flute.o: Flute.cpp
|
||||
$(CC) -c Flute.cpp
|
||||
|
||||
Brass.o: Brass.cpp
|
||||
$(CC) -c Brass.cpp
|
||||
|
||||
Bowed.o: Bowed.cpp
|
||||
$(CC) -c Bowed.cpp
|
||||
|
||||
Rhodey.o: Rhodey.cpp
|
||||
$(CC) -c Rhodey.cpp
|
||||
|
||||
Wurley.o: Wurley.cpp
|
||||
$(CC) -c Wurley.cpp
|
||||
|
||||
TubeBell.o: TubeBell.cpp
|
||||
$(CC) -c TubeBell.cpp
|
||||
|
||||
HeavyMtl.o: HeavyMtl.cpp
|
||||
$(CC) -c HeavyMtl.cpp
|
||||
|
||||
PercFlut.o: PercFlut.cpp
|
||||
$(CC) -c PercFlut.cpp
|
||||
|
||||
BeeThree.o: BeeThree.cpp
|
||||
$(CC) -c BeeThree.cpp
|
||||
|
||||
FMVoices.o: FMVoices.cpp
|
||||
$(CC) -c FMVoices.cpp
|
||||
|
||||
Moog1.o: Moog1.cpp
|
||||
$(CC) -c Moog1.cpp
|
||||
|
||||
DrumSynt: $(LIBRARY) DrumSynt.cpp $(O_FILES)
|
||||
$(CC) -o DrumSynt DrumSynt.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
testVoic: $(LIBRARY) testVoic.cpp $(O_FILES)
|
||||
$(CC) -o testVoic testVoic.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
# $(O_FILES) :
|
||||
# $(CC) -c -o $@ $*.cpp
|
||||
|
||||
Object.o : Object.cpp
|
||||
$(CC) -c Object.cpp
|
||||
|
||||
Envelope.o : Envelope.cpp
|
||||
$(CC) -c Envelope.cpp
|
||||
|
||||
ADSR.o : ADSR.cpp
|
||||
$(CC) -c ADSR.cpp
|
||||
|
||||
Noise.o : Noise.cpp
|
||||
$(CC) -c Noise.cpp
|
||||
|
||||
SubNoise.o : SubNoise.cpp
|
||||
$(CC) -c SubNoise.cpp
|
||||
|
||||
RawWave.o : RawWave.cpp
|
||||
$(CC) -c RawWave.cpp
|
||||
|
||||
RawLoop.o : RawLoop.cpp
|
||||
$(CC) -c RawLoop.cpp
|
||||
|
||||
NIWave1S.o : NIWave1S.cpp
|
||||
$(CC) -c NIWave1S.cpp
|
||||
|
||||
Modulatr.o : Modulatr.cpp
|
||||
$(CC) -c Modulatr.cpp
|
||||
|
||||
SingWave.o : SingWave.cpp
|
||||
$(CC) -c SingWave.cpp
|
||||
|
||||
RawWvOut.o : RawWvOut.cpp
|
||||
$(CC) -c RawWvOut.cpp
|
||||
|
||||
RawWvIn.o : RawWvIn.cpp
|
||||
$(CC) -c RawWvIn.cpp
|
||||
|
||||
Filter.o : Filter.cpp
|
||||
$(CC) -c Filter.cpp
|
||||
|
||||
OneZero.o : OneZero.cpp
|
||||
$(CC) -c OneZero.cpp
|
||||
|
||||
OnePole.o : OnePole.cpp
|
||||
$(CC) -c OnePole.cpp
|
||||
|
||||
TwoZero.o : TwoZero.cpp
|
||||
$(CC) -c TwoZero.cpp
|
||||
|
||||
TwoPole.o : TwoPole.cpp
|
||||
$(CC) -c TwoPole.cpp
|
||||
|
||||
DCBlock.o : DCBlock.cpp
|
||||
$(CC) -c DCBlock.cpp
|
||||
|
||||
BiQuad.o : BiQuad.cpp
|
||||
$(CC) -c BiQuad.cpp
|
||||
|
||||
AllPass1.o : AllPass1.cpp
|
||||
$(CC) -c AllPass1.cpp
|
||||
|
||||
DLineA.o : DLineA.cpp
|
||||
$(CC) -c DLineA.cpp
|
||||
|
||||
DLineL.o : DLineL.cpp
|
||||
$(CC) -c DLineL.cpp
|
||||
|
||||
DLineN.o : DLineN.cpp
|
||||
$(CC) -c DLineN.cpp
|
||||
|
||||
FormSwep.o : FormSwep.cpp
|
||||
$(CC) -c FormSwep.cpp
|
||||
|
||||
BowTabl.o : BowTabl.cpp
|
||||
$(CC) -c BowTabl.cpp
|
||||
|
||||
JetTabl.o : JetTabl.cpp
|
||||
$(CC) -c JetTabl.cpp
|
||||
|
||||
ReedTabl.o : ReedTabl.cpp
|
||||
$(CC) -c ReedTabl.cpp
|
||||
|
||||
LipFilt.o : LipFilt.cpp
|
||||
$(CC) -c LipFilt.cpp
|
||||
|
||||
Modal4.o : Modal4.cpp
|
||||
$(CC) -c Modal4.cpp
|
||||
|
||||
FM4Op.o : FM4Op.cpp
|
||||
$(CC) -c FM4Op.cpp
|
||||
|
||||
FM4Alg3.o : FM4Alg3.cpp
|
||||
$(CC) -c FM4Alg3.cpp
|
||||
|
||||
FM4Alg4.o : FM4Alg4.cpp
|
||||
$(CC) -c FM4Alg4.cpp
|
||||
|
||||
FM4Alg5.o : FM4Alg5.cpp
|
||||
$(CC) -c FM4Alg5.cpp
|
||||
|
||||
FM4Alg6.o : FM4Alg6.cpp
|
||||
$(CC) -c FM4Alg6.cpp
|
||||
|
||||
FM4Alg8.o : FM4Alg8.cpp
|
||||
$(CC) -c FM4Alg8.cpp
|
||||
|
||||
Plucked2.o : Plucked2.cpp
|
||||
$(CC) -c Plucked2.cpp
|
||||
|
||||
SamplFlt.o : SamplFlt.cpp
|
||||
$(CC) -c SamplFlt.cpp
|
||||
|
||||
Sampler.o : Sampler.cpp
|
||||
$(CC) -c Sampler.cpp
|
||||
|
||||
VoicForm.o : VoicForm.cpp
|
||||
$(CC) -c VoicForm.cpp
|
||||
|
||||
MIDIText.o : MIDIText.cpp
|
||||
$(CC) -c MIDIText.cpp
|
||||
|
||||
MIDIInpt.o : MIDIInpt.cpp
|
||||
$(CC) -c MIDIInpt.cpp
|
||||
|
||||
VoicMang.o : VoicMang.cpp
|
||||
$(CC) -c VoicMang.cpp
|
||||
|
||||
Reverb.o : Reverb.cpp
|
||||
$(CC) -c Reverb.cpp
|
||||
|
||||
clean :
|
||||
rm $(INSTR)
|
||||
rm *.o
|
||||
|
||||
cleanIns :
|
||||
rm $(INSTR)
|
||||
|
||||
strip :
|
||||
strip $(INSTR)
|
||||
116
Mandolin.cpp
116
Mandolin.cpp
@@ -1,116 +0,0 @@
|
||||
/********************************************/
|
||||
/* Commuted Mandolin Subclass of enhanced */
|
||||
/* dual plucked-string model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* Controls: CONTROL1 = bodySize */
|
||||
/* CONTROL2 = pluckPosition */
|
||||
/* CONTROL3 = loopGain */
|
||||
/* MOD_WHEEL= deTuning */
|
||||
/* */
|
||||
/* Note: Commuted Synthesis, as with many */
|
||||
/* other WaveGuide techniques, is covered */
|
||||
/* by patents, granted, pending, and/or */
|
||||
/* applied-for. Many are assigned to the */
|
||||
/* Board of Trustees, Stanford University. */
|
||||
/* For information, contact the Office of */
|
||||
/* Technology Licensing, Stanford U. */
|
||||
/********************************************/
|
||||
|
||||
#include "Mandolin.h"
|
||||
|
||||
Mandolin :: Mandolin(MY_FLOAT lowestFreq) : Plucked2(lowestFreq)
|
||||
{
|
||||
soundfile = new RawWave("rawwaves/mandpluk.raw");
|
||||
soundfile->normalize(0.05); /* Empirical hack here */
|
||||
soundfile->setLooping(0);
|
||||
dampTime = 0;
|
||||
waveDone = 1;
|
||||
}
|
||||
|
||||
void Mandolin :: pluck(MY_FLOAT amplitude)
|
||||
{ /* this function gets interesting here, */
|
||||
soundfile->reset(); /* because pluck may be longer than */
|
||||
pluckAmp = amplitude; /* string length, so we just reset the */
|
||||
/* soundfile and add in the pluck in */
|
||||
/* the tick method. */
|
||||
combDelay->setDelay(
|
||||
0.5 * pluckPos * lastLength); /* Set Pick Position */
|
||||
/* which puts zeroes at pos*length */
|
||||
dampTime = (long) lastLength; /* See tick method below */
|
||||
waveDone = 0;
|
||||
}
|
||||
|
||||
void Mandolin :: pluck(MY_FLOAT amplitude, MY_FLOAT position)
|
||||
{
|
||||
pluckPos = position; /* pluck position is zeroes at pos*length */
|
||||
this->pluck(amplitude);
|
||||
}
|
||||
|
||||
void Mandolin :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
this->pluck(amp);
|
||||
#if defined(_debug_)
|
||||
printf("Mandolin : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Mandolin :: setBodySize(MY_FLOAT size)
|
||||
{
|
||||
soundfile->setRate(size);
|
||||
}
|
||||
|
||||
MY_FLOAT Mandolin :: tick()
|
||||
{
|
||||
MY_FLOAT temp = 0;
|
||||
if (!waveDone) {
|
||||
waveDone = soundfile->informTick(); /* as long as it goes . . . */
|
||||
temp = soundfile->lastOut() * pluckAmp; /* scaled pluck excitation */
|
||||
temp = temp - combDelay->tick(temp); /* with comb filtering */
|
||||
}
|
||||
if (dampTime>=0) { /* Damping hack to help avoid */
|
||||
dampTime -= 1; /* overflow on replucking */
|
||||
lastOutput = delayLine->tick( /* Calculate 1st delay */
|
||||
filter->tick( /* filterered reflection */
|
||||
temp + /* plus pluck excitation */
|
||||
(delayLine->lastOut() * 0.7)));
|
||||
lastOutput += delayLine2->tick( /* and 2nd delay */
|
||||
filter2->tick( /* just like the 1st */
|
||||
temp +
|
||||
(delayLine2->lastOut() * 0.7))); /* that's the whole thing!! */
|
||||
}
|
||||
else { /* No damping hack after 1 period */
|
||||
lastOutput = delayLine->tick( /* Calculate 1st delay */
|
||||
filter->tick( /* filtered reflection */
|
||||
temp + /* plus pluck excitation */
|
||||
(delayLine->lastOut()
|
||||
* loopGain)));
|
||||
lastOutput += delayLine2->tick( /* and 2nd delay */
|
||||
filter2->tick( /* just like the 1st */
|
||||
temp +
|
||||
(delayLine2->lastOut()
|
||||
* loopGain)));
|
||||
}
|
||||
lastOutput *= 2.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
void Mandolin :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("Mandolin : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == MIDI_control1)
|
||||
this->setBodySize(value * NORM_7 * 2.0);
|
||||
else if (number == MIDI_control2)
|
||||
this->setPluckPos(value * NORM_7);
|
||||
else if (number == MIDI_control3)
|
||||
this->setBaseLoopGain(0.97 + (value * NORM_7 * 0.03));
|
||||
else if (number == MIDI_mod_wheel)
|
||||
this->setDetune(1.0 - (value * NORM_7 * 0.1));
|
||||
else if (number == MIDI_after_touch)
|
||||
this->pluck(value * NORM_7);
|
||||
else {
|
||||
printf("Mandolin : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
41
Mandolin.h
41
Mandolin.h
@@ -1,41 +0,0 @@
|
||||
/********************************************/
|
||||
/* Commuted Mandolin Subclass of enhanced */
|
||||
/* dual plucked-string model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* Controls: CONTROL1 = bodySize */
|
||||
/* CONTROL2 = pluckPosition */
|
||||
/* CONTROL3 = loopGain */
|
||||
/* MOD_WHEEL= deTuning */
|
||||
/* */
|
||||
/* Note: Commuted Synthesis, as with many */
|
||||
/* other WaveGuide techniques, is covered */
|
||||
/* by patents, granted, pending, and/or */
|
||||
/* applied-for. All are assigned to the */
|
||||
/* Board of Trustees, Stanford University. */
|
||||
/* For information, contact the Office of */
|
||||
/* Technology Licensing, Stanford U. */
|
||||
/********************************************/
|
||||
|
||||
#if !defined(__Mandolin_h)
|
||||
#define __Mandolin_h
|
||||
|
||||
#include "Plucked2.h"
|
||||
#include "RawWave.h"
|
||||
|
||||
class Mandolin : public Plucked2
|
||||
{
|
||||
protected:
|
||||
RawWave *soundfile;
|
||||
long dampTime;
|
||||
int waveDone;
|
||||
public:
|
||||
Mandolin(MY_FLOAT lowestFreq);
|
||||
void pluck(MY_FLOAT amplitude);
|
||||
void pluck(MY_FLOAT amplitude,MY_FLOAT position);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
void setBodySize(MY_FLOAT size);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
111
Marimba.cpp
111
Marimba.cpp
@@ -1,111 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Marimba SubClass of Modal4 Instrument, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = stickHardness */
|
||||
/* CONTROL2 = strikePosition*/
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/*******************************************/
|
||||
|
||||
#include "Marimba.h"
|
||||
|
||||
Marimba :: Marimba() : Modal4()
|
||||
{
|
||||
wave = new RawWave("rawwaves/marmstk1.raw");
|
||||
wave->normalize();
|
||||
wave->setRate(0.5); /* normal stick */
|
||||
this->setRatioAndReson(0, 1.00,0.9996); /* Set all 132.0 */
|
||||
this->setRatioAndReson(1, 3.99,0.9994); /* of our 523.0 */
|
||||
this->setRatioAndReson(2,10.65,0.9994); /* default 1405.0 */
|
||||
this->setRatioAndReson(3,-18.50,0.999); /* resonances 2443.0 */
|
||||
this->setFiltGain(0,0.08); /* and */
|
||||
this->setFiltGain(1,0.02); /* gains */
|
||||
this->setFiltGain(2,0.02); /* for each */
|
||||
this->setFiltGain(3,0.015); /* resonance */
|
||||
directGain = 0.1;
|
||||
multiStrike = 0;
|
||||
}
|
||||
|
||||
Marimba :: ~Marimba()
|
||||
{
|
||||
}
|
||||
|
||||
void Marimba :: setStickHardness(MY_FLOAT hardness)
|
||||
{
|
||||
stickHardness = hardness;
|
||||
wave->setRate(0.25 * pow(4.0,stickHardness));
|
||||
masterGain = 0.1 + (1.8 * stickHardness);
|
||||
}
|
||||
|
||||
void Marimba :: setStrikePosition(MY_FLOAT position)
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
temp2 = position * PI;
|
||||
strikePosition = position; /* Hack only first three modes */
|
||||
temp = sin(temp2);
|
||||
this->setFiltGain(0,0.12 * temp); /* 1st mode function of pos. */
|
||||
temp = sin(0.05 + (3.9 * temp2));
|
||||
this->setFiltGain(1,-0.03 * temp); /* 2nd mode function of pos. */
|
||||
temp = sin(-0.05 + (11 * temp2));
|
||||
this->setFiltGain(2,0.11 * temp); /* 3rd mode function of pos. */
|
||||
}
|
||||
|
||||
void Marimba :: setModulationSpeed(MY_FLOAT mSpeed)
|
||||
{
|
||||
/* don't bother here, marimba decay so fast, mod doesn't make sense */
|
||||
}
|
||||
|
||||
void Marimba :: setModulationDepth(MY_FLOAT mDepth)
|
||||
{
|
||||
}
|
||||
|
||||
void Marimba :: strike(MY_FLOAT amplitude)
|
||||
{
|
||||
int temp;
|
||||
temp = random() >> 26;
|
||||
if (temp < 2) {
|
||||
multiStrike = 1;
|
||||
#if defined(_debug_)
|
||||
printf("striking twice here!!\n");
|
||||
#endif
|
||||
}
|
||||
else if (temp < 1) {
|
||||
multiStrike = 2;
|
||||
#if defined(_debug_)
|
||||
printf("striking three times here!!!\n");
|
||||
#endif
|
||||
}
|
||||
else multiStrike = 0;
|
||||
Modal4::strike(amplitude);
|
||||
}
|
||||
|
||||
void Marimba :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("Marimba : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == MIDI_control1)
|
||||
this->setStickHardness(value * NORM_7);
|
||||
else if (number == MIDI_control2)
|
||||
this->setStrikePosition(value * NORM_7);
|
||||
else if (number == MIDI_control3)
|
||||
vibr->setFreq((value * NORM_7 * 12.0));
|
||||
else if (number == MIDI_mod_wheel)
|
||||
vibrGain = (value * NORM_7);
|
||||
else if (number == MIDI_after_touch)
|
||||
this->strike(value * NORM_7);
|
||||
else {
|
||||
printf("Marimba : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
MY_FLOAT Marimba :: tick()
|
||||
{
|
||||
if (multiStrike>0)
|
||||
if (wave->isAllDone()) {
|
||||
wave->reset();
|
||||
multiStrike -= 1;
|
||||
}
|
||||
return Modal4::tick();
|
||||
}
|
||||
32
Marimba.h
32
Marimba.h
@@ -1,32 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Marimba SubClass of Modal4 Instrument, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = stickHardness */
|
||||
/* CONTROL2 = strikePosition*/
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Marimba_h)
|
||||
#define __Marimba_h
|
||||
|
||||
#include "Modal4.h"
|
||||
|
||||
class Marimba : public Modal4
|
||||
{
|
||||
private:
|
||||
int multiStrike;
|
||||
public:
|
||||
Marimba();
|
||||
~Marimba();
|
||||
void setStickHardness(MY_FLOAT hardness);
|
||||
void setStrikePosition(MY_FLOAT position);
|
||||
void setModulationSpeed(MY_FLOAT mSpeed);
|
||||
void setModulationDepth(MY_FLOAT mDepth);
|
||||
virtual void strike(MY_FLOAT amplitude);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
187
Modal4.cpp
187
Modal4.cpp
@@ -1,187 +0,0 @@
|
||||
/*******************************************/
|
||||
/* 4 Resonance Modal Synthesis Instrument */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains an excitation */
|
||||
/* wavetable, an envelope, and four reso- */
|
||||
/* nances (Non-Sweeping BiQuad Filters). */
|
||||
/*******************************************/
|
||||
|
||||
#include "Modal4.h"
|
||||
|
||||
Modal4 :: Modal4()
|
||||
{
|
||||
envelope = new Envelope;
|
||||
/* We don't make the excitation wave here yet, */
|
||||
/* because we don't know what it's going to be. */
|
||||
filters[0] = new BiQuad;
|
||||
filters[1] = new BiQuad;
|
||||
filters[2] = new BiQuad;
|
||||
filters[3] = new BiQuad;
|
||||
onepole = new OnePole;
|
||||
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
vibr->normalize();
|
||||
vibr->setFreq(6.0);
|
||||
vibrGain = 0.05;
|
||||
|
||||
directGain = 0.0;
|
||||
masterGain = 1.0;
|
||||
baseFreq = 440.0;
|
||||
this->setRatioAndReson(0,1.00,0.9997); /* Set some */
|
||||
this->setRatioAndReson(1,1.30,0.9997); /* silly */
|
||||
this->setRatioAndReson(2,1.77,0.9997); /* default */
|
||||
this->setRatioAndReson(3,2.37,0.9997); /* values here */
|
||||
this->setFiltGain(0,0.01);
|
||||
this->setFiltGain(1,0.01);
|
||||
this->setFiltGain(2,0.01);
|
||||
this->setFiltGain(3,0.01);
|
||||
this->clear();
|
||||
filters[0]->setEqualGainZeroes();
|
||||
filters[1]->setEqualGainZeroes();
|
||||
filters[2]->setEqualGainZeroes();
|
||||
filters[3]->setEqualGainZeroes();
|
||||
stickHardness = 0.5;
|
||||
strikePosition = 0.561;
|
||||
}
|
||||
|
||||
Modal4 :: ~Modal4()
|
||||
{
|
||||
delete envelope;
|
||||
delete wave;
|
||||
delete filters[0];
|
||||
delete filters[1];
|
||||
delete filters[2];
|
||||
delete filters[3];
|
||||
delete onepole;
|
||||
delete vibr;
|
||||
}
|
||||
|
||||
void Modal4 :: clear()
|
||||
{
|
||||
onepole->clear();
|
||||
filters[0]->clear();
|
||||
filters[1]->clear();
|
||||
filters[2]->clear();
|
||||
filters[3]->clear();
|
||||
}
|
||||
|
||||
void Modal4 :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
this->setRatioAndReson(0,ratios[0],resons[0]);
|
||||
this->setRatioAndReson(1,ratios[1],resons[1]);
|
||||
this->setRatioAndReson(2,ratios[2],resons[2]);
|
||||
this->setRatioAndReson(3,ratios[3],resons[3]);
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void Modal4 :: setRatioAndReson(int whichOne, MY_FLOAT ratio,MY_FLOAT reson)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
if (ratio*baseFreq < SRATE_OVER_TWO) {
|
||||
ratios[whichOne] = ratio;
|
||||
}
|
||||
else {
|
||||
temp = ratio;
|
||||
while (temp*baseFreq > SRATE_OVER_TWO) temp *= 0.5;
|
||||
ratios[whichOne] = temp;
|
||||
#if defined(_debug_)
|
||||
printf("Modal4 : Aliasing would occur here, correcting.\n");
|
||||
#endif
|
||||
}
|
||||
resons[whichOne] = reson;
|
||||
if (ratio<0)
|
||||
temp = -ratio;
|
||||
else
|
||||
temp = ratio*baseFreq;
|
||||
filters[whichOne]->setFreqAndReson(temp,reson);
|
||||
}
|
||||
|
||||
void Modal4 :: setMasterGain(MY_FLOAT aGain)
|
||||
{
|
||||
masterGain = aGain;
|
||||
}
|
||||
|
||||
void Modal4 :: setDirectGain(MY_FLOAT aGain)
|
||||
{
|
||||
directGain = aGain;
|
||||
}
|
||||
|
||||
void Modal4 :: setFiltGain(int whichOne, MY_FLOAT gain)
|
||||
{
|
||||
filters[whichOne]->setGain(gain);
|
||||
}
|
||||
|
||||
void Modal4 :: strike(MY_FLOAT amplitude)
|
||||
{
|
||||
int i;
|
||||
MY_FLOAT temp;
|
||||
envelope->setRate(1.0);
|
||||
envelope->setTarget(amplitude);
|
||||
onepole->setPole(1.0 - amplitude);
|
||||
envelope->tick();
|
||||
wave->reset();
|
||||
for (i=0;i<4;i++) {
|
||||
if (ratios[i] < 0)
|
||||
temp = -ratios[i];
|
||||
else
|
||||
temp = ratios[i] * baseFreq;
|
||||
filters[i]->setFreqAndReson(temp,resons[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Modal4 :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->strike(amp);
|
||||
this->setFreq(freq);
|
||||
#if defined(_debug_)
|
||||
printf("Modal4 : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Modal4 :: noteOff(MY_FLOAT amp) /* This calls damp, but inverts the */
|
||||
{ /* meaning of amplitude. */
|
||||
this->damp(1.0 - (amp * 0.03)); /* (high amplitude means fast damping) */
|
||||
#if defined(_debug_)
|
||||
printf("Modal4 : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Modal4 :: damp(MY_FLOAT amplitude)
|
||||
{
|
||||
int i;
|
||||
MY_FLOAT temp;
|
||||
for (i=0;i<4;i++) {
|
||||
if (ratios[i] < 0)
|
||||
temp = -ratios[i];
|
||||
else
|
||||
temp = ratios[i] * baseFreq;
|
||||
filters[i]->setFreqAndReson(temp,resons[i]*amplitude);
|
||||
}
|
||||
}
|
||||
|
||||
void Modal4 :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT Modal4 :: tick()
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
temp = masterGain * onepole->tick(wave->tick() * envelope->tick());
|
||||
temp2 = filters[0]->tick(temp);
|
||||
temp2 += filters[1]->tick(temp);
|
||||
temp2 += filters[2]->tick(temp);
|
||||
temp2 += filters[3]->tick(temp);
|
||||
temp2 = temp2 - (temp2 * directGain);
|
||||
temp2 += directGain * temp;
|
||||
|
||||
if (vibrGain != 0.0) {
|
||||
temp = 1.0 + (vibr->tick() * vibrGain); /* Calculate AM */
|
||||
temp2 = temp * temp2; /* and apply to master out */
|
||||
}
|
||||
|
||||
lastOutput = temp2 * 2.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
52
Modal4.h
52
Modal4.h
@@ -1,52 +0,0 @@
|
||||
/*******************************************/
|
||||
/* 4 Resonance Modal Synthesis Instrument */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains an excitation */
|
||||
/* wavetable, an envelope, and four reso- */
|
||||
/* nances (Non-Sweeping BiQuad Filters). */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Modal4_h)
|
||||
#define __Modal4_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "Envelope.h"
|
||||
#include "RawWave.h"
|
||||
#include "RawLoop.h"
|
||||
#include "BiQuad.h"
|
||||
#include "OnePole.h"
|
||||
|
||||
class Modal4 : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
Envelope *envelope;
|
||||
RawWave *wave;
|
||||
BiQuad *filters[4];
|
||||
OnePole *onepole;
|
||||
RawLoop *vibr;
|
||||
MY_FLOAT vibrGain;
|
||||
MY_FLOAT masterGain;
|
||||
MY_FLOAT directGain;
|
||||
MY_FLOAT stickHardness;
|
||||
MY_FLOAT strikePosition;
|
||||
MY_FLOAT baseFreq;
|
||||
MY_FLOAT ratios[4];
|
||||
MY_FLOAT resons[4];
|
||||
public:
|
||||
Modal4();
|
||||
~Modal4();
|
||||
void clear();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void setRatioAndReson(int whichOne, MY_FLOAT ratio, MY_FLOAT reson);
|
||||
void setMasterGain(MY_FLOAT aGain);
|
||||
void setDirectGain(MY_FLOAT aGain);
|
||||
void setFiltGain(int whichOne, MY_FLOAT gain);
|
||||
virtual void strike(MY_FLOAT amplitude);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
void damp(MY_FLOAT amplitude);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
84
Modulatr.cpp
84
Modulatr.cpp
@@ -1,84 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Modulator Class, Perry R. Cook, 1995-96*/
|
||||
/* This Object combines random and */
|
||||
/* periodic modulations to give a nice */
|
||||
/* natural human modulation function. */
|
||||
/*******************************************/
|
||||
|
||||
#define POLE_POS 0.999
|
||||
#define RND_SCALE 10.0
|
||||
|
||||
#include "Modulatr.h"
|
||||
|
||||
Modulatr :: Modulatr()
|
||||
{
|
||||
vibwave = new RawWave("rawwaves/sinewave.raw");
|
||||
vibwave->normalize();
|
||||
vibwave->setFreq(6.0);
|
||||
vibwave->setLooping(1);
|
||||
vibAmt = 0.04;
|
||||
noise = new SubNoise(330);
|
||||
rndAmt = 0.005;
|
||||
onepole = new OnePole;
|
||||
onepole->setPole(POLE_POS);
|
||||
onepole->setGain(rndAmt * RND_SCALE);
|
||||
}
|
||||
|
||||
Modulatr :: ~Modulatr()
|
||||
{
|
||||
delete vibwave;
|
||||
delete noise;
|
||||
delete onepole;
|
||||
}
|
||||
|
||||
void Modulatr :: reset()
|
||||
{
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
void Modulatr :: setVibFreq(double vibFreq)
|
||||
{
|
||||
vibwave->setFreq(vibFreq);
|
||||
}
|
||||
|
||||
void Modulatr :: setVibAmt(double vibAmount)
|
||||
{
|
||||
vibAmt = vibAmount;
|
||||
}
|
||||
|
||||
void Modulatr :: setRndAmt(double rndAmount)
|
||||
{
|
||||
rndAmt = rndAmount;
|
||||
onepole->setGain(RND_SCALE * rndAmt);
|
||||
}
|
||||
|
||||
double Modulatr :: tick()
|
||||
{
|
||||
lastOutput = vibAmt * vibwave->tick(); /* Compute periodic and */
|
||||
lastOutput += onepole->tick(noise->tick()); /* random modulations */
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
double Modulatr :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
Modulatr testMod;
|
||||
FILE *fd;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
fd = fopen("test.raw","wb");
|
||||
|
||||
for (i=0;i<20000;i++) {
|
||||
data = testMod.tick() * 32000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
36
Modulatr.h
36
Modulatr.h
@@ -1,36 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Modulator Class, Perry R. Cook, 1995-96*/
|
||||
/* This Object combines random and */
|
||||
/* periodic modulations to give a nice */
|
||||
/* natural human modulation function. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Modulatr_h)
|
||||
#define __Modulatr_h
|
||||
|
||||
#include "Object.h"
|
||||
#include "RawWave.h"
|
||||
#include "SubNoise.h"
|
||||
#include "OnePole.h"
|
||||
|
||||
class Modulatr : public Object
|
||||
{
|
||||
protected:
|
||||
RawWave *vibwave;
|
||||
SubNoise *noise;
|
||||
OnePole *onepole;
|
||||
double vibAmt;
|
||||
double rndAmt;
|
||||
double lastOutput;
|
||||
public:
|
||||
Modulatr();
|
||||
~Modulatr();
|
||||
void reset();
|
||||
void setVibFreq(double vibFreq);
|
||||
void setVibAmt(double vibAmount);
|
||||
void setRndAmt(double rndAmount);
|
||||
double tick();
|
||||
double lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
108
Moog1.cpp
108
Moog1.cpp
@@ -1,108 +0,0 @@
|
||||
/******************************************/
|
||||
/* Test Sampler Subclass of */
|
||||
/* Sampling Synthesizer Class */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = filterQ */
|
||||
/* CONTROL2 = filterRate */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#include "Moog1.h"
|
||||
|
||||
Moog1 :: Moog1() : SamplFlt()
|
||||
{
|
||||
attacks[0] = new RawWave("rawwaves/mandpluk.raw");
|
||||
loops[0] = new RawWave("rawwaves/impuls20.raw");
|
||||
loops[1] = new RawWave("rawwaves/sinewave.raw"); /* Steal one for vibrato */
|
||||
attacks[0]->normalize();
|
||||
loops[0]->normalize();
|
||||
loops[0]->setLooping(1);
|
||||
loops[1]->normalize();
|
||||
loops[1]->setLooping(1);
|
||||
loops[1]->setFreq(6.122);
|
||||
adsr->setAll(0.05,0.00003,0.6,0.0002);
|
||||
filterQ = 0.85;
|
||||
filterRate = 0.0001;
|
||||
modDepth = 0.0;
|
||||
}
|
||||
|
||||
Moog1 :: ~Moog1()
|
||||
{
|
||||
delete attacks[0];
|
||||
delete loops[0];
|
||||
delete loops[1];
|
||||
}
|
||||
|
||||
void Moog1 :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
attacks[0]->setFreq(baseFreq * 0.01);
|
||||
loops[0]->setFreq(baseFreq);
|
||||
}
|
||||
|
||||
void Moog1 :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
|
||||
this->setFreq(freq);
|
||||
this->keyOn();
|
||||
attackGain = amp * 0.5;
|
||||
loopGain = amp;
|
||||
|
||||
temp = filterQ+0.05;
|
||||
filters[0]->setStates(2000,temp,2.0 * (1.0 - temp));
|
||||
filters[1]->setStates(2000,temp,2.0 * (1.0 - temp));
|
||||
temp = filterQ+0.099;
|
||||
filters[0]->setTargets( 0,temp,2.0 * (1.0 - temp));
|
||||
filters[1]->setTargets( 0,temp,2.0 * (1.0 - temp));
|
||||
filters[0]->setSweepRate(filterRate * RATE_NORM);
|
||||
filters[1]->setSweepRate(filterRate * RATE_NORM);
|
||||
#if defined(_debug_)
|
||||
printf("Moog1 : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Moog1 :: setModulationSpeed(MY_FLOAT mSpeed)
|
||||
{
|
||||
loops[1]->setFreq(mSpeed);
|
||||
}
|
||||
|
||||
void Moog1 :: setModulationDepth(MY_FLOAT mDepth)
|
||||
{
|
||||
modDepth = mDepth * 0.5;
|
||||
}
|
||||
|
||||
void Moog1 :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("Moog1 : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == MIDI_control1)
|
||||
filterQ = 0.80 + (0.1 * value * NORM_7);
|
||||
else if (number == MIDI_control2)
|
||||
filterRate = (value * NORM_7 * 0.0002);
|
||||
else if (number == MIDI_control3)
|
||||
this->setModulationSpeed(value * NORM_7 * 12.0);
|
||||
else if (number == MIDI_mod_wheel)
|
||||
this->setModulationDepth(value * NORM_7);
|
||||
else if (number == MIDI_after_touch)
|
||||
adsr->setTarget(value * NORM_7);
|
||||
else {
|
||||
printf("Moog1 : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
MY_FLOAT Moog1 :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
|
||||
if (modDepth!=0.0) {
|
||||
temp = loops[1]->tick() * modDepth;
|
||||
loops[0]->setFreq(baseFreq * (1.0 + temp));
|
||||
}
|
||||
lastOutput = SamplFlt :: tick();
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
34
Moog1.h
34
Moog1.h
@@ -1,34 +0,0 @@
|
||||
/******************************************/
|
||||
/* Moog1 Subclass of */
|
||||
/* Sampling Synthesizer Class */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = filterQ */
|
||||
/* CONTROL2 = filterRate */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Moog1_h)
|
||||
#define __Moog1_h
|
||||
|
||||
#include "SamplFlt.h"
|
||||
|
||||
class Moog1 : public SamplFlt
|
||||
{
|
||||
private:
|
||||
MY_FLOAT modDepth;
|
||||
MY_FLOAT filterQ;
|
||||
MY_FLOAT filterRate;
|
||||
public:
|
||||
Moog1();
|
||||
~Moog1();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
void setModulationSpeed(MY_FLOAT mSpeed);
|
||||
void setModulationDepth(MY_FLOAT mDepth);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
163
NIFileIn.cpp
163
NIFileIn.cpp
@@ -1,163 +0,0 @@
|
||||
/*******************************************/
|
||||
/* NonInterpolating One-Shot Raw Sound- */
|
||||
/* file Class, by Perry R. Cook, 1995-96 */
|
||||
/* This Object can open a raw 16bit data */
|
||||
/* (signed integers) file, and play back */
|
||||
/* the data once, with no interpolation */
|
||||
/* on playback. Once finished, it closes */
|
||||
/* the file, the file is reopened with */
|
||||
/* the reset() method. */
|
||||
/* This is useful for small memory model, */
|
||||
/* applications, or for streaming from */
|
||||
/* disk (and generally non real-time */
|
||||
/* applications). */
|
||||
/*******************************************/
|
||||
|
||||
#include "NIFileIn.h"
|
||||
|
||||
NIFileIn :: NIFileIn(char *fileName)
|
||||
{
|
||||
long i;
|
||||
|
||||
strcpy(fileNm,fileName);
|
||||
|
||||
myFile = fopen(fileNm,"rb");
|
||||
if (!myFile) {
|
||||
printf("Couldn't find soundfile %s !!!!!!!!\n",fileName);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (fread(&data,2,1,myFile)) i++;
|
||||
length = i;
|
||||
fseek(myFile,0,0);
|
||||
time = 0.0;
|
||||
rate = 1.0;
|
||||
lastTime = 0;
|
||||
finished = 0;
|
||||
gain = 1.0;
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
NIFileIn :: ~NIFileIn()
|
||||
{
|
||||
this->finish();
|
||||
}
|
||||
|
||||
void NIFileIn :: reset()
|
||||
{
|
||||
if (finished) {
|
||||
myFile = fopen(fileNm,"rb");
|
||||
}
|
||||
fseek(myFile,0,0);
|
||||
|
||||
printf("Resetting\n");
|
||||
time = 0.0;
|
||||
lastTime = 0;
|
||||
finished = 0;
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
void NIFileIn :: normalize()
|
||||
{
|
||||
this->normalize(1.0);
|
||||
}
|
||||
|
||||
void NIFileIn :: normalize(MY_FLOAT newPeak)
|
||||
{
|
||||
long i;
|
||||
FILE *fd;
|
||||
|
||||
gain = 0.0;
|
||||
|
||||
fd = fopen(fileNm,"rb");
|
||||
for (i=0;i<length;i++) {
|
||||
fread(&data,2,1,fd);
|
||||
if (fabs(data) > gain)
|
||||
gain = fabs(data);
|
||||
}
|
||||
if (gain > 0.0) {
|
||||
gain = newPeak / gain;
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
void NIFileIn :: setRate(MY_FLOAT aRate)
|
||||
{
|
||||
rate = aRate;
|
||||
}
|
||||
|
||||
void NIFileIn :: finish()
|
||||
{
|
||||
finished = 1;
|
||||
lastOutput = 0.0;
|
||||
if (myFile) {
|
||||
fclose(myFile);
|
||||
myFile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
MY_FLOAT NIFileIn :: tick()
|
||||
{
|
||||
this->informTick();
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
int NIFileIn :: informTick()
|
||||
{
|
||||
long temp;
|
||||
|
||||
if (!finished) {
|
||||
|
||||
time += rate; /* Update current time */
|
||||
|
||||
if (time >= length) { /* Check for end of sound */
|
||||
time = length - 1; /* stick at end */
|
||||
finished = 1; /* Information for one-shot use */
|
||||
fclose(myFile);
|
||||
myFile = 0;
|
||||
}
|
||||
else {
|
||||
temp = (long) time; /* Integer part of time address */
|
||||
if (temp > lastTime) { /* If we cross next sample time */
|
||||
lastTime = temp;
|
||||
fread(&data,2,1,myFile); /* Snarf next sample from file */
|
||||
lastOutput = data * gain; /* And save as non-interpolated data */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
MY_FLOAT NIFileIn :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
NIFileIn oneShot("rawwaves/mandpluk.raw");
|
||||
FILE *fd;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
fd = fopen("test.raw","wb");
|
||||
oneShot.setRate(1.0);
|
||||
while (!oneShot.informTick()) {
|
||||
data = oneShot.lastOut();
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
oneShot.reset();
|
||||
oneShot.setRate(0.5);
|
||||
for (i=0;i<16384;i++) {
|
||||
data = oneShot.tick();
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
|
||||
47
NIFileIn.h
47
NIFileIn.h
@@ -1,47 +0,0 @@
|
||||
/*******************************************/
|
||||
/* NonInterpolating One-Shot Raw Sound- */
|
||||
/* file Class, by Perry R. Cook, 1995-96 */
|
||||
/* This Object can open a raw 16bit data */
|
||||
/* (signed integers) file, and play back */
|
||||
/* the data once, with no interpolation */
|
||||
/* on playback. Once finished, it closes */
|
||||
/* the file, the file is reopened with */
|
||||
/* the reset() method. */
|
||||
/* This is useful for small memory model, */
|
||||
/* applications, or for streaming from */
|
||||
/* disk (and generally non real-time */
|
||||
/* applications). */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__NIFileIn_h)
|
||||
#define __NIFileIn_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class NIFileIn : public Object
|
||||
{
|
||||
protected:
|
||||
long length;
|
||||
long lastTime;
|
||||
int finished;
|
||||
short data;
|
||||
char fileNm[128];
|
||||
FILE *myFile;
|
||||
MY_FLOAT rate;
|
||||
MY_FLOAT time;
|
||||
MY_FLOAT gain;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
NIFileIn(char *fileName);
|
||||
~NIFileIn();
|
||||
void reset();
|
||||
void normalize();
|
||||
void normalize(MY_FLOAT newPeak);
|
||||
void setRate(MY_FLOAT aRate);
|
||||
void finish();
|
||||
MY_FLOAT tick();
|
||||
int informTick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
119
NIWave1S.cpp
119
NIWave1S.cpp
@@ -1,119 +0,0 @@
|
||||
/*******************************************/
|
||||
/* NonInterpolating One-Shot Raw Sound- */
|
||||
/* file Class, by Perry R. Cook, 1995-96 */
|
||||
/* This Object can open a raw 16bit data */
|
||||
/* (signed integers) file, and play back */
|
||||
/* the data once (again when reset), with */
|
||||
/* no interpolation on playback. */
|
||||
/*******************************************/
|
||||
|
||||
#include "NIWave1S.h"
|
||||
|
||||
NIWave1S :: NIWave1S(char *fileName)
|
||||
{
|
||||
long i;
|
||||
short temp;
|
||||
FILE *fd;
|
||||
fd = fopen(fileName,"rb");
|
||||
if (!fd) {
|
||||
printf("Couldn't find soundfile %s !!!!!!!!\n",fileName);
|
||||
exit(0);
|
||||
}
|
||||
i = 0;
|
||||
while (fread(&temp,2,1,fd)) i++;
|
||||
length = i;
|
||||
fseek(fd,0,0);
|
||||
data = (MY_FLOAT *) malloc(MY_FLOAT_SIZE * (length + 1));
|
||||
i = 0;
|
||||
while (fread(&temp,2,1,fd)) {
|
||||
data[i] = temp;
|
||||
i++;
|
||||
}
|
||||
data[length] = data[length-1];
|
||||
fclose(fd);
|
||||
time = 0.0;
|
||||
rate = 1.0;
|
||||
}
|
||||
|
||||
void NIWave1S :: reset()
|
||||
{
|
||||
time = 0.0;
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
void NIWave1S :: normalize()
|
||||
{
|
||||
this->normalize(1.0);
|
||||
}
|
||||
|
||||
void NIWave1S :: normalize(MY_FLOAT newPeak)
|
||||
{
|
||||
long i;
|
||||
MY_FLOAT max = 0.0;
|
||||
for (i=0;i<=length;i++)
|
||||
if (fabs(data[i]) > max)
|
||||
max = fabs(data[i]);
|
||||
if (max > 0.0) {
|
||||
max = 1.0 / max;
|
||||
max *= newPeak;
|
||||
for (i=0;i<=length;i++)
|
||||
data[i] *= max;
|
||||
}
|
||||
}
|
||||
|
||||
void NIWave1S :: setRate(MY_FLOAT aRate)
|
||||
{
|
||||
rate = aRate;
|
||||
}
|
||||
|
||||
MY_FLOAT NIWave1S :: tick()
|
||||
{
|
||||
this->informTick();
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
int NIWave1S :: informTick()
|
||||
{
|
||||
int allDone = 0;
|
||||
long temp;
|
||||
|
||||
time += rate; /* Update current time */
|
||||
|
||||
if (time >= length) { /* Check for end of sound */
|
||||
time = length-1; /* stick at end */
|
||||
allDone = 1; /* Information for one-shot use */
|
||||
}
|
||||
temp = (long) time; /* Integer part of time address */
|
||||
lastOutput = data[temp]; /* Get non-interpolated data */
|
||||
|
||||
return allDone;
|
||||
}
|
||||
|
||||
MY_FLOAT NIWave1S :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
NIWave1S oneShot("rawwaves/mandpluk.raw");
|
||||
FILE *fd;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
fd = fopen("test.raw","wb");
|
||||
for (i=0;i<8192;i++) {
|
||||
data = oneShot.tick();
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
oneShot.reset();
|
||||
oneShot.setRate(0.5);
|
||||
for (i=0;i<16384;i++) {
|
||||
data = oneShot.tick();
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
34
NIWave1S.h
34
NIWave1S.h
@@ -1,34 +0,0 @@
|
||||
/*******************************************/
|
||||
/* NonInterpolating One-Shot Raw Sound- */
|
||||
/* file Class, by Perry R. Cook, 1995-96 */
|
||||
/* This Object can open a raw 16bit data */
|
||||
/* (signed integers) file, and play back */
|
||||
/* the data once (again when reset), with */
|
||||
/* no interpolation on playback. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__NIWave1S_h)
|
||||
#define __NIWave1S_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class NIWave1S : public Object
|
||||
{
|
||||
protected:
|
||||
long length;
|
||||
MY_FLOAT *data;
|
||||
MY_FLOAT rate;
|
||||
MY_FLOAT time;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
NIWave1S(char *fileName);
|
||||
void reset();
|
||||
void normalize();
|
||||
void normalize(MY_FLOAT newPeak);
|
||||
void setRate(MY_FLOAT aRate);
|
||||
MY_FLOAT tick();
|
||||
int informTick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
52
Noise.cpp
52
Noise.cpp
@@ -1,52 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Noise Generator Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* White noise as often as you like. */
|
||||
/*******************************************/
|
||||
|
||||
#include "Noise.h"
|
||||
|
||||
Noise :: Noise() : Object()
|
||||
{
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
Noise :: ~Noise()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* THIS IS FOR TURBO C */
|
||||
/* Constant = 1.0 / 16384.0 */
|
||||
/* #define ONE_OVER_RANDLIMIT 0.00006103516 */
|
||||
|
||||
|
||||
/* THIS IS FOR UNIX, NeXT and SGI */
|
||||
#define ONE_OVER_RANDLIMIT 0.00000000093132258
|
||||
|
||||
MY_FLOAT Noise :: tick()
|
||||
{
|
||||
/* THIS ONE IS TURBO C */
|
||||
/* lastOutput = (MY_FLOAT) random(32767) - 16384.0; */
|
||||
|
||||
/* THIS IS FOR UNIX, NeXT and SGI */
|
||||
|
||||
lastOutput = (MY_FLOAT) random() - 1073741823.0;
|
||||
lastOutput *= ONE_OVER_RANDLIMIT;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT Noise :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main ************************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
long i;
|
||||
Noise test;
|
||||
for (i=0;i<20;i++) printf("%lf\n",test.tick());
|
||||
}
|
||||
*/
|
||||
23
Noise.h
23
Noise.h
@@ -1,23 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Noise Generator Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* White noise as often as you like. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Noise_h)
|
||||
#define __Noise_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class Noise : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Noise();
|
||||
~Noise();
|
||||
virtual MY_FLOAT tick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
29
Object.cpp
29
Object.cpp
@@ -1,29 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Object Class, by Perry R. Cook, 1995-96*/
|
||||
/* This is mostly here for compatibility */
|
||||
/* with Objective C. We'll also stick */
|
||||
/* global defines here, so everyone will */
|
||||
/* see them. */
|
||||
/*******************************************/
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
|
||||
/* This is just here for compatibility and convenience,
|
||||
so there's no need to do any real calculations.
|
||||
I do set up some redefinable variables here. */
|
||||
|
||||
|
||||
Object :: Object()
|
||||
{
|
||||
MIDI_mod_wheel = 1; /* Controller # 1 */
|
||||
MIDI_control1 = 2; /* Breath Pressure */
|
||||
MIDI_control2 = 4; /* Foot Control */
|
||||
MIDI_control3 = 11; /* Expression Pedal */
|
||||
MIDI_after_touch = 128; /* Channel Pressure -> new controller */
|
||||
}
|
||||
|
||||
Object :: ~Object()
|
||||
{
|
||||
}
|
||||
|
||||
91
Object.h
91
Object.h
@@ -1,91 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Object Class, by Perry R. Cook, 1995-96*/
|
||||
/* This is mostly here for compatibility */
|
||||
/* with Objective C. We'll also stick */
|
||||
/* global defines here, so everyone will */
|
||||
/* see them. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Object_h)
|
||||
#define __Object_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
int MIDI_control1;
|
||||
int MIDI_control2;
|
||||
int MIDI_control3;
|
||||
int MIDI_mod_wheel;
|
||||
int MIDI_after_touch;
|
||||
protected:
|
||||
Object();
|
||||
~Object();
|
||||
};
|
||||
|
||||
/* Only use one of __SGI_ __NeXT_ __DOS_ */
|
||||
/* And choice of __SGI_REALTIME or not */
|
||||
|
||||
#define __SGI_
|
||||
#define __SGI_REALTIME
|
||||
/* #define __NeXT_ */
|
||||
|
||||
/* SRATE here is 44100, others are derived accordingly */
|
||||
/* #define SRATE 44100.0
|
||||
#define SRATE_OVER_TWO 22050.0
|
||||
#define ONE_OVER_SRATE 0.00002267573696
|
||||
#define RATE_NORM 0.5
|
||||
*/
|
||||
|
||||
/* SRATE here is 22050, others are derived accordingly */
|
||||
#define SRATE 22050.0
|
||||
#define SRATE_OVER_TWO 11025.0
|
||||
#define ONE_OVER_SRATE 0.00004535147392
|
||||
#define RATE_NORM 1.0
|
||||
|
||||
|
||||
/* SRATE here is 8k, others are derived accordingly */
|
||||
/* #define SRATE 8000.0
|
||||
#define SRATE_OVER_TWO 4000
|
||||
#define ONE_OVER_SRATE 0.00012500000000
|
||||
#define RATE_NORM 2.75625
|
||||
*/
|
||||
/* RATE_NORM is 22050 / 8000 */
|
||||
|
||||
/* Yer Basic Trigonometric constants */
|
||||
#define PI 3.14159265359
|
||||
#define TWO_PI 6.28318530718
|
||||
#define ONE_OVER_TWO_PI 0.15915494309
|
||||
|
||||
/* States for Envelopes, etc. */
|
||||
|
||||
#define ATTACK 0
|
||||
#define DECAY 1
|
||||
#define SUSTAIN 2
|
||||
#define RELEASE 3
|
||||
|
||||
/* Machine dependent stuff, possibly useful for optimization */
|
||||
/* for example, changing double to float here increases */
|
||||
/* performance (speed) by a whopping 4-6% on 486-flavor machines */
|
||||
/* BUT!! a change from float to double here increases speed by */
|
||||
/* 30% or so on SGI machines */
|
||||
/* #define MY_FLOAT float */
|
||||
/* #define MY_FLOAT_SIZE 4 */
|
||||
|
||||
#define MY_FLOAT double
|
||||
#define MY_FLOAT_SIZE 8
|
||||
|
||||
/* Debugging define, causes massive printf's to come out. */
|
||||
/* Also enables timing calculations in WaveOut class, other stuff. */
|
||||
/* #define _debug_ 1 */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define NORM_7 0.0078125
|
||||
/* this is 1/128 for MIDI normalization*/
|
||||
|
||||
#endif
|
||||
81
OnePole.cpp
81
OnePole.cpp
@@ -1,81 +0,0 @@
|
||||
/*******************************************/
|
||||
/* One Pole Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* The parameter gain is an additional */
|
||||
/* gain parameter applied to the filter */
|
||||
/* on top of the normalization that takes */
|
||||
/* place automatically. So the net max */
|
||||
/* gain through the system equals the */
|
||||
/* value of gain. sgain is the combina- */
|
||||
/* tion of gain and the normalization */
|
||||
/* parameter, so if you set the poleCoeff */
|
||||
/* to alpha, sgain is always set to */
|
||||
/* gain * (1.0 - fabs(alpha)). */
|
||||
/*******************************************/
|
||||
|
||||
#include "OnePole.h"
|
||||
|
||||
OnePole :: OnePole() : Filter()
|
||||
{
|
||||
poleCoeff = 0.9;
|
||||
gain = 1.0;
|
||||
sgain = 0.1;
|
||||
outputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
|
||||
outputs[0] = 0.0;
|
||||
}
|
||||
|
||||
OnePole :: ~OnePole()
|
||||
{
|
||||
free(outputs);
|
||||
}
|
||||
|
||||
void OnePole :: clear()
|
||||
{
|
||||
outputs[0] = 0.0;
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
void OnePole :: setPole(MY_FLOAT aValue)
|
||||
{
|
||||
poleCoeff = aValue;
|
||||
if (poleCoeff > 0.0) /* Normalize gain to 1.0 max */
|
||||
sgain = gain * (1.0 - poleCoeff);
|
||||
else
|
||||
sgain = gain * (1.0 + poleCoeff);
|
||||
}
|
||||
|
||||
void OnePole :: setGain(MY_FLOAT aValue)
|
||||
{
|
||||
gain = aValue;
|
||||
if (poleCoeff > 0.0)
|
||||
sgain = gain * (1.0 - poleCoeff); /* Normalize gain to 1.0 max */
|
||||
else
|
||||
sgain = gain * (1.0 + poleCoeff);
|
||||
}
|
||||
|
||||
MY_FLOAT OnePole :: tick(MY_FLOAT sample) /* Perform Filter Operation */
|
||||
{
|
||||
outputs[0] = (sgain * sample) + (poleCoeff * outputs[0]);
|
||||
lastOutput = outputs[0];
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main ************************/
|
||||
/*
|
||||
#include <stdio.h>
|
||||
|
||||
void main()
|
||||
{
|
||||
long i;
|
||||
OnePole test;
|
||||
test.setPole(0.99);
|
||||
for (i=0;i<150;i++) printf("%lf ",test.tick(1.0));
|
||||
printf("\n\n");
|
||||
|
||||
test.clear();
|
||||
test.setPole(0.9);
|
||||
test.setGain(2.0);
|
||||
for (i=0;i<150;i++) printf("%lf ",test.tick(0.5));
|
||||
printf("\n\n");
|
||||
}
|
||||
*/
|
||||
35
OnePole.h
35
OnePole.h
@@ -1,35 +0,0 @@
|
||||
/*******************************************/
|
||||
/* One Pole Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* The parameter gain is an additional */
|
||||
/* gain parameter applied to the filter */
|
||||
/* on top of the normalization that takes */
|
||||
/* place automatically. So the net max */
|
||||
/* gain through the system equals the */
|
||||
/* value of gain. sgain is the combina- */
|
||||
/* tion of gain and the normalization */
|
||||
/* parameter, so if you set the poleCoeff */
|
||||
/* to alpha, sgain is always set to */
|
||||
/* gain * (1.0 - fabs(alpha)). */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__OnePole_h)
|
||||
#define __OnePole_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class OnePole : public Filter
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT poleCoeff;
|
||||
MY_FLOAT sgain;
|
||||
public:
|
||||
OnePole();
|
||||
~OnePole();
|
||||
void clear();
|
||||
void setPole(MY_FLOAT aValue);
|
||||
void setGain(MY_FLOAT aValue);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
64
OneZero.cpp
64
OneZero.cpp
@@ -1,64 +0,0 @@
|
||||
/*******************************************/
|
||||
/* One Zero Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* The parameter gain is an additional */
|
||||
/* gain parameter applied to the filter */
|
||||
/* on top of the normalization that takes */
|
||||
/* place automatically. So the net max */
|
||||
/* gain through the system equals the */
|
||||
/* value of gain. sgain is the combina- */
|
||||
/* tion of gain and the normalization */
|
||||
/* parameter, so if you set the poleCoeff */
|
||||
/* to alpha, sgain is always set to */
|
||||
/* gain / (1.0 - fabs(alpha)). */
|
||||
/*******************************************/
|
||||
|
||||
#include "OneZero.h"
|
||||
|
||||
OneZero :: OneZero()
|
||||
{
|
||||
gain = 1.0;
|
||||
zeroCoeff = 1.0;
|
||||
sgain = 0.5;
|
||||
inputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
|
||||
this->clear();
|
||||
}
|
||||
|
||||
OneZero :: ~OneZero()
|
||||
{
|
||||
free(inputs);
|
||||
}
|
||||
|
||||
void OneZero :: clear()
|
||||
{
|
||||
inputs[0] = 0.0;
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
void OneZero :: setGain(MY_FLOAT aValue)
|
||||
{
|
||||
gain = aValue;
|
||||
if (zeroCoeff > 0.0) /* Normalize gain to 1.0 max */
|
||||
sgain = gain / (1.0 + zeroCoeff);
|
||||
else
|
||||
sgain = gain / (1.0 - zeroCoeff);
|
||||
}
|
||||
|
||||
void OneZero :: setCoeff(MY_FLOAT aValue)
|
||||
{
|
||||
zeroCoeff = aValue;
|
||||
if (zeroCoeff > 0.0) /* Normalize gain to 1.0 max */
|
||||
sgain = gain / (1.0 + zeroCoeff);
|
||||
else
|
||||
sgain = gain / (1.0 - zeroCoeff);
|
||||
}
|
||||
|
||||
MY_FLOAT OneZero :: tick(MY_FLOAT sample) /* Perform Filter Operation */
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
temp = sgain * sample;
|
||||
lastOutput = (inputs[0] * zeroCoeff) + temp;
|
||||
inputs[0] = temp;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
35
OneZero.h
35
OneZero.h
@@ -1,35 +0,0 @@
|
||||
/*******************************************/
|
||||
/* One Zero Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* The parameter gain is an additional */
|
||||
/* gain parameter applied to the filter */
|
||||
/* on top of the normalization that takes */
|
||||
/* place automatically. So the net max */
|
||||
/* gain through the system equals the */
|
||||
/* value of gain. sgain is the combina- */
|
||||
/* tion of gain and the normalization */
|
||||
/* parameter, so if you set the poleCoeff */
|
||||
/* to alpha, sgain is always set to */
|
||||
/* gain / (1.0 - fabs(alpha)). */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__OneZero_h)
|
||||
#define __OneZero_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class OneZero : public Filter
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT zeroCoeff;
|
||||
MY_FLOAT sgain;
|
||||
public:
|
||||
OneZero();
|
||||
~OneZero();
|
||||
void clear();
|
||||
void setGain(MY_FLOAT aValue);
|
||||
void setCoeff(MY_FLOAT aValue);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
50
PercFlut.cpp
50
PercFlut.cpp
@@ -1,50 +0,0 @@
|
||||
/******************************************/
|
||||
/* Percussive Flute Subclass */
|
||||
/* of Algorithm 4 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/******************************************/
|
||||
|
||||
#include "PercFlut.h"
|
||||
|
||||
PercFlut :: PercFlut() : FM4Alg4()
|
||||
{
|
||||
this->loadWaves("rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw");
|
||||
|
||||
this->setRatio(0,1.50 );
|
||||
this->setRatio(1,3.00 * 0.995);
|
||||
this->setRatio(2,2.99 * 1.005);
|
||||
this->setRatio(3,6.00 * 0.997);
|
||||
gains[0] = __FM4Op_gains[99];
|
||||
gains[1] = __FM4Op_gains[71];
|
||||
gains[2] = __FM4Op_gains[93];
|
||||
gains[3] = __FM4Op_gains[85];
|
||||
adsr[0]->setAll(0.001,0.001,__FM4Op_susLevels[14],0.001);
|
||||
adsr[1]->setAll(0.05,0.0001,__FM4Op_susLevels[13],0.0001);
|
||||
adsr[2]->setAll(0.05,0.0020,__FM4Op_susLevels[11],0.001);
|
||||
adsr[3]->setAll(0.05,0.0010,__FM4Op_susLevels[13],0.005);
|
||||
twozero->setGain(0.0);
|
||||
modDepth = 0.005;
|
||||
}
|
||||
|
||||
void PercFlut :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
}
|
||||
|
||||
void PercFlut :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
gains[0] = amp * __FM4Op_gains[99];
|
||||
gains[1] = amp * __FM4Op_gains[71];
|
||||
gains[2] = amp * __FM4Op_gains[93];
|
||||
gains[3] = amp * __FM4Op_gains[85];
|
||||
this->setFreq(freq);
|
||||
this->keyOn();
|
||||
#if defined(_debug_)
|
||||
printf("PercFlut : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
21
PercFlut.h
21
PercFlut.h
@@ -1,21 +0,0 @@
|
||||
/******************************************/
|
||||
/* Percussive Flute Subclass */
|
||||
/* of Algorithm 4 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__PercFlut_h)
|
||||
#define __PercFlut_h
|
||||
|
||||
#include "FM4Alg4.h"
|
||||
|
||||
class PercFlut : public FM4Alg4
|
||||
{
|
||||
public:
|
||||
PercFlut();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
};
|
||||
|
||||
#endif
|
||||
189
PhonTabl.h
189
PhonTabl.h
@@ -1,189 +0,0 @@
|
||||
double phonGains[32][2] =
|
||||
{{1.0,0.0}, // eee
|
||||
{1.0,0.0}, // ihh
|
||||
{1.5,0.0}, // ehh
|
||||
{1.0,0.0}, // aaa
|
||||
|
||||
{0.5,0.0}, // ahh
|
||||
{0.5,0.0}, // aww
|
||||
{0.5,0.0}, // ohh
|
||||
{0.5,0.0}, // uhh
|
||||
|
||||
{0.5,0.0}, // uuu
|
||||
{0.15,0.0}, // ooo
|
||||
{0.15,0.0}, // rrr
|
||||
{6.0,0.0}, // lll
|
||||
|
||||
{1.0,0.0}, // mmm
|
||||
{1.0,0.0}, // nnn
|
||||
{1.0,0.0}, // nng
|
||||
{1.0,0.0}, // ngg
|
||||
|
||||
{0.0,1.0}, // fff
|
||||
{0.0,1.0}, // sss
|
||||
{0.0,1.0}, // thh
|
||||
{0.0,1.0}, // shh
|
||||
|
||||
{0.0,0.2}, // xxx
|
||||
{0.0,0.003}, // hee
|
||||
{0.0,0.001}, // hoo
|
||||
{0.0,0.002}, // hah
|
||||
|
||||
{1.0,0.4}, // bbb
|
||||
{4.0,0.1}, // ddd
|
||||
{1.0,0.4}, // jjj
|
||||
{1.0,0.4}, // ggg
|
||||
|
||||
{1.0,0.1}, // vvv
|
||||
{1.0,0.1}, // zzz
|
||||
{1.0,0.1}, // thz
|
||||
{1.0,0.1} // zhh
|
||||
};
|
||||
|
||||
double phonParams[32][4][3] =
|
||||
{{ { 273,0.996, 0}, // eee (beet)
|
||||
{2086,0.945, -16},
|
||||
{2754,0.979, -12},
|
||||
{3270,0.440, -17}},
|
||||
{ { 385,0.987, 0}, // ihh (bit)
|
||||
{2056,0.930, -20},
|
||||
{2587,0.890, -20},
|
||||
{3150,0.400, -20}},
|
||||
{ { 515,0.977, 0}, // ehh (bet)
|
||||
{1805,0.810, -10},
|
||||
{2526,0.875, -10},
|
||||
{3103,0.400, -13}},
|
||||
{ { 773,0.950, 0}, // aaa (bat)
|
||||
{1676,0.830, -6},
|
||||
{2380,0.880, -20},
|
||||
{3027,0.600, -20}},
|
||||
|
||||
{ { 770,0.950, 0}, // ahh (father)
|
||||
{1153,0.970, -3},
|
||||
{2450,0.780, -20},
|
||||
{3140,0.800, -32}},
|
||||
{ { 637,0.910, 0}, // aww (bought)
|
||||
{ 895,0.900, -3},
|
||||
{2556,0.950, -17},
|
||||
{3070,0.910, -20}},
|
||||
{ { 637,0.910, 0}, // ohh (bone) NOTE:: same as aww (bought)
|
||||
{ 895,0.900, -3},
|
||||
{2556,0.950, -17},
|
||||
{3070,0.910, -20}},
|
||||
{ { 561,0.965, 0}, // uhh (but)
|
||||
{1084,0.930, -10},
|
||||
{2541,0.930, -15},
|
||||
{3345,0.900, -20}},
|
||||
|
||||
{ { 515,0.976, 0}, // uuu (foot)
|
||||
{1031,0.950, -3},
|
||||
{2572,0.960, -11},
|
||||
{3345,0.960, -20}},
|
||||
{ { 349,0.986, 0}, // ooo (boot)
|
||||
{ 918,0.940, -10},
|
||||
{2350,0.960, -17},
|
||||
{2731,0.950, -23}},
|
||||
{ { 394,0.959, 0}, // rrr (bird)
|
||||
{1297,0.780, -6},
|
||||
{1441,0.980, -6},
|
||||
{2754,0.950, -30}},
|
||||
{ { 462,0.940, 0}, // lll (lull)
|
||||
{2754,0.900, -30},
|
||||
{3406,0.100, -30},
|
||||
{3755,0.100, -30}},
|
||||
|
||||
{ { 265,0.987, 0}, // mmm (mom)
|
||||
{1176,0.940, -22},
|
||||
{2352,0.970, -20},
|
||||
{3277,0.940, -31}},
|
||||
{ { 204,0.980, 0}, // nnn (nun)
|
||||
{1570,0.940, -15},
|
||||
{2481,0.980, -12},
|
||||
{3133,0.800, -30}},
|
||||
{ { 204,0.980, 0}, // nng (sang) NOTE:: same as nnn
|
||||
{1570,0.940, -15},
|
||||
{2481,0.980, -12},
|
||||
{3133,0.800, -30}},
|
||||
{ { 204,0.980, 0}, // ngg (bong) NOTE:: same as nnn
|
||||
{1570,0.940, -15},
|
||||
{2481,0.980, -12},
|
||||
{3133,0.800, -30}},
|
||||
|
||||
{ {1000,0.300, -10}, // fff
|
||||
{2800,0.860, -10},
|
||||
{7425,0.740, 0},
|
||||
{8140,0.860, 0}},
|
||||
{ {2000,0.700, -20}, // sss
|
||||
{5257,0.750, -15},
|
||||
{7171,0.840, -3},
|
||||
{9000,0.900, 0}},
|
||||
{ { 100,0.900, 0}, // thh
|
||||
{4000,0.500, -20},
|
||||
{5500,0.500, -15},
|
||||
{8000,0.400, -20}},
|
||||
{ {2693,0.940, 0}, // shh
|
||||
{4000,0.720, -10},
|
||||
{6123,0.870, -10},
|
||||
{7755,0.750, -18}},
|
||||
|
||||
{ {1000,0.300, -10}, // xxx NOTE:: Not Really Done Yet
|
||||
{2800,0.860, -10},
|
||||
{7425,0.740, 0},
|
||||
{8140,0.860, 0}},
|
||||
{ { 273,0.996, 0}, // hee (beet) (noisy eee)
|
||||
{2086,0.945, -16},
|
||||
{2754,0.979, -12},
|
||||
{3270,0.440, -17}},
|
||||
{ { 349,0.986, 0}, // hoo (boot) (noisy ooo)
|
||||
{ 918,0.940, -10},
|
||||
{2350,0.960, -17},
|
||||
{2731,0.950, -23}},
|
||||
{ { 770,0.950, 0}, // hah (father) (noisy ahh)
|
||||
{1153,0.970, -3},
|
||||
{2450,0.780, -20},
|
||||
{3140,0.800, -32}},
|
||||
|
||||
{ {2000,0.700, -20}, // bbb NOTE:: Not Really Done Yet
|
||||
{5257,0.750, -15},
|
||||
{7171,0.840, -3},
|
||||
{9000,0.900, 0}},
|
||||
{ { 100,0.900, 0}, // ddd NOTE:: Not Really Done Yet
|
||||
{4000,0.500, -20},
|
||||
{5500,0.500, -15},
|
||||
{8000,0.400, -20}},
|
||||
{ {2693,0.940, 0}, // jjj NOTE:: Not Really Done Yet
|
||||
{4000,0.720, -10},
|
||||
{6123,0.870, -10},
|
||||
{7755,0.750, -18}},
|
||||
{ {2693,0.940, 0}, // ggg NOTE:: Not Really Done Yet
|
||||
{4000,0.720, -10},
|
||||
{6123,0.870, -10},
|
||||
{7755,0.750, -18}},
|
||||
|
||||
{ {2000,0.700, -20}, // vvv NOTE:: Not Really Done Yet
|
||||
{5257,0.750, -15},
|
||||
{7171,0.840, -3},
|
||||
{9000,0.900, 0}},
|
||||
{ { 100,0.900, 0}, // zzz NOTE:: Not Really Done Yet
|
||||
{4000,0.500, -20},
|
||||
{5500,0.500, -15},
|
||||
{8000,0.400, -20}},
|
||||
{ {2693,0.940, 0}, // thz NOTE:: Not Really Done Yet
|
||||
{4000,0.720, -10},
|
||||
{6123,0.870, -10},
|
||||
{7755,0.750, -18}},
|
||||
{ {2693,0.940, 0}, // zhh NOTE:: Not Really Done Yet
|
||||
{4000,0.720, -10},
|
||||
{6123,0.870, -10},
|
||||
{7755,0.750, -18}}
|
||||
};
|
||||
|
||||
char phonemes[32][4] =
|
||||
{"eee","ihh","ehh","aaa",
|
||||
"ahh","aww","ohh","uhh",
|
||||
"uuu","ooo","rrr","lll",
|
||||
"mmm","nnn","nng","ngg",
|
||||
"fff","sss","thh","shh",
|
||||
"xxx","hee","hoo","hah",
|
||||
"bbb","ddd","jjj","ggg",
|
||||
"vvv","zzz","thz","zhh"};
|
||||
84
Plucked.cpp
84
Plucked.cpp
@@ -1,84 +0,0 @@
|
||||
/******************************************/
|
||||
/* Karplus-Strong plucked string model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* There exist at least two patents, */
|
||||
/* assigned to Stanford, bearing the */
|
||||
/* names of Karplus and/or Strong. */
|
||||
/******************************************/
|
||||
|
||||
#include "Plucked.h"
|
||||
|
||||
Plucked :: Plucked(MY_FLOAT lowestFreq)
|
||||
{
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
loopGain = 0.999;
|
||||
delayLine = new DLineA(length);
|
||||
loopFilt = new OneZero;
|
||||
pickFilt = new OnePole;
|
||||
noise = new Noise;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
Plucked :: ~Plucked()
|
||||
{
|
||||
delete delayLine;
|
||||
delete loopFilt;
|
||||
delete pickFilt;
|
||||
delete noise;
|
||||
}
|
||||
|
||||
void Plucked :: clear()
|
||||
{
|
||||
delayLine->clear();
|
||||
loopFilt->clear();
|
||||
pickFilt->clear();
|
||||
}
|
||||
|
||||
void Plucked :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
MY_FLOAT delay;
|
||||
delay = ((MY_FLOAT) SRATE / frequency) - 0.5; /* length - delays */
|
||||
delayLine->setDelay(delay);
|
||||
loopGain = 0.995 + (frequency * 0.000005);
|
||||
if (loopGain>1.0) loopGain = 0.99999;
|
||||
}
|
||||
|
||||
void Plucked :: pluck(MY_FLOAT amplitude)
|
||||
{
|
||||
long i;
|
||||
pickFilt->setPole(0.999 - (amplitude*0.15));
|
||||
pickFilt->setGain(amplitude * 0.5);
|
||||
for (i=0;i<length;i++)
|
||||
delayLine->tick(delayLine->lastOut() * 0.6 /* fill delay with noise */
|
||||
+ pickFilt->tick(noise->tick())); /* additively with current */
|
||||
/* contents */
|
||||
}
|
||||
|
||||
void Plucked :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
this->pluck(amp);
|
||||
#if defined(_debug_)
|
||||
printf("Plucked : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Plucked :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
loopGain = 1.0 - amp;
|
||||
#if defined(_debug_)
|
||||
printf("Plucked : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
MY_FLOAT Plucked :: tick()
|
||||
{
|
||||
lastOutput = delayLine->tick( /* check this out, */
|
||||
loopFilt->tick( /* here's the whole inner */
|
||||
delayLine->lastOut() /* loop of the instrument!! */
|
||||
* loopGain));
|
||||
lastOutput *= 3.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
40
Plucked.h
40
Plucked.h
@@ -1,40 +0,0 @@
|
||||
/******************************************/
|
||||
/* Karplus-Strong plucked string model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* There exist at least two patents, */
|
||||
/* assigned to Stanford, bearing the */
|
||||
/* names of Karplus and/or Strong. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Plucked_h)
|
||||
#define __Plucked_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "DLineA.h"
|
||||
#include "OneZero.h"
|
||||
#include "OnePole.h"
|
||||
#include "Noise.h"
|
||||
|
||||
class Plucked : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
DLineA *delayLine;
|
||||
OneZero *loopFilt;
|
||||
OnePole *pickFilt;
|
||||
Noise *noise;
|
||||
long length;
|
||||
MY_FLOAT loopGain;
|
||||
public:
|
||||
Plucked(MY_FLOAT lowestFreq);
|
||||
~Plucked();
|
||||
void clear();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void pluck(MY_FLOAT amplitude);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
90
Plucked2.cpp
90
Plucked2.cpp
@@ -1,90 +0,0 @@
|
||||
/******************************************/
|
||||
/* Enhanced (Jaffe-Smith, Smith, others) */
|
||||
/* Karplus-Strong plucked model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* This is the super-class, with no */
|
||||
/* excitation specified. So this one by */
|
||||
/* itself doesn't make any sound. */
|
||||
/******************************************/
|
||||
|
||||
#include "Plucked2.h"
|
||||
|
||||
Plucked2 :: Plucked2(MY_FLOAT lowestFreq)
|
||||
{
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
baseLoopGain = 0.995;
|
||||
loopGain = 0.999;
|
||||
delayLine = new DLineA(length);
|
||||
delayLine2 = new DLineA(length);
|
||||
combDelay = new DLineL(length);
|
||||
filter = new OneZero;
|
||||
filter2 = new OneZero;
|
||||
pluckAmp = 0.3;
|
||||
pluckPos = 0.4;
|
||||
detuning = 0.995;
|
||||
lastFreq = lowestFreq * 2.0;
|
||||
lastLength = length * 0.5;
|
||||
}
|
||||
|
||||
Plucked2 :: ~Plucked2()
|
||||
{
|
||||
delete delayLine;
|
||||
delete delayLine2;
|
||||
delete combDelay;
|
||||
delete filter;
|
||||
delete filter2;
|
||||
}
|
||||
|
||||
void Plucked2 :: clear()
|
||||
{
|
||||
delayLine->clear();
|
||||
delayLine2->clear();
|
||||
combDelay->clear();
|
||||
filter->clear();
|
||||
filter2->clear();
|
||||
}
|
||||
|
||||
void Plucked2 :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
lastFreq = frequency;
|
||||
lastLength = ((MY_FLOAT) SRATE / lastFreq); /* length - delays */
|
||||
delayLine->setDelay((lastLength / detuning) - 0.5);
|
||||
delayLine2->setDelay((lastLength * detuning) - 0.5);
|
||||
loopGain = baseLoopGain + (frequency * 0.000005);
|
||||
if (loopGain>1.0) loopGain = 0.99999;
|
||||
}
|
||||
|
||||
void Plucked2 :: setDetune(MY_FLOAT detune)
|
||||
{
|
||||
detuning = detune;
|
||||
delayLine->setDelay((lastLength / detuning) - 0.5);
|
||||
delayLine2->setDelay((lastLength * detuning) - 0.5);
|
||||
}
|
||||
|
||||
void Plucked2 :: setFreqAndDetune(MY_FLOAT frequency,MY_FLOAT detune)
|
||||
{
|
||||
lastFreq = frequency;
|
||||
detuning = detune;
|
||||
this->setFreq(frequency);
|
||||
}
|
||||
|
||||
void Plucked2 :: setPluckPos(MY_FLOAT position)
|
||||
{
|
||||
pluckPos = position;
|
||||
}
|
||||
|
||||
void Plucked2 :: setBaseLoopGain(MY_FLOAT aGain)
|
||||
{
|
||||
baseLoopGain = aGain;
|
||||
loopGain = baseLoopGain + (lastFreq * 0.000005);
|
||||
if (loopGain>1.0) loopGain = 0.99999;
|
||||
}
|
||||
|
||||
void Plucked2 :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
loopGain = (1.0 - amp) * 0.5;
|
||||
#if defined(_debug_)
|
||||
printf("Plucked2 : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
46
Plucked2.h
46
Plucked2.h
@@ -1,46 +0,0 @@
|
||||
/******************************************/
|
||||
/* Enhanced (Jaffe-Smith, Smith, others) */
|
||||
/* Karplus-Strong plucked model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* This is the super-class, with no */
|
||||
/* excitation specified. So this one by */
|
||||
/* itself doesn't make any sound. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Plucked2_h)
|
||||
#define __Plucked2_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "DLineL.h"
|
||||
#include "DLineA.h"
|
||||
#include "OneZero.h"
|
||||
|
||||
class Plucked2 : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
DLineA *delayLine;
|
||||
DLineA *delayLine2;
|
||||
DLineL *combDelay;
|
||||
OneZero *filter;
|
||||
OneZero *filter2;
|
||||
long length;
|
||||
MY_FLOAT loopGain;
|
||||
MY_FLOAT baseLoopGain;
|
||||
MY_FLOAT lastFreq;
|
||||
MY_FLOAT lastLength;
|
||||
MY_FLOAT detuning;
|
||||
MY_FLOAT pluckAmp;
|
||||
MY_FLOAT pluckPos;
|
||||
public:
|
||||
Plucked2(MY_FLOAT lowestFreq);
|
||||
~Plucked2();
|
||||
void clear();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void setDetune(MY_FLOAT detune);
|
||||
void setFreqAndDetune(MY_FLOAT frequency, MY_FLOAT detune);
|
||||
void setPluckPos(MY_FLOAT position);
|
||||
void setBaseLoopGain(MY_FLOAT aGain);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
};
|
||||
|
||||
#endif
|
||||
117
README
Normal file
117
README
Normal file
@@ -0,0 +1,117 @@
|
||||
The Synthesis ToolKit in C++ (STK)
|
||||
|
||||
By Perry R. Cook and Gary P. Scavone, 1995-2002.
|
||||
|
||||
This distribution of the Synthesis ToolKit in C++ (STK) contains the following:
|
||||
|
||||
include: STK class header files
|
||||
src: STK class source files
|
||||
rawwaves: STK audio files (1-channel, 16-bit, big-endian)
|
||||
doc: STK documentation
|
||||
projects: example STK programs
|
||||
|
||||
Please read the Legal and Ethical notes near the bottom of this document.
|
||||
|
||||
For compiling and installing STK, see the INSTALL file in this directory.
|
||||
|
||||
|
||||
OVERVIEW:
|
||||
|
||||
The Synthesis ToolKit in C++ (STK) is a set of open source audio signal processing and algorithmic synthesis classes written in C++. STK was designed to facilitate rapid development of music synthesis and audio processing software, with an emphasis on cross-platform functionality, realtime control, ease of use, and educational example code. The Synthesis ToolKit is extremely portable (it's mostly platform-independent C and C++ code), and it's completely user-extensible (all source included, no unusual libraries, and no hidden drivers). We like to think that this increases the chances that our programs will still work in another 5-10 years. In fact, the ToolKit has been working continuously for nearly 8 years now. STK currently runs with "realtime" support (audio and MIDI) on SGI (Irix), Linux, Macintosh OS X, and Windows computer platforms. Generic, non-realtime support has been tested under NeXTStep, Sun, and other platforms and should work with any standard C++ compiler.
|
||||
|
||||
The Synthesis ToolKit is free for non-commercial use. The only parts of the Synthesis ToolKit that are platform-dependent concern real-time audio and MIDI input and output, and that is taken care of with a few special classes. The interface for MIDI input and the simple Tcl/Tk graphical user interfaces (GUIs) provided is the same, so it's easy to experiment in real time using either the GUIs or MIDI. The Synthesis ToolKit can generate simultaneous SND (AU), WAV, AIFF, and MAT-file output soundfile formats (as well as realtime sound output), so you can view your results using one of a large variety of sound/signal analysis tools already available (e.g. Snd, Cool Edit, Matlab).
|
||||
|
||||
The Synthesis Toolkit is not one particular program. Rather, it is a set of C++ classes that you can use to create your own programs. A few example applications are provided to demonstrate some of the ways to use the classes. If you have specific needs, you will probably have to either modify the example programs or write a new program altogether. Further, the example programs don't have a fancy GUI wrapper. If you feel the need to have a "drag and drop" graphical patching GUI, you probably don't want to use the ToolKit. Spending hundreds of hours making platform-dependent graphics code would go against one of the fundamental design goals of the ToolKit - platform independence.
|
||||
|
||||
For those instances where a simple GUI with sliders and buttons is helpful, we use Tcl/Tk (http://dev.scriptics.com) which is freely distributed for all the supported ToolKit platforms. A number of Tcl/Tk GUI scripts are distributed with the ToolKit release. For control, the Synthesis Toolkit uses raw MIDI (on supported platforms), and SKINI (Synthesis ToolKit Instrument Network Interface, a MIDI-like text message synthesis control format).
|
||||
|
||||
|
||||
SYSTEM REQUIREMENTS:
|
||||
|
||||
See the individual README's (eg. README-linux) in the /doc directory for platform specific information and system requirements. In general, you will use the configure script to create Makefiles on unix platforms or the VC++ workspace files to compile the example programs. To use the Tcl/Tk GUIs, you will need Tcl/Tk version 8.0 or higher.
|
||||
|
||||
|
||||
WHAT'S NEW:
|
||||
|
||||
Despite being available in one form or another since 1996, we still consider STK to be alpha software. Thus, backward compatability has not been a priority. Please read the Release Notes to see what has changed since the last release.
|
||||
|
||||
The control message handling scheme has been simplified greatly through the use of the Messager class. It is now possible to have access to simultaneous piped, socketed, and/or MIDI input control messages. In most cases, this should eliminate the use of the Md2Skini program.
|
||||
|
||||
Realtime audio input capabilities were added to STK with release 3.0, though the behavior of such is very hardware dependent. Under Linux and Irix, audio input and output are possible with very low latency. Using the Windoze DirectSound API, minimum dependable output sound latency seems to be around 20 milliseconds or so, while input sound latency is on the order of a hundred milliseconds or more!
|
||||
|
||||
As mentioned above, it is possible to record the audio ouput of an STK program to .snd, .wav, .raw, .aif, and .mat (Matlab MAT-file) output file types. Though somewhat obsolete, the program Md2Skini can be used to write SKINI scorefiles from realtime MIDI input. Finally, STK should compile with non-realtime functionality on any platform with a generic C++ compiler.
|
||||
|
||||
For those who wish to make a library from the core STK classes, the configure script generates a Makefile in the src directory that will accomplish that (Linux, SGI, and Macintosh OS X only).
|
||||
|
||||
|
||||
DISCLAIMER:
|
||||
|
||||
You probably already guessed this, but just to be sure, we don't guarantee anything works. :-) It's free ... what do you expect? If you find a bug, please let us know and we'll try to correct it. You can also make suggestions, but again, no guarantees. Send email to prc@cs.princeton.edu and gary@ccrma.stanford.edu.
|
||||
|
||||
|
||||
LEGAL AND ETHICAL:
|
||||
|
||||
This software was designed and created to be made publicly available for free, primarily for academic purposes, so if you use it, pass it on with this documentation, and for free.
|
||||
|
||||
If you make a million dollars with it, give us some. If you make compositions with it, put us in the program notes.
|
||||
|
||||
Some of the concepts are covered by various patents, some known to us and likely others which are unknown. Many of the ones known to us are administered by the Stanford Office of Technology and Licensing.
|
||||
|
||||
The good news is that large hunks of the techniques used here are public domain. To avoid subtle legal issues, we'll not state what's freely useable here, but we'll try to note within the various classes where certain things are likely to be protected by patents.
|
||||
|
||||
|
||||
FURTHER READING:
|
||||
|
||||
For complete documentation on this ToolKit, the classes, etc., see the doc directory of the distribution or surf to http://www-ccrma.stanford.edu/software/stk/. Also check the platform specific README's for specific system requirements.
|
||||
|
||||
|
||||
PERRY'S NOTES FROM THE ORIGINAL DISTRIBUTION:
|
||||
|
||||
This whole world was created with no particular hardware in mind. These examples are intended to be tutorial in nature, as a platform for the continuation of my research, and as a possible starting point for a software synthesis system. The basic motivation was to create the necessary unit generators to do the synthesis, processing, and control that I want to do and teach about. Little thought for optimization was given (see Object.cpp), and therefore improvements, especially speed enhancements, should be possible with these classes. It was written with some basic concepts in mind about how to let compilers optimize.
|
||||
|
||||
Your question at this point might be, "But Perry, with CMix, CMusic, CSound, CShells, CMonkeys, etc. already cluttering the landscape, why a new set of stupid C functions for music synthesis and processing?" The answers lie below.
|
||||
|
||||
1) I needed to port many of the things I've done
|
||||
into something which is generic enough to port
|
||||
further to different machines.
|
||||
|
||||
2) I really plan to document this stuff, so that
|
||||
you don't have to be me to figure out what's
|
||||
going on. (I'll probably be sorry I said this
|
||||
in a couple of years, when even I can't figure
|
||||
out what I was thinking.)
|
||||
|
||||
3) The classic difficulties most people have in
|
||||
trying to implement physical models are:
|
||||
|
||||
A) They have trouble understanding the papers,
|
||||
and/or in turning the theory into practice.
|
||||
|
||||
B) The Physical Model instruments are a pain to get
|
||||
to oscillate, and coming up with stable and
|
||||
meaningful parameter values is required to
|
||||
get the models to work at all.
|
||||
|
||||
This set of C++ unit generators and instruments
|
||||
might help to diminish the scores of emails I
|
||||
get asking what to do with those block diagrams
|
||||
I put in my papers.
|
||||
|
||||
4) I wanted to try some new stuff with modal synthesis,
|
||||
and implement some classic FM patches as well.
|
||||
|
||||
5) I wanted to reimplement, and newly implement
|
||||
more of the intelligent and physical performer
|
||||
models I've talked about in some of my papers.
|
||||
But I wanted to do it in a portable way, and in
|
||||
such a way that I can hook up modules quickly.
|
||||
I also wanted to make these instruments connectable
|
||||
to such player objects, so folks like Brad Garton
|
||||
who really think a lot about the players can connect
|
||||
them to my instruments, a lot about which I think.
|
||||
|
||||
6) More rationalizations to follow . . .
|
||||
|
||||
|
||||
|
||||
|
||||
117
README.txt
117
README.txt
@@ -1,117 +0,0 @@
|
||||
TK96CPP
|
||||
A ToolKit of Audio Synthesis Classes
|
||||
and Instruments in C++
|
||||
Perry Cook, 1995-96
|
||||
|
||||
Please read the Legal and Ethical notes at the
|
||||
bottom of this document.
|
||||
|
||||
For instant fun, if you get it to compile (see
|
||||
below) type TestAllNext or TestAllSGIRT. The
|
||||
former makes sound files of each instrument and
|
||||
saves them under the instrument name. The latter
|
||||
plays in real time from a SKINI scorefile.
|
||||
|
||||
For even more potential fun, try the GUI and MIDI
|
||||
interface demos in the directory TCLSpecs. MIDI
|
||||
is SGI specific for today, look for more support
|
||||
later. TCL works on SGI, maybe elsewhere, but
|
||||
you must have and install Tcl/TK.
|
||||
|
||||
For more documentation on this ToolKit, the classes,
|
||||
etc, read the file HIERARCH.txt and the individual
|
||||
class definitions.
|
||||
|
||||
SGI vs. NeXT vs. Intel vs. the world:
|
||||
See Object.h and Makefile for machine-specific
|
||||
items.
|
||||
|
||||
Initial public release. Some objects still beta.
|
||||
|
||||
This whole world was created with no particular
|
||||
hardware in mind. These examples are intended
|
||||
to be tutorial in nature, as a platform for the
|
||||
continuation of my research, and as a possible
|
||||
starting point for a software synthesis system.
|
||||
The basic motivation was to create the necessary
|
||||
unit generators to do the synthesis, processing,
|
||||
and control that I want to do and teach about.
|
||||
Little thought for optimization was given (see
|
||||
Object.cpp), and therefore improvements, especially
|
||||
speed enhancements, should be possible with
|
||||
these classes. It was written with some basic
|
||||
concepts in mind about how to let compilers
|
||||
optimize (see Adrian Freed's home page for some
|
||||
nice experience-based thoughts on that topic).
|
||||
|
||||
Your question at this point might be, "But Perry,
|
||||
with CMix, CMusic, CSound, CShells, CMonkeys, etc.
|
||||
already cluttering the landscape, why a new set
|
||||
of stupid C functions for music synthesis and
|
||||
processing?" The answers lie below.
|
||||
|
||||
1) I needed to port many of the things I've done
|
||||
into something which is generic enough to port
|
||||
further to different machines.
|
||||
|
||||
2) I really plan to document this stuff, so that
|
||||
you don't have to be me to figure out what's
|
||||
going on. (I'll probably be sorry I said this
|
||||
in a couple of years, when even I can't figure
|
||||
out what I was thinking.)
|
||||
|
||||
3) The classic difficulties most people have in
|
||||
trying to implement physical models are:
|
||||
|
||||
A) They have trouble understanding the papers,
|
||||
and/or in turning the theory into practice.
|
||||
|
||||
B) The Physical Model instruments are a pain to get
|
||||
to oscillate, and coming up with stable and
|
||||
meaningful parameter values is required to
|
||||
get the models to work at all.
|
||||
|
||||
This set of C++ unitgenerators and instruments
|
||||
might help to diminish the scores of EMails I
|
||||
get asking what to do with those block diagrams
|
||||
I put in my papers.
|
||||
|
||||
4) I wanted to try some new stuff with modal synthesis,
|
||||
and implement some classic FM patches as well.
|
||||
|
||||
5) I wanted to reimplement, and newly implement
|
||||
more of the intelligent and physical performer
|
||||
models I've talked about in some of my papers.
|
||||
But I wanted to do it in a portable way, and in
|
||||
such a way that I can hook up modules quickly.
|
||||
I also wanted to make these instruments connectable
|
||||
to such player objects, so folks like Brad Garton
|
||||
who really think a lot about the players can connect
|
||||
them to my instruments, a lot about which I think.
|
||||
|
||||
6) More rationalizations to follow . . .
|
||||
|
||||
***********************************************************
|
||||
Legal and Ethical:
|
||||
|
||||
This software was designed and created to be
|
||||
made publicly available for free, primarily for
|
||||
academic purposes, so if you use it, pass it on
|
||||
with this documentation, and for free.
|
||||
|
||||
If you make a million dollars with it, give me some.
|
||||
If you make compositions with it, put me in the
|
||||
program notes.
|
||||
|
||||
Some of the concepts are covered by various patents,
|
||||
some known to me and likely others which are unknown.
|
||||
Many of the ones known to me are administered by the
|
||||
Stanford Office of Technology and Licensing.
|
||||
|
||||
The good news is that large hunks of the techniques
|
||||
used here are public domain. To avoid subtle legal
|
||||
issues, I'll not state what's freely useable here,
|
||||
but I'll try to note within the various classes
|
||||
where certain things are likely to be protected by
|
||||
patents.
|
||||
***********************************************************
|
||||
155
RawLoop.cpp
155
RawLoop.cpp
@@ -1,155 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Raw Looped Soundfile Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This Object can open a raw 16bit data */
|
||||
/* (signed integers) file, and play back */
|
||||
/* the data, looping only, with linear */
|
||||
/* interpolation on playback. */
|
||||
/*******************************************/
|
||||
|
||||
#include "RawLoop.h"
|
||||
|
||||
RawLoop :: RawLoop(char *fileName)
|
||||
{
|
||||
long i;
|
||||
short temp;
|
||||
FILE *fd;
|
||||
fd = fopen(fileName,"rb");
|
||||
if (!fd) {
|
||||
printf("Couldn't find soundfile %s !!!!!!!!\n",fileName);
|
||||
exit(0);
|
||||
}
|
||||
i = 0;
|
||||
while (fread(&temp,2,1,fd)) i++;
|
||||
length = i;
|
||||
fseek(fd,0,0);
|
||||
data = (MY_FLOAT *) malloc(MY_FLOAT_SIZE * (length + 1));
|
||||
i = 0;
|
||||
while (fread(&temp,2,1,fd)) {
|
||||
data[i] = temp;
|
||||
i++;
|
||||
}
|
||||
data[length] = data[0];
|
||||
fclose(fd);
|
||||
time = 0.0;
|
||||
phaseOffset = 0.0;
|
||||
rate = 1.0;
|
||||
}
|
||||
|
||||
RawLoop :: ~RawLoop()
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
|
||||
void RawLoop :: reset()
|
||||
{
|
||||
time = 0.0;
|
||||
lastOutput = 0.0;
|
||||
}
|
||||
|
||||
void RawLoop :: normalize()
|
||||
{
|
||||
this->normalize(1.0);
|
||||
}
|
||||
|
||||
void RawLoop :: normalize(MY_FLOAT newPeak)
|
||||
{
|
||||
long i;
|
||||
MY_FLOAT max = 0.0;
|
||||
for (i=0;i<=length;i++)
|
||||
if (fabs(data[i]) > max)
|
||||
max = fabs(data[i]);
|
||||
if (max > 0.0) {
|
||||
max = 1.0 / max;
|
||||
max *= newPeak;
|
||||
for (i=0;i<=length;i++)
|
||||
data[i] *= max;
|
||||
}
|
||||
}
|
||||
|
||||
void RawLoop :: setRate(MY_FLOAT aRate)
|
||||
{
|
||||
rate = aRate;
|
||||
}
|
||||
|
||||
void RawLoop :: setFreq(MY_FLOAT aFreq)
|
||||
{
|
||||
rate = length * ONE_OVER_SRATE * aFreq;
|
||||
}
|
||||
|
||||
void RawLoop :: addTime(MY_FLOAT aTime) /* Add an absolute time */
|
||||
{ /* in samples */
|
||||
time += aTime;
|
||||
}
|
||||
|
||||
void RawLoop :: addPhase(MY_FLOAT anAngle) /* Add a time in cycles */
|
||||
{ /* Cycles here means */
|
||||
time += length * anAngle; /* 1.0 = length */
|
||||
}
|
||||
|
||||
void RawLoop :: addPhaseOffset(MY_FLOAT anAngle)
|
||||
{ /* Add a phase offset */
|
||||
phaseOffset = length * anAngle; /* in cycles, where */
|
||||
} /* 1.0 = length */
|
||||
|
||||
MY_FLOAT RawLoop :: tick()
|
||||
{
|
||||
long temp;
|
||||
|
||||
MY_FLOAT temp_time, alpha;
|
||||
|
||||
time += rate; /* Update current time */
|
||||
|
||||
while (time >= length) /* Check for end of sound */
|
||||
time -= length; /* loop back to beginning */
|
||||
while (time < 0.0) /* Check for end of sound */
|
||||
time += length; /* loop back to beginning */
|
||||
|
||||
temp_time = time;
|
||||
|
||||
if (phaseOffset != 0.0) {
|
||||
temp_time += phaseOffset; /* Add phase offset */
|
||||
while (temp_time >= length) /* Check for end of sound */
|
||||
temp_time -= length; /* loop back to beginning */
|
||||
while (temp_time < 0.0) /* Check for end of sound */
|
||||
temp_time += length; /* loop back to beginning */
|
||||
}
|
||||
|
||||
temp = (long) temp_time; /* Integer part of time address */
|
||||
alpha = temp_time - (MY_FLOAT) temp; /* fractional part of time address */
|
||||
lastOutput = data[temp]; /* Do linear interpolation */
|
||||
lastOutput = lastOutput + /* same as alpha*data[temp+1] */
|
||||
(alpha * (data[temp+1]
|
||||
- lastOutput)); /* + (1-alpha)data[temp] */
|
||||
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT RawLoop :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
RawLoop loopWave("rawwaves/sinewave.raw");
|
||||
FILE *fd;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
loopWave.setFreq(5500);
|
||||
fd = fopen("test.raw","wb");
|
||||
for (i=0;i<4096;i++) {
|
||||
data = loopWave.tick();
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
loopWave.setFreq(2750);
|
||||
for (i=0;i<4096;i++) {
|
||||
data = loopWave.tick();
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
39
RawLoop.h
39
RawLoop.h
@@ -1,39 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Raw Looped Soundfile Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This Object can open a raw 16bit data */
|
||||
/* (signed integers) file, and play back */
|
||||
/* the data, looping only, with linear */
|
||||
/* interpolation on playback. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__RawLoop_h)
|
||||
#define __RawLoop_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class RawLoop : public Object
|
||||
{
|
||||
protected:
|
||||
long length;
|
||||
MY_FLOAT *data;
|
||||
MY_FLOAT rate;
|
||||
MY_FLOAT time;
|
||||
MY_FLOAT phaseOffset;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
RawLoop(char *fileName);
|
||||
~RawLoop();
|
||||
void reset();
|
||||
void normalize();
|
||||
void normalize(MY_FLOAT newPeak);
|
||||
void setRate(MY_FLOAT aRate);
|
||||
void setFreq(MY_FLOAT aFreq);
|
||||
void addTime(MY_FLOAT aTime);
|
||||
void addPhase(MY_FLOAT anAngle);
|
||||
void addPhaseOffset(MY_FLOAT anAngle);
|
||||
MY_FLOAT tick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
235
RawWave.cpp
235
RawWave.cpp
@@ -1,235 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Raw Soundfile Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This Object can open a raw 16bit data */
|
||||
/* (signed integers) file, and play back */
|
||||
/* the data once or looping, with linear */
|
||||
/* interpolation on playback. */
|
||||
/*******************************************/
|
||||
|
||||
#include "RawWave.h"
|
||||
|
||||
RawWave :: RawWave(char *fileName)
|
||||
{
|
||||
long i;
|
||||
short temp;
|
||||
FILE *fd;
|
||||
fd = fopen(fileName,"rb");
|
||||
if (!fd) {
|
||||
printf("Couldn't find soundfile %s !!!!!!!!\n",fileName);
|
||||
exit(0);
|
||||
}
|
||||
i = 0;
|
||||
while (fread(&temp,2,1,fd)) i++;
|
||||
length = i;
|
||||
fseek(fd,0,0);
|
||||
data = (MY_FLOAT *) malloc(MY_FLOAT_SIZE * (length + 1));
|
||||
myData = 1;
|
||||
i = 0;
|
||||
while (fread(&temp,2,1,fd)) {
|
||||
data[i] = temp;
|
||||
i++;
|
||||
}
|
||||
data[length] = data[length-1];
|
||||
fclose(fd);
|
||||
looping = 0;
|
||||
time = length;
|
||||
phaseOffset = 0.0;
|
||||
rate = 1.0;
|
||||
allDone = 0;
|
||||
}
|
||||
|
||||
RawWave :: RawWave(MY_FLOAT *someData, long aLength)
|
||||
{
|
||||
|
||||
length = aLength;
|
||||
data = someData;
|
||||
myData = 0;
|
||||
looping = 0;
|
||||
time = 0.0;
|
||||
phaseOffset = 0.0;
|
||||
rate = 1.0;
|
||||
}
|
||||
|
||||
RawWave :: ~RawWave()
|
||||
{
|
||||
if (myData) {
|
||||
free(data);
|
||||
data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void RawWave :: reset()
|
||||
{
|
||||
time = 0.0;
|
||||
lastOutput = 0.0;
|
||||
allDone = 0;
|
||||
}
|
||||
|
||||
void RawWave :: normalize()
|
||||
{
|
||||
this->normalize(1.0);
|
||||
}
|
||||
|
||||
void RawWave :: normalize(MY_FLOAT newPeak)
|
||||
{
|
||||
long i;
|
||||
MY_FLOAT max = 0.0;
|
||||
for (i=0;i<=length;i++)
|
||||
if (fabs(data[i]) > max)
|
||||
max = fabs(data[i]);
|
||||
if (max > 0.0) {
|
||||
max = 1.0 / max;
|
||||
max *= newPeak;
|
||||
for (i=0;i<=length;i++)
|
||||
data[i] *= max;
|
||||
}
|
||||
}
|
||||
|
||||
void RawWave :: setRate(MY_FLOAT aRate)
|
||||
{
|
||||
rate = aRate;
|
||||
}
|
||||
|
||||
void RawWave :: setFreq(MY_FLOAT aFreq)
|
||||
{
|
||||
rate = length * ONE_OVER_SRATE * aFreq;
|
||||
}
|
||||
|
||||
void RawWave :: addTime(MY_FLOAT aTime) /* Add an absolute time */
|
||||
{ /* in samples */
|
||||
time += aTime;
|
||||
}
|
||||
|
||||
void RawWave :: addPhase(MY_FLOAT anAngle) /* Add a time in cycles */
|
||||
{ /* Cycles here means */
|
||||
time += length * anAngle; /* 1.0 = length */
|
||||
}
|
||||
|
||||
void RawWave :: addPhaseOffset(MY_FLOAT anAngle)
|
||||
{ /* Add a phase offset */
|
||||
phaseOffset = length * anAngle; /* in cycles, where */
|
||||
} /* 1.0 = length */
|
||||
|
||||
void RawWave :: setLooping(int aLoopStatus)
|
||||
{
|
||||
time = 0;
|
||||
looping = aLoopStatus;
|
||||
if (looping) data[length] = data[0];
|
||||
}
|
||||
|
||||
long RawWave :: getLength()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
MY_FLOAT* RawWave :: getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
MY_FLOAT RawWave :: tick()
|
||||
{
|
||||
this->informTick();
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
int RawWave :: isAllDone()
|
||||
{
|
||||
return allDone;
|
||||
}
|
||||
|
||||
int RawWave :: informTick()
|
||||
{
|
||||
long temp;
|
||||
|
||||
MY_FLOAT temp_time, alpha;
|
||||
|
||||
time += rate; /* Update current time */
|
||||
|
||||
if (looping) {
|
||||
while (time >= length) /* Check for end of sound */
|
||||
time -= length; /* loop back to beginning */
|
||||
while (time < 0.0) /* Check for end of sound */
|
||||
time += length; /* loop back to beginning */
|
||||
}
|
||||
else {
|
||||
if (time >= length) { /* Check for end of sound */
|
||||
time = length-1; /* stick at end */
|
||||
allDone = 1; /* Information for one-shot use */
|
||||
}
|
||||
else if (time < 0.0) /* Check for end of sound */
|
||||
time = 0.0; /* stick at beg */
|
||||
}
|
||||
|
||||
temp_time = time;
|
||||
|
||||
if (phaseOffset != 0.0) {
|
||||
temp_time += phaseOffset; /* Add phase offset */
|
||||
if (looping) {
|
||||
while (temp_time >= length) /* Check for end of sound */
|
||||
temp_time -= length; /* loop back to beginning */
|
||||
while (temp_time < 0.0) /* Check for end of sound */
|
||||
temp_time += length; /* loop back to beginning */
|
||||
}
|
||||
else {
|
||||
if (temp_time >= length) /* Check for end of sound */
|
||||
temp_time = length-1; /* stick at end */
|
||||
else if (temp_time < 0.0) /* check for end of sound */
|
||||
temp_time = 0.0; /* stick at beg */
|
||||
}
|
||||
}
|
||||
|
||||
temp = (long) temp_time; /* Integer part of time address */
|
||||
alpha = temp_time - (MY_FLOAT) temp; /* fractional part of time address */
|
||||
lastOutput = data[temp]; /* Do linear interpolation */
|
||||
lastOutput = lastOutput + /* same as alpha*data[temp+1] */
|
||||
(alpha * (data[temp+1] -
|
||||
lastOutput)); /* + (1-alpha)data[temp] */
|
||||
|
||||
return allDone;
|
||||
}
|
||||
|
||||
MY_FLOAT RawWave :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
|
||||
void main()
|
||||
{
|
||||
RawWave loopWave("rawwaves/sinewave.raw");
|
||||
RawWave oneShot("rawwaves/mandpluk.raw");
|
||||
FILE *fd;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
loopWave.setLooping(1);
|
||||
loopWave.setFreq(5500);
|
||||
fd = fopen("test.raw","wb");
|
||||
for (i=0;i<4096;i++) {
|
||||
data = loopWave.tick();
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
loopWave.setFreq(2750);
|
||||
for (i=0;i<4096;i++) {
|
||||
data = loopWave.tick();
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
oneShot.setLooping(0);
|
||||
for (i=0;i<8192;i++) {
|
||||
data = oneShot.tick();
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
oneShot.reset();
|
||||
oneShot.setRate(0.5);
|
||||
for (i=0;i<16384;i++) {
|
||||
data = oneShot.tick();
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user