mirror of
https://github.com/thestk/stk
synced 2026-01-11 20:11:52 +00:00
Version 2.01
This commit is contained in:
committed by
Stephen Sinclair
parent
6485746ee9
commit
ea749b71d2
62
ADSR.cpp
62
ADSR.cpp
@@ -15,12 +15,12 @@
|
||||
|
||||
ADSR :: ADSR() : Envelope()
|
||||
{
|
||||
target = 0.0;
|
||||
value = 0.0;
|
||||
attackRate = 0.001;
|
||||
decayRate = 0.001;
|
||||
sustainLevel = 0.5;
|
||||
releaseRate = 0.01;
|
||||
target = (MY_FLOAT) 0.0;
|
||||
value = (MY_FLOAT) 0.0;
|
||||
attackRate = (MY_FLOAT) 0.001;
|
||||
decayRate = (MY_FLOAT) 0.001;
|
||||
sustainLevel = (MY_FLOAT) 0.5;
|
||||
releaseRate = (MY_FLOAT) 0.01;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
@@ -31,14 +31,14 @@ ADSR :: ~ADSR()
|
||||
|
||||
void ADSR :: keyOn()
|
||||
{
|
||||
target = 1.0;
|
||||
target = (MY_FLOAT) 1.0;
|
||||
rate = attackRate;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
void ADSR :: keyOff()
|
||||
{
|
||||
target = 0.0;
|
||||
target = (MY_FLOAT) 0.0;
|
||||
rate = releaseRate;
|
||||
state = 3;
|
||||
}
|
||||
@@ -50,7 +50,6 @@ void ADSR :: setAttackRate(MY_FLOAT aRate)
|
||||
attackRate = -aRate;
|
||||
}
|
||||
else attackRate = aRate;
|
||||
attackRate = attackRate * RATE_NORM; /* SEE Object.h */
|
||||
}
|
||||
|
||||
void ADSR :: setDecayRate(MY_FLOAT aRate)
|
||||
@@ -60,14 +59,13 @@ void ADSR :: setDecayRate(MY_FLOAT aRate)
|
||||
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;
|
||||
sustainLevel = (MY_FLOAT) 0.0;
|
||||
}
|
||||
else sustainLevel = aLevel;
|
||||
}
|
||||
@@ -79,15 +77,41 @@ void ADSR :: setReleaseRate(MY_FLOAT aRate)
|
||||
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)
|
||||
void ADSR :: setAttackTime(MY_FLOAT aTime)
|
||||
{
|
||||
this->setAttackRate(attRate);
|
||||
this->setDecayRate(decRate);
|
||||
if (aTime < 0.0) {
|
||||
printf("negative times not allowed!!, correcting\n");
|
||||
attackRate = ONE_OVER_SRATE / -aTime;
|
||||
}
|
||||
else attackRate = ONE_OVER_SRATE / aTime;
|
||||
}
|
||||
|
||||
void ADSR :: setDecayTime(MY_FLOAT aTime)
|
||||
{
|
||||
if (aTime < 0.0) {
|
||||
printf("negative times not allowed!!, correcting\n");
|
||||
decayRate = ONE_OVER_SRATE / -aTime;
|
||||
}
|
||||
else decayRate = ONE_OVER_SRATE / aTime;
|
||||
}
|
||||
|
||||
void ADSR :: setReleaseTime(MY_FLOAT aTime)
|
||||
{
|
||||
if (aTime < 0.0) {
|
||||
printf("negative times not allowed!!, correcting\n");
|
||||
releaseRate = ONE_OVER_SRATE / -aTime;
|
||||
}
|
||||
else releaseRate = ONE_OVER_SRATE / aTime;
|
||||
}
|
||||
|
||||
void ADSR :: setAllTimes(MY_FLOAT attTime, MY_FLOAT decTime, MY_FLOAT susLevel, MY_FLOAT relTime)
|
||||
{
|
||||
this->setAttackTime(attTime);
|
||||
this->setDecayTime(decTime);
|
||||
this->setSustainLevel(susLevel);
|
||||
this->setReleaseRate(relRate);
|
||||
this->setReleaseTime(relTime);
|
||||
}
|
||||
|
||||
void ADSR :: setTarget(MY_FLOAT aTarget)
|
||||
@@ -111,7 +135,7 @@ void ADSR :: setValue(MY_FLOAT aValue)
|
||||
target = aValue;
|
||||
value = aValue;
|
||||
this->setSustainLevel(aValue);
|
||||
rate = 0.0;
|
||||
rate = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
MY_FLOAT ADSR :: tick()
|
||||
@@ -129,14 +153,14 @@ MY_FLOAT ADSR :: tick()
|
||||
value -= decayRate;
|
||||
if (value <= sustainLevel) {
|
||||
value = sustainLevel;
|
||||
rate = 0.0;
|
||||
rate = (MY_FLOAT) 0.0;
|
||||
state = SUSTAIN;
|
||||
}
|
||||
}
|
||||
else if (state==RELEASE) {
|
||||
value -= releaseRate;
|
||||
if (value <= 0.0) {
|
||||
value = 0.0;
|
||||
value = (MY_FLOAT) 0.0;
|
||||
state = 4;
|
||||
}
|
||||
}
|
||||
|
||||
5
ADSR.h
5
ADSR.h
@@ -32,7 +32,10 @@ class ADSR : public Envelope
|
||||
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 setAttackTime(MY_FLOAT aTime);
|
||||
void setDecayTime(MY_FLOAT aTime);
|
||||
void setReleaseTime(MY_FLOAT aTime);
|
||||
void setAllTimes(MY_FLOAT attTime, MY_FLOAT decTime, MY_FLOAT susLevel, MY_FLOAT relTime);
|
||||
void setTarget(MY_FLOAT aTarget);
|
||||
void setValue(MY_FLOAT aValue);
|
||||
MY_FLOAT tick();
|
||||
|
||||
49
AgogoBel.cpp
49
AgogoBel.cpp
@@ -12,21 +12,22 @@
|
||||
/* 360, 1470, 2401, 4600 */
|
||||
|
||||
#include "AgogoBel.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
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;
|
||||
wave->setRate((MY_FLOAT) 7.0); /* hardstick */
|
||||
this->setRatioAndReson(0, (MY_FLOAT) 1.00,(MY_FLOAT) 0.999); /* Set our */
|
||||
this->setRatioAndReson(1, (MY_FLOAT) 4.08,(MY_FLOAT) 0.999); /* resonances */
|
||||
this->setRatioAndReson(2,(MY_FLOAT) 6.669,(MY_FLOAT) 0.999); /* here */
|
||||
this->setRatioAndReson(3,(MY_FLOAT) -3725.0, (MY_FLOAT)0.999); /* (One fixed) */
|
||||
this->setFiltGain(0,(MY_FLOAT) 0.06); /* And filter */
|
||||
this->setFiltGain(1,(MY_FLOAT) 0.05); /* gains too */
|
||||
this->setFiltGain(2,(MY_FLOAT) 0.03);
|
||||
this->setFiltGain(3,(MY_FLOAT) 0.02);
|
||||
directGain = (MY_FLOAT) 0.25;
|
||||
}
|
||||
|
||||
AgogoBel :: ~AgogoBel()
|
||||
@@ -37,8 +38,8 @@ AgogoBel :: ~AgogoBel()
|
||||
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 */
|
||||
wave->setRate((MY_FLOAT) 3.0 + ((MY_FLOAT) 8.0 * stickHardness)); /* hardness <-> center */
|
||||
masterGain = (MY_FLOAT) 1.0; /* freq and amplitude */
|
||||
}
|
||||
|
||||
void AgogoBel :: setStrikePosition(MY_FLOAT position)
|
||||
@@ -46,12 +47,12 @@ 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! */
|
||||
temp = (MY_FLOAT) sin(0.7 * temp2); /* three modes, */
|
||||
this->setFiltGain(0,(MY_FLOAT) 0.08 * temp); /* leave the other */
|
||||
temp = (MY_FLOAT) sin(0.1 + (5.0 * temp2)); /* fixed. Why? */
|
||||
this->setFiltGain(1,(MY_FLOAT) 0.07 * temp); /* So it doesn't */
|
||||
temp = (MY_FLOAT) sin(0.2 + (7.0 * temp2)); /* sound like a */
|
||||
this->setFiltGain(2,(MY_FLOAT) 0.04 * temp); /* sample! */
|
||||
}
|
||||
|
||||
void AgogoBel :: controlChange(int number, MY_FLOAT value)
|
||||
@@ -59,15 +60,15 @@ 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)
|
||||
if (number == __SK_StickHardness_)
|
||||
this->setStickHardness(value * NORM_7);
|
||||
else if (number == MIDI_control2)
|
||||
else if (number == __SK_StrikePosition_)
|
||||
this->setStrikePosition(value * NORM_7);
|
||||
else if (number == MIDI_control3)
|
||||
vibr->setFreq((value * NORM_7 * 12.0));
|
||||
else if (number == MIDI_mod_wheel)
|
||||
else if (number == __SK_ModFrequency_)
|
||||
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
|
||||
else if (number == __SK_ModWheel_)
|
||||
vibrGain = (value * NORM_7);
|
||||
else if (number == MIDI_after_touch)
|
||||
else if (number == __SK_AfterTouch_Cont_)
|
||||
this->strike(value * NORM_7);
|
||||
else {
|
||||
printf("AgogoBel : Undefined Control Number!!\n");
|
||||
|
||||
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
|
||||
20
BeeThree.cpp
20
BeeThree.cpp
@@ -13,19 +13,19 @@ BeeThree :: BeeThree() : FM4Alg8()
|
||||
"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);
|
||||
this->setRatio(0,(MY_FLOAT) 0.999);
|
||||
this->setRatio(1,(MY_FLOAT) 1.997);
|
||||
this->setRatio(2,(MY_FLOAT) 3.006);
|
||||
this->setRatio(3,(MY_FLOAT) 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);
|
||||
adsr[0]->setAllTimes((MY_FLOAT) 0.005,(MY_FLOAT) 0.003,(MY_FLOAT) 1.0,(MY_FLOAT) 0.01);
|
||||
adsr[1]->setAllTimes((MY_FLOAT) 0.005,(MY_FLOAT) 0.003,(MY_FLOAT) 1.0,(MY_FLOAT) 0.01);
|
||||
adsr[2]->setAllTimes((MY_FLOAT) 0.005,(MY_FLOAT) 0.003,(MY_FLOAT) 1.0,(MY_FLOAT) 0.01);
|
||||
adsr[3]->setAllTimes((MY_FLOAT) 0.005,(MY_FLOAT) 0.001,(MY_FLOAT) 0.4,(MY_FLOAT) 0.03);
|
||||
twozero->setGain((MY_FLOAT) 0.1);
|
||||
}
|
||||
|
||||
BeeThree :: ~BeeThree()
|
||||
@@ -46,7 +46,7 @@ MY_FLOAT BeeThree :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
if (modDepth > 0.0) {
|
||||
temp = 1.0 + (modDepth * vibWave->tick() * 0.1);
|
||||
temp = (MY_FLOAT) 1.0 + (modDepth * vibWave->tick() * (MY_FLOAT) 0.1);
|
||||
waves[0]->setFreq(baseFreq * ratios[0] * temp);
|
||||
waves[1]->setFreq(baseFreq * ratios[1] * temp);
|
||||
waves[2]->setFreq(baseFreq * ratios[2] * temp);
|
||||
|
||||
22
BiQuad.cpp
22
BiQuad.cpp
@@ -11,11 +11,11 @@
|
||||
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;
|
||||
zeroCoeffs[0] = (MY_FLOAT) 0.0;
|
||||
zeroCoeffs[1] = (MY_FLOAT) 0.0;
|
||||
poleCoeffs[0] = (MY_FLOAT) 0.0;
|
||||
poleCoeffs[1] = (MY_FLOAT) 0.0;
|
||||
gain = (MY_FLOAT) 1.0;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@ BiQuad :: ~BiQuad()
|
||||
|
||||
void BiQuad :: clear()
|
||||
{
|
||||
inputs[0] = 0.0;
|
||||
inputs[1] = 0.0;
|
||||
lastOutput = 0.0;
|
||||
inputs[0] = (MY_FLOAT) 0.0;
|
||||
inputs[1] = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void BiQuad :: setPoleCoeffs(MY_FLOAT *coeffs)
|
||||
@@ -46,13 +46,13 @@ void BiQuad :: setZeroCoeffs(MY_FLOAT *coeffs)
|
||||
void BiQuad :: setFreqAndReson(MY_FLOAT freq, MY_FLOAT reson)
|
||||
{
|
||||
poleCoeffs[1] = - (reson * reson);
|
||||
poleCoeffs[0] = 2.0 * reson * cos(TWO_PI * freq / SRATE);
|
||||
poleCoeffs[0] = (MY_FLOAT) 2.0 * reson * (MY_FLOAT) cos(TWO_PI * freq / SRATE);
|
||||
}
|
||||
|
||||
void BiQuad :: setEqualGainZeroes()
|
||||
{
|
||||
zeroCoeffs[1] = -1.0;
|
||||
zeroCoeffs[0] = 0.0;
|
||||
zeroCoeffs[1] = (MY_FLOAT) -1.0;
|
||||
zeroCoeffs[0] = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void BiQuad :: setGain(MY_FLOAT aValue)
|
||||
|
||||
10
BowTabl.cpp
10
BowTabl.cpp
@@ -7,9 +7,9 @@
|
||||
|
||||
BowTabl :: BowTabl()
|
||||
{
|
||||
offSet = 0.0; /* offset is a bias, really not needed unless */
|
||||
offSet = (MY_FLOAT) 0.0; /* offset is a bias, really not needed unless */
|
||||
/* friction is different in each direction */
|
||||
slope = 0.1; /* controls width of friction pulse, */
|
||||
slope = (MY_FLOAT) 0.1; /* controls width of friction pulse, */
|
||||
/* related to bowForce */
|
||||
}
|
||||
|
||||
@@ -33,10 +33,10 @@ MY_FLOAT BowTabl :: lookup(MY_FLOAT sample) /* Perform Table Lookup */
|
||||
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);
|
||||
lastOutput = (MY_FLOAT) fabs((double) input) + (MY_FLOAT) 0.75; /* below min delta, friction = 1 */
|
||||
lastOutput = (MY_FLOAT) pow(lastOutput,(MY_FLOAT) -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 */
|
||||
if (lastOutput > 1.0 ) lastOutput = (MY_FLOAT) 1.0; /* maximum friction is 1.0 */
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
|
||||
61
Bowed.cpp
61
Bowed.cpp
@@ -15,39 +15,40 @@
|
||||
/******************************************/
|
||||
|
||||
#include "Bowed.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
Bowed :: Bowed(MY_FLOAT lowestFreq)
|
||||
{
|
||||
long length;
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
neckDelay = new DLineL(length);
|
||||
length >> 1;
|
||||
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;
|
||||
vibrGain = (MY_FLOAT) 0.0;
|
||||
|
||||
neckDelay->setDelay(100.0);
|
||||
bridgeDelay->setDelay(29.0);
|
||||
neckDelay->setDelay((MY_FLOAT) 100.0);
|
||||
bridgeDelay->setDelay((MY_FLOAT) 29.0);
|
||||
|
||||
bowTabl->setSlope(3.0);
|
||||
bowTabl->setSlope((MY_FLOAT) 3.0);
|
||||
|
||||
reflFilt->setPole(0.6 - (0.1 * RATE_NORM));
|
||||
reflFilt->setGain(0.95);
|
||||
reflFilt->setPole((MY_FLOAT) (0.6 - (0.1 * 22050.0 / SRATE)));
|
||||
reflFilt->setGain((MY_FLOAT) 0.95);
|
||||
|
||||
bodyFilt->setFreqAndReson(500.0, 0.85);
|
||||
bodyFilt->setFreqAndReson((MY_FLOAT) 500.0, (MY_FLOAT) 0.85);
|
||||
bodyFilt->setEqualGainZeroes();
|
||||
bodyFilt->setGain(0.2);
|
||||
bodyFilt->setGain((MY_FLOAT) 0.2);
|
||||
|
||||
vibr->normalize();
|
||||
vibr->setFreq(6.12723);
|
||||
vibr->setFreq((MY_FLOAT) 6.12723);
|
||||
|
||||
adsr->setAll(0.002,0.01,0.9,0.01);
|
||||
adsr->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.005,(MY_FLOAT) 0.9,(MY_FLOAT) 0.01);
|
||||
|
||||
betaRatio = 0.127236;
|
||||
betaRatio = (MY_FLOAT) 0.127236;
|
||||
}
|
||||
|
||||
Bowed :: ~Bowed()
|
||||
@@ -69,16 +70,16 @@ void Bowed :: clear()
|
||||
|
||||
void Bowed :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseDelay = (MY_FLOAT) SRATE / frequency - 4.0; /* delay - approx. filter delay */
|
||||
baseDelay = SRATE / frequency - (MY_FLOAT) 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 */
|
||||
neckDelay->setDelay(baseDelay * ((MY_FLOAT) 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);
|
||||
maxVelocity = (MY_FLOAT) 0.03 + ((MY_FLOAT) 0.2 * amplitude);
|
||||
}
|
||||
|
||||
void Bowed :: stopBowing(MY_FLOAT rate)
|
||||
@@ -89,7 +90,7 @@ void Bowed :: stopBowing(MY_FLOAT rate)
|
||||
|
||||
void Bowed :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->startBowing(amp,amp * 0.001);
|
||||
this->startBowing(amp,amp * (MY_FLOAT) 0.001);
|
||||
this->setFreq(freq);
|
||||
#if defined(_debug_)
|
||||
printf("Bowed : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
@@ -98,7 +99,7 @@ void Bowed :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
|
||||
void Bowed :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->stopBowing((1.0 - amp) * 0.005);
|
||||
this->stopBowing(((MY_FLOAT) 1.0 - amp) * (MY_FLOAT) 0.005);
|
||||
#if defined(_debug_)
|
||||
printf("Bowed : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
@@ -112,8 +113,8 @@ void Bowed :: setVibrato(MY_FLOAT amount)
|
||||
MY_FLOAT Bowed :: tick()
|
||||
{
|
||||
MY_FLOAT bowVelocity;
|
||||
MY_FLOAT bridgeRefl=0,nutRefl=0;
|
||||
MY_FLOAT newVel=0,velDiff=0,stringVel=0;
|
||||
MY_FLOAT bridgeRefl=(MY_FLOAT) 0,nutRefl=(MY_FLOAT) 0;
|
||||
MY_FLOAT newVel=(MY_FLOAT) 0,velDiff=(MY_FLOAT) 0,stringVel=(MY_FLOAT) 0;
|
||||
|
||||
bowVelocity = maxVelocity * adsr->tick();
|
||||
|
||||
@@ -127,7 +128,7 @@ MY_FLOAT Bowed :: tick()
|
||||
bridgeDelay->tick(nutRefl + newVel); /* propagations */
|
||||
|
||||
if (vibrGain > 0.0) {
|
||||
neckDelay->setDelay((baseDelay * (1.0 - betaRatio)) +
|
||||
neckDelay->setDelay((baseDelay * ((MY_FLOAT) 1.0 - betaRatio)) +
|
||||
(baseDelay * vibrGain*vibr->tick()));
|
||||
}
|
||||
|
||||
@@ -141,18 +142,18 @@ 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);
|
||||
if (number == __SK_BowPressure_)
|
||||
bowTabl->setSlope((MY_FLOAT) 5.0 - ((MY_FLOAT) 4.0 * value * NORM_7));
|
||||
else if (number == __SK_BowPosition_) {
|
||||
betaRatio = (MY_FLOAT) 0.027236 + ((MY_FLOAT) 0.2 * value * NORM_7);
|
||||
bridgeDelay->setDelay(baseDelay * betaRatio); /* bow to bridge length */
|
||||
neckDelay->setDelay(baseDelay * (1.0 - betaRatio)); /* bow to nut (finger) length */
|
||||
neckDelay->setDelay(baseDelay * ((MY_FLOAT) 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)
|
||||
else if (number == __SK_ModFrequency_)
|
||||
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
|
||||
else if (number == __SK_ModWheel_)
|
||||
vibrGain = (value * NORM_7 * (MY_FLOAT) 0.4);
|
||||
else if (number == __SK_AfterTouch_Cont_)
|
||||
adsr->setTarget(value * NORM_7);
|
||||
else {
|
||||
printf("Bowed : Undefined Control Number!!\n");
|
||||
|
||||
38
Brass.cpp
38
Brass.cpp
@@ -14,6 +14,7 @@
|
||||
/******************************************/
|
||||
|
||||
#include "Brass.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
Brass :: Brass(MY_FLOAT lowestFreq)
|
||||
{
|
||||
@@ -22,13 +23,15 @@ Brass :: Brass(MY_FLOAT lowestFreq)
|
||||
lipFilter = new LipFilt;
|
||||
dcBlock = new DCBlock;
|
||||
adsr = new ADSR;
|
||||
adsr->setAll(0.02, 0.05, 1.0, 0.001);
|
||||
adsr->setAllTimes((MY_FLOAT) 0.005, (MY_FLOAT) 0.001, (MY_FLOAT) 1.0, (MY_FLOAT) 0.010);
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
this->clear();
|
||||
|
||||
vibr->normalize();
|
||||
vibr->setFreq(6.137);
|
||||
vibrGain = 0.05; /* breath periodic vibrato component */
|
||||
vibr->setFreq((MY_FLOAT) 6.137);
|
||||
vibrGain = (MY_FLOAT) 0.05; /* breath periodic vibrato component */
|
||||
|
||||
maxPressure = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
Brass :: ~Brass()
|
||||
@@ -45,12 +48,11 @@ 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;
|
||||
slideTarget = (SRATE / frequency * (MY_FLOAT) 2.0) + (MY_FLOAT) 3.0;
|
||||
/* fudge correction for filter delays */
|
||||
delayLine->setDelay(slideTarget); /* we'll play a harmonic */
|
||||
lipTarget = frequency;
|
||||
@@ -78,7 +80,7 @@ void Brass :: stopBlowing(MY_FLOAT rate)
|
||||
void Brass :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
this->startBlowing(amp, amp * 0.001);
|
||||
this->startBlowing(amp, amp * (MY_FLOAT) 0.001);
|
||||
#if defined(_debug_)
|
||||
printf("Brass : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
@@ -86,7 +88,7 @@ void Brass :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
|
||||
void Brass :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->stopBlowing(amp * 0.005);
|
||||
this->stopBlowing(amp * (MY_FLOAT) 0.005);
|
||||
#if defined(_debug_)
|
||||
printf("Brass : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
@@ -100,8 +102,8 @@ MY_FLOAT Brass :: 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 */
|
||||
lipFilter->tick((MY_FLOAT) 0.3 * breathPressure, /* mouth input */
|
||||
(MY_FLOAT) 0.85 * delayLine->lastOut()))); /* and bore reflection */
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
@@ -111,17 +113,17 @@ void Brass :: controlChange(int number, MY_FLOAT value)
|
||||
#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);
|
||||
if (number == __SK_LipTension_) {
|
||||
temp = lipTarget * (MY_FLOAT) 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)
|
||||
else if (number == __SK_SlideLength_)
|
||||
delayLine->setDelay(slideTarget * ((MY_FLOAT) 0.5 + (value * NORM_7)));
|
||||
else if (number == __SK_ModFrequency_)
|
||||
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
|
||||
else if (number == __SK_ModWheel_ )
|
||||
vibrGain = (value * NORM_7 * (MY_FLOAT) 0.4);
|
||||
else if (number == __SK_AfterTouch_Cont_)
|
||||
adsr->setTarget(value * NORM_7);
|
||||
else {
|
||||
printf("Brass : Undefined Control Number!!\n");
|
||||
|
||||
45
Clarinet.cpp
45
Clarinet.cpp
@@ -14,23 +14,24 @@
|
||||
/******************************************/
|
||||
|
||||
#include "Clarinet.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
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);
|
||||
reedTable->setOffset((MY_FLOAT) 0.7);
|
||||
reedTable->setSlope((MY_FLOAT) -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;
|
||||
vibr->setFreq((MY_FLOAT) 5.735);
|
||||
outputGain = (MY_FLOAT) 1.0;
|
||||
noiseGain = (MY_FLOAT) 0.2;
|
||||
vibrGain = (MY_FLOAT) 0.1;
|
||||
}
|
||||
|
||||
Clarinet :: ~Clarinet()
|
||||
@@ -46,13 +47,13 @@ Clarinet :: ~Clarinet()
|
||||
void Clarinet :: clear()
|
||||
{
|
||||
delayLine->clear();
|
||||
filter->tick(0.0);
|
||||
filter->tick((MY_FLOAT) 0.0);
|
||||
}
|
||||
|
||||
void Clarinet :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
delayLine->setDelay /* length - approx filter delay */
|
||||
((SRATE / frequency) * 0.5 - 1.5);
|
||||
((SRATE / frequency) * (MY_FLOAT) 0.5 - (MY_FLOAT) 1.5);
|
||||
}
|
||||
|
||||
void Clarinet :: startBlowing(MY_FLOAT amplitude,MY_FLOAT rate)
|
||||
@@ -64,14 +65,14 @@ void Clarinet :: startBlowing(MY_FLOAT amplitude,MY_FLOAT rate)
|
||||
void Clarinet :: stopBlowing(MY_FLOAT rate)
|
||||
{
|
||||
envelope->setRate(rate);
|
||||
envelope->setTarget(0.0);
|
||||
envelope->setTarget((MY_FLOAT) 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;
|
||||
this->startBlowing((MY_FLOAT) 0.55 + (amp * (MY_FLOAT) 0.30),amp * (MY_FLOAT) 0.005);
|
||||
outputGain = amp + (MY_FLOAT) 0.001;
|
||||
#if defined(_debug_)
|
||||
printf("Clarinet : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
@@ -79,7 +80,7 @@ void Clarinet :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
|
||||
void Clarinet :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->stopBlowing(amp * 0.01);
|
||||
this->stopBlowing(amp * (MY_FLOAT) 0.01);
|
||||
#if defined(_debug_)
|
||||
printf("Clarinet : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
@@ -96,7 +97,7 @@ MY_FLOAT Clarinet :: tick()
|
||||
breathPressure += breathPressure *
|
||||
vibrGain * vibr->tick();
|
||||
pressureDiff = filter->tick(delayLine->lastOut()); /* differential pressure */
|
||||
pressureDiff = (pressureDiff * -0.95) - breathPressure; /* of reflected and mouth */
|
||||
pressureDiff = (pressureDiff * (MY_FLOAT) -0.95) - breathPressure; /* of reflected and mouth */
|
||||
lastOutput = delayLine->tick(breathPressure + /* perform scattering */
|
||||
pressureDiff * reedTable->lookup(pressureDiff)); /* in economical way */
|
||||
lastOutput *= outputGain;
|
||||
@@ -108,15 +109,15 @@ 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) {
|
||||
if (number == __SK_ReedStiffness_)
|
||||
reedTable->setSlope((MY_FLOAT) -0.44 + ((MY_FLOAT) 0.26 * value * NORM_7));
|
||||
else if (number == __SK_NoiseLevel_)
|
||||
noiseGain = (value * NORM_7 * (MY_FLOAT) 0.4);
|
||||
else if (number == __SK_ModFrequency_)
|
||||
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
|
||||
else if (number == __SK_ModWheel_)
|
||||
vibrGain = (value * NORM_7 * (MY_FLOAT) 0.5);
|
||||
else if (number == __SK_AfterTouch_Cont_) {
|
||||
envelope->setValue(value * NORM_7);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -26,14 +26,14 @@ DCBlock :: ~DCBlock()
|
||||
|
||||
void DCBlock :: clear()
|
||||
{
|
||||
outputs[0] = 0.0;
|
||||
inputs[0] = 0.0;
|
||||
lastOutput = 0.0;
|
||||
outputs[0] = (MY_FLOAT) 0.0;
|
||||
inputs[0] = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
MY_FLOAT DCBlock :: tick(MY_FLOAT sample)
|
||||
{
|
||||
outputs[0] = sample - inputs[0] + (0.99 * outputs[0]);
|
||||
outputs[0] = sample - inputs[0] + ((MY_FLOAT) 0.99 * outputs[0]);
|
||||
inputs[0] = sample;
|
||||
lastOutput = outputs[0];
|
||||
return lastOutput;
|
||||
|
||||
17
DLineA.cpp
17
DLineA.cpp
@@ -22,7 +22,7 @@ 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;
|
||||
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0;
|
||||
this->clear();
|
||||
inPoint = 0;
|
||||
outPoint = length >> 1;
|
||||
@@ -36,9 +36,9 @@ DLineA :: ~DLineA()
|
||||
void DLineA :: clear()
|
||||
{
|
||||
long i;
|
||||
for (i=0;i<length;i++) inputs[i] = 0.0;
|
||||
lastIn = 0;
|
||||
lastOutput = 0;
|
||||
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0.0;
|
||||
lastIn = (MY_FLOAT) 0;
|
||||
lastOutput = (MY_FLOAT) 0;
|
||||
}
|
||||
|
||||
void DLineA :: setDelay(MY_FLOAT lag)
|
||||
@@ -49,13 +49,14 @@ void DLineA :: setDelay(MY_FLOAT lag)
|
||||
while (outputPointer<0)
|
||||
outputPointer += length; /* modulo table length */
|
||||
outPoint = (long) outputPointer; /* Integer part of delay */
|
||||
alpha = 1.0 + outPoint - outputPointer; /* fractional part of delay */
|
||||
alpha = (MY_FLOAT) 1.0 + outPoint - outputPointer; /* fractional part of delay */
|
||||
if (alpha<0.1) {
|
||||
outputPointer += 1.0; /* Hack to avoid pole/zero */
|
||||
outputPointer += (MY_FLOAT) 1.0;/* Hack to avoid pole/zero */
|
||||
outPoint += 1; /* cancellation. Keeps allpass */
|
||||
alpha += 1.0; /* delay in range of .1 to 1.1 */
|
||||
alpha += (MY_FLOAT) 1.0; /* delay in range of .1 to 1.1 */
|
||||
}
|
||||
coeff = (1.0 - alpha) / (1.0 + alpha); /* coefficient for all pass */
|
||||
coeff = ((MY_FLOAT) 1.0 - alpha) /
|
||||
((MY_FLOAT) 1.0 + alpha); /* coefficient for all pass */
|
||||
}
|
||||
|
||||
MY_FLOAT DLineA :: tick(MY_FLOAT sample) /* Take sample, yield sample */
|
||||
|
||||
@@ -28,8 +28,8 @@ DLineL :: ~DLineL()
|
||||
void DLineL :: clear()
|
||||
{
|
||||
long i;
|
||||
for (i=0;i<length;i++) inputs[i] = 0.0;
|
||||
lastOutput = 0;
|
||||
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 0;
|
||||
}
|
||||
|
||||
void DLineL :: setDelay(MY_FLOAT lag)
|
||||
@@ -40,7 +40,7 @@ void DLineL :: setDelay(MY_FLOAT lag)
|
||||
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) */
|
||||
omAlpha = (MY_FLOAT) 1.0 - alpha; /* 1.0 - fractional part (more efficient) */
|
||||
}
|
||||
|
||||
MY_FLOAT DLineL :: tick(MY_FLOAT sample) /* Take one, yield one */
|
||||
|
||||
@@ -15,7 +15,7 @@ DLineN :: DLineN(long max_length)
|
||||
length = max_length;
|
||||
inputs = (MY_FLOAT *) malloc(length * MY_FLOAT_SIZE);
|
||||
this->clear();
|
||||
this->setDelay(length * 0.5);
|
||||
this->setDelay(length * (MY_FLOAT) 0.5);
|
||||
inPoint = 0;
|
||||
outPoint = 0;
|
||||
}
|
||||
@@ -28,8 +28,8 @@ DLineN :: ~DLineN()
|
||||
void DLineN :: clear()
|
||||
{
|
||||
long i;
|
||||
for (i=0;i<length;i++) inputs[i] = 0.0;
|
||||
lastOutput = 0;
|
||||
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 0;
|
||||
}
|
||||
|
||||
void DLineN :: setDelay(MY_FLOAT lag)
|
||||
|
||||
0
Debug/.placeholder
Normal file
0
Debug/.placeholder
Normal file
101
DrumSynt.cpp
101
DrumSynt.cpp
@@ -2,7 +2,7 @@
|
||||
/* Master Class for Drum Synthesizer */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains a bunch of */
|
||||
/* RawWvIn objects (Non-Interpolating, */
|
||||
/* NI1sWave objects (Non-Interpolating, */
|
||||
/* 1 shot players), run through a bunch */
|
||||
/* of one-pole filters. You can specify */
|
||||
/* the maximum Polyphony (maximum number */
|
||||
@@ -13,49 +13,65 @@
|
||||
#include "DrumSynt.h"
|
||||
#include <string.h>
|
||||
|
||||
/* Not really General MIDI yet. Coming soon. */
|
||||
unsigned char genMIDIMap[128] = { 0,0,0,0,0,0,0,0, // 0-7
|
||||
0,0,0,0,0,0,0,0, // 8-15
|
||||
0,0,0,0,0,0,0,0, // 16-23
|
||||
0,0,0,0,0,0,0,0, // 24-31
|
||||
0,0,0,0,1,0,2,0, // 32-39
|
||||
2,3,6,3,6,4,7,4, // 40-47
|
||||
5,8,5,0,0,0,10,0, // 48-55
|
||||
9,0,0,0,0,0,0,0, // 56-63
|
||||
0,0,0,0,0,0,0,0, // 64-71
|
||||
0,0,0,0,0,0,0,0, // 72-79
|
||||
0,0,0,0,0,0,0,0, // 80-87
|
||||
0,0,0,0,0,0,0,0, // 88-95
|
||||
0,0,0,0,0,0,0,0, // 96-103
|
||||
0,0,0,0,0,0,0,0, // 104-111
|
||||
0,0,0,0,0,0,0,0, // 112-119
|
||||
0,0,0,0,0,0,0,0}; // 120-127
|
||||
|
||||
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"
|
||||
"dope.raw",
|
||||
"bassdrum.raw",
|
||||
"snardrum.raw",
|
||||
"tomlowdr.raw",
|
||||
"tommiddr.raw",
|
||||
"tomhidrm.raw",
|
||||
"hihatcym.raw",
|
||||
"ridecymb.raw",
|
||||
"crashcym.raw",
|
||||
"cowbell1.raw",
|
||||
"tambourn.raw"
|
||||
};
|
||||
|
||||
DrumSynt :: DrumSynt() : Object()
|
||||
DrumSynt :: DrumSynt() : Instrmnt()
|
||||
{
|
||||
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)
|
||||
void DrumSynt :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
int i,notDone;
|
||||
int noteNum;
|
||||
int vel;
|
||||
char tempString[64];
|
||||
RawWvIn *tempWv;
|
||||
OnePole *tempFilt;
|
||||
|
||||
printf("NoteOn: %s vel=%i\n",waveNames[noteNum],vel);
|
||||
noteNum = (int) ((12*log(freq/220)/log(2)) + 57.01); // Yes I know, this is tres kludgey
|
||||
vel = (int) (amp * 127);
|
||||
|
||||
#if defined(_debug_)
|
||||
printf("NoteOn: %s vel=%i\n",waveNames[genMIDIMap[noteNum]],vel);
|
||||
#endif
|
||||
|
||||
notDone = -1;
|
||||
for (i=0;i<DRUM_POLYPHONY;i++) { /* Check first to see */
|
||||
@@ -69,7 +85,7 @@ void DrumSynt :: noteOn(int noteNum, int vel)
|
||||
tempWv = waves[0];
|
||||
tempFilt = filters[0];
|
||||
for (i=0;i<DRUM_POLYPHONY-1;i++) { /* preempt oldest */
|
||||
waves[i] = waves[i+1]; /* oldest voice and */
|
||||
waves[i] = waves[i+1]; /* voice and */
|
||||
filters[i] = filters[i+1]; /* ripple all down */
|
||||
}
|
||||
waves[DRUM_POLYPHONY-1] = tempWv;
|
||||
@@ -80,22 +96,24 @@ void DrumSynt :: noteOn(int noteNum, int vel)
|
||||
}
|
||||
|
||||
sounding[numSounding-1] = noteNum; /* allocate new wave */
|
||||
strcpy(tempString,"rawwaves/drumwavs/");
|
||||
strcat(tempString,waveNames[noteNum]);
|
||||
strcpy(tempString,"rawwaves/");
|
||||
strcat(tempString,waveNames[genMIDIMap[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);
|
||||
waves[numSounding-1]->normalize((MY_FLOAT) 0.2);
|
||||
filters[numSounding-1]->setPole((MY_FLOAT) 0.999 - ((MY_FLOAT) vel * NORM_7 * 0.6));
|
||||
filters[numSounding-1]->setGain(vel / (MY_FLOAT) 128.0);
|
||||
}
|
||||
else {
|
||||
waves[notDone]->reset();
|
||||
filters[notDone]->setPole(0.999 - (vel / 32.0));
|
||||
filters[notDone]->setGain(vel / 128.0);
|
||||
filters[notDone]->setPole((MY_FLOAT) 0.999 - ((MY_FLOAT) vel * NORM_7 * 0.6));
|
||||
filters[notDone]->setGain(vel / (MY_FLOAT) 128.0);
|
||||
}
|
||||
|
||||
#if defined(_debug_)
|
||||
printf("Number Sounding = %i\n",numSounding);
|
||||
for (i=0;i<numSounding;i++) printf(" %i ",sounding[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
MY_FLOAT DrumSynt :: tick()
|
||||
@@ -106,17 +124,17 @@ MY_FLOAT DrumSynt :: tick()
|
||||
|
||||
i = 0;
|
||||
notDone = 1;
|
||||
output = 0.0;
|
||||
output = (MY_FLOAT) 0.0;
|
||||
|
||||
if (numSounding == 0) notDone = 0;
|
||||
while (notDone && (i < numSounding)) {
|
||||
|
||||
output += waves[i]->lastOut();
|
||||
output += filters[i]->tick(waves[i]->lastOut());
|
||||
|
||||
if (waves[i]->informTick() == 1) {
|
||||
|
||||
#if defined(_debug_)
|
||||
printf("Wave %i %i down here\n",i,sounding[i]);
|
||||
|
||||
#endif
|
||||
delete waves[i];
|
||||
tempFilt = filters[i];
|
||||
|
||||
@@ -135,30 +153,31 @@ MY_FLOAT DrumSynt :: tick()
|
||||
i++;
|
||||
}
|
||||
|
||||
return output;
|
||||
return output * 2;
|
||||
}
|
||||
|
||||
/************** Test Main Program *********************/
|
||||
|
||||
/*
|
||||
#include "miditabl.h"
|
||||
#include "RawWvOut.h"
|
||||
#include "Reverb.h"
|
||||
#include "Noise.h"
|
||||
|
||||
int main()
|
||||
void main()
|
||||
{
|
||||
long i,j;
|
||||
DrumSynt instrument;
|
||||
RawWvOut output("test.snd");
|
||||
Reverb reverb(2137);
|
||||
Reverb reverb((MY_FLOAT) 2137);
|
||||
Noise noise;
|
||||
|
||||
for (j=0;j<100;j++) {
|
||||
i = (int) (fabs(noise.tick()) * DRUM_NUMWAVES);
|
||||
instrument.noteOn(i,127);
|
||||
instrument.noteOn(i,1.0);
|
||||
for (i=0;i<2000;i++) output.tick(reverb.tick(instrument.tick()));
|
||||
}
|
||||
|
||||
for (i=0;i<22000;i++) output.tick(reverb.tick(instrument.tick()));
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
10
DrumSynt.h
10
DrumSynt.h
@@ -13,14 +13,14 @@
|
||||
#if !defined(__DrumSynt_h)
|
||||
#define __DrumSynt_h
|
||||
|
||||
#include "Object.h"
|
||||
#include "Instrmnt.h"
|
||||
#include "RawWvIn.h"
|
||||
#include "OnePole.h"
|
||||
|
||||
#define DRUM_NUMWAVES 10
|
||||
#define DRUM_NUMWAVES 11
|
||||
#define DRUM_POLYPHONY 4
|
||||
|
||||
class DrumSynt : public Object
|
||||
class DrumSynt : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
RawWvIn *waves[DRUM_POLYPHONY];
|
||||
@@ -30,8 +30,8 @@ class DrumSynt : public Object
|
||||
public:
|
||||
DrumSynt();
|
||||
/* ~DrumSynt(); */
|
||||
void noteOn(int noteNum, int vel);
|
||||
MY_FLOAT tick();
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
20
Envelope.cpp
20
Envelope.cpp
@@ -16,9 +16,9 @@
|
||||
|
||||
Envelope :: Envelope() : Object()
|
||||
{
|
||||
target = 0.0;
|
||||
value = 0.0;
|
||||
rate = 0.001;
|
||||
target = (MY_FLOAT) 0.0;
|
||||
value = (MY_FLOAT) 0.0;
|
||||
rate = (MY_FLOAT) 0.001;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
@@ -28,13 +28,13 @@ Envelope :: ~Envelope()
|
||||
|
||||
void Envelope :: keyOn()
|
||||
{
|
||||
target = 1.0;
|
||||
target = (MY_FLOAT) 1.0;
|
||||
if (value != target) state = 1;
|
||||
}
|
||||
|
||||
void Envelope :: keyOff()
|
||||
{
|
||||
target = 0.0;
|
||||
target = (MY_FLOAT) 0.0;
|
||||
if (value != target) state = 1;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,15 @@ void Envelope :: setRate(MY_FLOAT aRate)
|
||||
rate = -aRate;
|
||||
}
|
||||
else rate = aRate;
|
||||
rate = rate * RATE_NORM; /* SEE Object.h */
|
||||
}
|
||||
|
||||
void Envelope :: setTime(MY_FLOAT aTime)
|
||||
{
|
||||
if (aTime < 0.0) {
|
||||
printf("negative times not allowed!!, correcting\n");
|
||||
rate = ONE_OVER_SRATE / -aTime ;
|
||||
}
|
||||
else rate = ONE_OVER_SRATE / aTime ;
|
||||
}
|
||||
|
||||
void Envelope :: setTarget(MY_FLOAT aTarget)
|
||||
|
||||
@@ -26,10 +26,11 @@ class Envelope : public Object
|
||||
int state;
|
||||
public:
|
||||
Envelope();
|
||||
~Envelope();
|
||||
virtual ~Envelope();
|
||||
void keyOn();
|
||||
void keyOff();
|
||||
void setRate(MY_FLOAT aRate);
|
||||
void setTime(MY_FLOAT aTime);
|
||||
void setTarget(MY_FLOAT aTarget);
|
||||
void setValue(MY_FLOAT aValue);
|
||||
MY_FLOAT tick();
|
||||
|
||||
21
FM4Alg3.cpp
21
FM4Alg3.cpp
@@ -22,30 +22,35 @@ FM4Alg3 :: FM4Alg3() : FM4Op()
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
FM4Alg3 :: ~FM4Alg3()
|
||||
{
|
||||
}
|
||||
|
||||
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 = vibWave->tick() * modDepth * (MY_FLOAT) 0.2;
|
||||
waves[0]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * ((MY_FLOAT) 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();
|
||||
temp = ((MY_FLOAT) 1.0 - (control2 * (MY_FLOAT) 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 += control2 * (MY_FLOAT) 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;
|
||||
lastOutput = temp * (MY_FLOAT) 0.5;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ class FM4Alg3 : public FM4Op
|
||||
{
|
||||
public:
|
||||
FM4Alg3();
|
||||
virtual ~FM4Alg3();
|
||||
MY_FLOAT tick();
|
||||
};
|
||||
|
||||
|
||||
21
FM4Alg4.cpp
21
FM4Alg4.cpp
@@ -22,27 +22,32 @@ FM4Alg4 :: FM4Alg4() : FM4Op()
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
FM4Alg4 :: ~FM4Alg4()
|
||||
{
|
||||
}
|
||||
|
||||
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]);
|
||||
temp = vibWave->tick() * modDepth * (MY_FLOAT) 0.2;
|
||||
waves[0]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * ((MY_FLOAT) 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 = ((MY_FLOAT) 1.0 - (control2 * (MY_FLOAT) 0.5)) *
|
||||
gains[2] * adsr[2]->tick() * waves[2]->tick();
|
||||
temp += control2 * (MY_FLOAT) 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;
|
||||
lastOutput = temp * (MY_FLOAT) 0.5;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ class FM4Alg4 : public FM4Op
|
||||
{
|
||||
public:
|
||||
FM4Alg4();
|
||||
virtual ~FM4Alg4();
|
||||
MY_FLOAT tick();
|
||||
};
|
||||
|
||||
|
||||
13
FM4Alg5.cpp
13
FM4Alg5.cpp
@@ -25,6 +25,10 @@ FM4Alg5 :: FM4Alg5() : FM4Op()
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
FM4Alg5 :: ~FM4Alg5()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT FM4Alg5 :: tick()
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
@@ -36,13 +40,14 @@ MY_FLOAT FM4Alg5 :: tick()
|
||||
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();
|
||||
temp = ((MY_FLOAT) 1.0 - (control2 * (MY_FLOAT) 0.5)) *
|
||||
gains[0] * adsr[0]->tick() * waves[0]->tick();
|
||||
temp += control2 * (MY_FLOAT) 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 */
|
||||
temp = temp * ((MY_FLOAT) 1.0 + temp2); /* and apply it to output */
|
||||
|
||||
lastOutput = temp * 0.5;
|
||||
lastOutput = temp * (MY_FLOAT) 0.5;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ class FM4Alg5 : public FM4Op
|
||||
{
|
||||
public:
|
||||
FM4Alg5();
|
||||
virtual ~FM4Alg5();
|
||||
MY_FLOAT tick();
|
||||
};
|
||||
|
||||
|
||||
16
FM4Alg6.cpp
16
FM4Alg6.cpp
@@ -24,17 +24,21 @@ FM4Alg6 :: FM4Alg6() : FM4Op()
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
FM4Alg6 :: ~FM4Alg6()
|
||||
{
|
||||
}
|
||||
|
||||
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 */
|
||||
temp2 = vibWave->tick() * modDepth * (MY_FLOAT) 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]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp2) * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp2) * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp2) * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp2) * ratios[3]);
|
||||
|
||||
waves[0]->addPhaseOffset(temp * mods[0]);
|
||||
waves[1]->addPhaseOffset(temp * mods[1]);
|
||||
@@ -45,7 +49,7 @@ MY_FLOAT FM4Alg6 :: 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;
|
||||
return temp * (MY_FLOAT) 0.33;
|
||||
}
|
||||
|
||||
void FM4Alg6 :: controlChange(int number, MY_FLOAT value)
|
||||
|
||||
@@ -28,6 +28,7 @@ class FM4Alg6 : public FM4Op
|
||||
MY_FLOAT mods[3];
|
||||
public:
|
||||
FM4Alg6();
|
||||
virtual ~FM4Alg6();
|
||||
MY_FLOAT tick();
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
10
FM4Alg8.cpp
10
FM4Alg8.cpp
@@ -26,18 +26,22 @@ FM4Alg8 :: FM4Alg8() : FM4Op()
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
FM4Alg8 :: ~FM4Alg8()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT FM4Alg8 :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
|
||||
waves[3]->addPhaseOffset(twozero->lastOut());
|
||||
temp = control1 * 2.0 * gains[3] * adsr[3]->tick() * waves[3]->tick();
|
||||
temp = control1 * (MY_FLOAT) 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 += control2 * (MY_FLOAT) 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;
|
||||
lastOutput = temp * (MY_FLOAT) 0.125;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ class FM4Alg8 : public FM4Op
|
||||
{
|
||||
public:
|
||||
FM4Alg8();
|
||||
virtual ~FM4Alg8();
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
|
||||
59
FM4Op.cpp
59
FM4Op.cpp
@@ -14,12 +14,13 @@
|
||||
/*******************************************/
|
||||
|
||||
#include "FM4Op.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
FM4Op :: FM4Op()
|
||||
{
|
||||
int i;
|
||||
MY_FLOAT temp;
|
||||
MY_FLOAT tempCoeffs[2] = {0.0, -1.0};
|
||||
MY_FLOAT tempCoeffs[2] = {(MY_FLOAT) 0.0, (MY_FLOAT) -1.0};
|
||||
adsr[0] = new ADSR;
|
||||
adsr[1] = new ADSR;
|
||||
adsr[2] = new ADSR;
|
||||
@@ -27,37 +28,37 @@ FM4Op :: FM4Op()
|
||||
twozero = new TwoZero;
|
||||
vibWave = new RawLoop("rawwaves/sinewave.raw");
|
||||
vibWave->normalize();
|
||||
vibWave->setFreq(6.0); /* should make this random?? */
|
||||
modDepth = 0.0;
|
||||
vibWave->setFreq((MY_FLOAT) 6.0); /* should make this random?? */
|
||||
modDepth = (MY_FLOAT) 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;
|
||||
baseFreq = (MY_FLOAT) 440.0;
|
||||
ratios[0] = (MY_FLOAT) 1.0;
|
||||
ratios[1] = (MY_FLOAT) 1.0;
|
||||
ratios[2] = (MY_FLOAT) 1.0;
|
||||
ratios[3] = (MY_FLOAT) 1.0;
|
||||
gains[0] = (MY_FLOAT) 1.0;
|
||||
gains[1] = (MY_FLOAT) 1.0;
|
||||
gains[2] = (MY_FLOAT) 1.0;
|
||||
gains[3] = (MY_FLOAT) 1.0;
|
||||
twozero->setZeroCoeffs(tempCoeffs);
|
||||
twozero->setGain(0.0);
|
||||
control1 = 1.0;
|
||||
control2 = 1.0;
|
||||
temp = 1.0;
|
||||
twozero->setGain((MY_FLOAT) 0.0);
|
||||
control1 = (MY_FLOAT) 1.0;
|
||||
control2 = (MY_FLOAT) 1.0;
|
||||
temp = (MY_FLOAT) 1.0;
|
||||
for (i=99;i>=0;i--) {
|
||||
__FM4Op_gains[i] = temp;
|
||||
temp *= 0.933033;
|
||||
temp *= (MY_FLOAT) 0.933033;
|
||||
}
|
||||
temp = 1.0;
|
||||
temp = (MY_FLOAT) 1.0;
|
||||
for (i=15;i>=0;i--) {
|
||||
__FM4Op_susLevels[i] = temp;
|
||||
temp *= 0.707101;
|
||||
temp *= (MY_FLOAT) 0.707101;
|
||||
}
|
||||
temp = 8.498186;
|
||||
temp = (MY_FLOAT) 8.498186;
|
||||
for (i=0;i<32;i++) {
|
||||
__FM4Op_attTimes[i] = temp;
|
||||
temp *= 0.707101;
|
||||
temp *= (MY_FLOAT) 0.707101;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,12 +146,12 @@ void FM4Op :: setModulationDepth(MY_FLOAT mDepth)
|
||||
|
||||
void FM4Op :: setControl1(MY_FLOAT cVal)
|
||||
{
|
||||
control1 = cVal*2.0;
|
||||
control1 = cVal * (MY_FLOAT) 2.0;
|
||||
}
|
||||
|
||||
void FM4Op :: setControl2(MY_FLOAT cVal)
|
||||
{
|
||||
control2 = cVal*2.0;
|
||||
control2 = cVal * (MY_FLOAT) 2.0;
|
||||
}
|
||||
|
||||
void FM4Op :: controlChange(int number, MY_FLOAT value)
|
||||
@@ -158,15 +159,15 @@ 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)
|
||||
if (number == __SK_Breath_)
|
||||
this->setControl1(value * NORM_7);
|
||||
else if (number == MIDI_control2)
|
||||
else if (number == __SK_FootControl_)
|
||||
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)
|
||||
else if (number == __SK_ModFrequency_)
|
||||
this->setModulationSpeed(value * NORM_7 * (MY_FLOAT) 12.0); /* 0 to 12 Hz */
|
||||
else if (number == __SK_ModWheel_)
|
||||
this->setModulationDepth(value * NORM_7);
|
||||
else if (number == MIDI_after_touch) {
|
||||
else if (number == __SK_AfterTouch_Cont_) {
|
||||
adsr[0]->setTarget(value * NORM_7);
|
||||
adsr[1]->setTarget(value * NORM_7);
|
||||
adsr[2]->setTarget(value * NORM_7);
|
||||
|
||||
2
FM4Op.h
2
FM4Op.h
@@ -39,7 +39,7 @@ class FM4Op : public Instrmnt
|
||||
MY_FLOAT __FM4Op_attTimes[32];
|
||||
public:
|
||||
FM4Op();
|
||||
~FM4Op();
|
||||
virtual ~FM4Op();
|
||||
void loadWaves(char* wave1, char* wave2, char* wave3, char* wave4);
|
||||
void clear();
|
||||
void setFreq(MY_FLOAT frequency);
|
||||
|
||||
81
FMVoices.cpp
81
FMVoices.cpp
@@ -6,6 +6,7 @@
|
||||
/******************************************/
|
||||
|
||||
#include "FMVoices.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
FMVoices :: FMVoices() : FM4Alg6()
|
||||
{
|
||||
@@ -14,29 +15,37 @@ FMVoices :: FMVoices() : FM4Alg6()
|
||||
"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);
|
||||
this->setRatio(0,(MY_FLOAT) 2.00);
|
||||
this->setRatio(1,(MY_FLOAT) 4.00);
|
||||
this->setRatio(2,(MY_FLOAT) 12.0);
|
||||
this->setRatio(3,(MY_FLOAT) 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;
|
||||
adsr[0]->setAllTimes((MY_FLOAT) 0.050,(MY_FLOAT) 0.050,
|
||||
__FM4Op_susLevels[15],(MY_FLOAT) 0.050);
|
||||
adsr[1]->setAllTimes((MY_FLOAT) 0.050,(MY_FLOAT) 0.050,
|
||||
__FM4Op_susLevels[15],(MY_FLOAT) 0.050);
|
||||
adsr[2]->setAllTimes((MY_FLOAT) 0.050,(MY_FLOAT) 0.050,
|
||||
__FM4Op_susLevels[15],(MY_FLOAT) 0.050);
|
||||
adsr[3]->setAllTimes((MY_FLOAT) 0.010,(MY_FLOAT) 0.010,
|
||||
__FM4Op_susLevels[15],(MY_FLOAT) 0.500);
|
||||
twozero->setGain((MY_FLOAT) 0.0);
|
||||
modDepth = (MY_FLOAT) 0.005;
|
||||
currentVowel = 0;
|
||||
tilt[0] = 1.0;
|
||||
tilt[1] = 0.5;
|
||||
tilt[2] = 0.2;
|
||||
mods[0] = 1.0;
|
||||
mods[1] = 1.1;
|
||||
mods[2] = 1.1;
|
||||
baseFreq = 110.0;
|
||||
this->setFreq(110.0);
|
||||
tilt[0] = (MY_FLOAT) 1.0;
|
||||
tilt[1] = (MY_FLOAT) 0.5;
|
||||
tilt[2] = (MY_FLOAT) 0.2;
|
||||
mods[0] = (MY_FLOAT) 1.0;
|
||||
mods[1] = (MY_FLOAT) 1.1;
|
||||
mods[2] = (MY_FLOAT) 1.1;
|
||||
baseFreq = (MY_FLOAT) 110.0;
|
||||
this->setFreq((MY_FLOAT) 110.0);
|
||||
}
|
||||
|
||||
#include "phonTabl.h"
|
||||
/* #include "phonTabl.h" */
|
||||
|
||||
extern double phonGains[32][2];
|
||||
extern double phonParams[32][4][3];
|
||||
extern char phonemes[32][4];
|
||||
|
||||
void FMVoices :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
@@ -45,33 +54,33 @@ void FMVoices :: setFreq(MY_FLOAT frequency)
|
||||
|
||||
if (currentVowel < 16) {
|
||||
tempi2 = currentVowel;
|
||||
temp2 = 0.9;
|
||||
temp2 = (MY_FLOAT) 0.9;
|
||||
}
|
||||
else if (currentVowel < 32) {
|
||||
tempi2 = currentVowel - 16;
|
||||
temp2 = 1.0;
|
||||
temp2 = (MY_FLOAT) 1.0;
|
||||
}
|
||||
else if (currentVowel < 48) {
|
||||
tempi2 = currentVowel - 32;
|
||||
temp2 = 1.1;
|
||||
temp2 = (MY_FLOAT) 1.1;
|
||||
}
|
||||
else if (currentVowel < 64) {
|
||||
else if (currentVowel <= 64) {
|
||||
tempi2 = currentVowel - 48;
|
||||
temp2 = 1.2;
|
||||
temp2 = (MY_FLOAT) 1.2;
|
||||
}
|
||||
baseFreq = frequency;
|
||||
temp = (temp2 * phonParams[tempi2][0][0] / baseFreq) + 0.5;
|
||||
temp = (temp2 * (MY_FLOAT) phonParams[tempi2][0][0] / baseFreq) + (MY_FLOAT) 0.5;
|
||||
tempi = (int) temp;
|
||||
this->setRatio(0,(MY_FLOAT) tempi);
|
||||
temp = (temp2 * phonParams[tempi2][1][0] / baseFreq) + 0.5;
|
||||
temp = (temp2 * (MY_FLOAT) phonParams[tempi2][1][0] / baseFreq) + (MY_FLOAT) 0.5;
|
||||
tempi = (int) temp;
|
||||
this->setRatio(1,(MY_FLOAT) tempi);
|
||||
temp = (temp2 * phonParams[tempi2][2][0] / baseFreq) + 0.5;
|
||||
temp = (temp2 * (MY_FLOAT) phonParams[tempi2][2][0] / baseFreq) + (MY_FLOAT) 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);
|
||||
gains[0] = (MY_FLOAT) 1.0; // pow(10.0,phonParams[tempi2][0][2] * 0.05);
|
||||
gains[1] = (MY_FLOAT) 1.0; // pow(10.0,phonParams[tempi2][1][2] * 0.05);
|
||||
gains[2] = (MY_FLOAT) 1.0; // pow(10.0,phonParams[tempi2][2][2] * 0.05);
|
||||
}
|
||||
|
||||
void FMVoices :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
@@ -94,18 +103,18 @@ void FMVoices :: controlChange(int number, MY_FLOAT value)
|
||||
#if defined(_debug_)
|
||||
printf("FM4Op : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == MIDI_control1)
|
||||
if (number == __SK_Breath_)
|
||||
gains[3] = __FM4Op_gains[(int) (value * 0.78125)];
|
||||
else if (number == MIDI_control2) {
|
||||
else if (number == __SK_FootControl_) {
|
||||
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)
|
||||
else if (number == __SK_ModFrequency_)
|
||||
this->setModulationSpeed(value * NORM_7 * (MY_FLOAT) 12.0); /* 0 to 12 Hz */
|
||||
else if (number == __SK_ModWheel_)
|
||||
this->setModulationDepth(value * NORM_7);
|
||||
else if (number == MIDI_after_touch) {
|
||||
else if (number == __SK_AfterTouch_Cont_) {
|
||||
temp = value * NORM_7;
|
||||
tilt[0] = temp;
|
||||
tilt[1] = temp * temp;
|
||||
|
||||
2
Filter.h
2
Filter.h
@@ -21,7 +21,7 @@ class Filter : public Object
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Filter();
|
||||
~Filter();
|
||||
virtual ~Filter();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
|
||||
61
Flute.cpp
61
Flute.cpp
@@ -15,13 +15,14 @@
|
||||
/******************************************/
|
||||
|
||||
#include "Flute.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
Flute :: Flute(MY_FLOAT lowestFreq)
|
||||
{
|
||||
long length;
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
boreDelay = new DLineL(length);
|
||||
length >> 1;
|
||||
length >>= 1;
|
||||
jetDelay = new DLineL(length);
|
||||
jetTable = new JetTabl;
|
||||
filter = new OnePole;
|
||||
@@ -31,19 +32,21 @@ Flute :: Flute(MY_FLOAT lowestFreq)
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
this->clear();
|
||||
|
||||
boreDelay->setDelay(100.0);
|
||||
jetDelay->setDelay(49.0);
|
||||
boreDelay->setDelay((MY_FLOAT) 100.0);
|
||||
jetDelay->setDelay((MY_FLOAT) 49.0);
|
||||
|
||||
filter->setPole(0.7 - (0.1 * RATE_NORM));
|
||||
filter->setGain(-1.0);
|
||||
filter->setPole((MY_FLOAT) 0.7 - ((MY_FLOAT) 0.1 * (MY_FLOAT) 22050.0 / SRATE));
|
||||
filter->setGain((MY_FLOAT) -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;
|
||||
vibr->setFreq((MY_FLOAT) 5.925);
|
||||
adsr->setAllTimes((MY_FLOAT) 0.005, (MY_FLOAT) 0.01, (MY_FLOAT) 0.8, (MY_FLOAT) 0.010);
|
||||
endRefl = (MY_FLOAT) 0.5;
|
||||
jetRefl = (MY_FLOAT) 0.5;
|
||||
noiseGain = (MY_FLOAT) 0.15; /* Breath pressure random component */
|
||||
vibrGain = (MY_FLOAT) 0.05; /* breath periodic vibrato component */
|
||||
jetRatio = (MY_FLOAT) 0.32;
|
||||
|
||||
maxPressure = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
Flute :: ~Flute()
|
||||
@@ -70,8 +73,8 @@ void Flute :: clear()
|
||||
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 */
|
||||
lastFreq = frequency * (MY_FLOAT) 0.66666; /* we're overblowing here */
|
||||
temp = SRATE / lastFreq - (MY_FLOAT) 2.0; /* Length - approx. filter delay */
|
||||
boreDelay->setDelay(temp); /* Length of bore tube */
|
||||
jetDelay->setDelay(temp * jetRatio); /* jet delay shorter */
|
||||
}
|
||||
@@ -79,7 +82,7 @@ void Flute :: setFreq(MY_FLOAT frequency)
|
||||
void Flute :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate)
|
||||
{
|
||||
adsr->setAttackRate(rate);
|
||||
maxPressure = amplitude / 0.8;
|
||||
maxPressure = amplitude / (MY_FLOAT) 0.8;
|
||||
adsr->keyOn();
|
||||
}
|
||||
|
||||
@@ -92,8 +95,8 @@ void Flute :: stopBlowing(MY_FLOAT rate)
|
||||
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;
|
||||
this->startBlowing((MY_FLOAT) 1.1 + (amp * (MY_FLOAT) 0.20),amp * (MY_FLOAT) 0.02);
|
||||
outputGain = amp + (MY_FLOAT) 0.001;
|
||||
#if defined(_debug_)
|
||||
printf("Flute : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
@@ -101,7 +104,7 @@ void Flute :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
|
||||
void Flute :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->stopBlowing(amp * 0.02);
|
||||
this->stopBlowing(amp * (MY_FLOAT) 0.02);
|
||||
#if defined(_debug_)
|
||||
printf("Flute : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
@@ -120,7 +123,7 @@ void Flute :: setEndRefl(MY_FLOAT refl)
|
||||
void Flute :: setJetDelay(MY_FLOAT aRatio)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
temp = SRATE / lastFreq - 2.0; /* Length - approx. filter delay */
|
||||
temp = SRATE / lastFreq - (MY_FLOAT) 2.0; /* Length - approx. filter delay */
|
||||
jetRatio = aRatio;
|
||||
jetDelay->setDelay(temp * aRatio); /* Scaled by ratio */
|
||||
}
|
||||
@@ -144,7 +147,7 @@ MY_FLOAT Flute :: tick()
|
||||
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 = (MY_FLOAT) 0.3 * boreDelay->tick(pressureDiff); /* Bore Delay and "bell" filter */
|
||||
|
||||
lastOutput *= outputGain;
|
||||
return lastOutput;
|
||||
@@ -156,15 +159,15 @@ 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)
|
||||
if (number == __SK_JetDelay_)
|
||||
this->setJetDelay((MY_FLOAT) 0.08 + ((MY_FLOAT) 0.48 * value * NORM_7));
|
||||
else if (number == __SK_NoiseLevel_)
|
||||
noiseGain = (value * NORM_7 * (MY_FLOAT) 0.4);
|
||||
else if (number == __SK_ModFrequency_)
|
||||
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
|
||||
else if (number == __SK_ModWheel_)
|
||||
vibrGain = (value * NORM_7 * (MY_FLOAT) 0.4);
|
||||
else if (number == __SK_AfterTouch_Cont_)
|
||||
adsr->setTarget(value * NORM_7);
|
||||
else {
|
||||
printf("Flute : Undefined Control Number!!\n");
|
||||
|
||||
50
FormSwep.cpp
50
FormSwep.cpp
@@ -11,22 +11,22 @@
|
||||
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;
|
||||
poleCoeffs[0] = (MY_FLOAT) 0.0;
|
||||
poleCoeffs[1] = (MY_FLOAT) 0.0;
|
||||
gain = (MY_FLOAT) 1.0;
|
||||
freq = (MY_FLOAT) 0.0;
|
||||
reson = (MY_FLOAT) 0.0;
|
||||
currentGain = (MY_FLOAT) 1.0;
|
||||
currentFreq = (MY_FLOAT) 0.0;
|
||||
currentReson = (MY_FLOAT) 0.0;
|
||||
targetGain = (MY_FLOAT) 1.0;
|
||||
targetFreq = (MY_FLOAT) 0.0;
|
||||
targetReson = (MY_FLOAT) 0.0;
|
||||
deltaGain = (MY_FLOAT) 0.0;
|
||||
deltaFreq = (MY_FLOAT) 0.0;
|
||||
deltaReson = (MY_FLOAT) 0.0;
|
||||
sweepState = (MY_FLOAT) 0.0;
|
||||
sweepRate = (MY_FLOAT) 0.002;
|
||||
dirty = 0;
|
||||
this->clear();
|
||||
}
|
||||
@@ -38,8 +38,8 @@ FormSwep :: ~FormSwep()
|
||||
|
||||
void FormSwep :: clear()
|
||||
{
|
||||
outputs[0] = 0.0;
|
||||
outputs[1] = 0.0;
|
||||
outputs[0] = (MY_FLOAT) 0.0;
|
||||
outputs[1] = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void FormSwep :: setPoleCoeffs(MY_FLOAT *coeffs)
|
||||
@@ -57,7 +57,7 @@ void FormSwep :: setFreqAndReson(MY_FLOAT aFreq, MY_FLOAT aReson)
|
||||
currentReson = aReson;
|
||||
currentFreq = aFreq;
|
||||
poleCoeffs[1] = - (reson * reson);
|
||||
poleCoeffs[0] = 2.0 * reson * cos(TWO_PI * freq / SRATE);
|
||||
poleCoeffs[0] = (MY_FLOAT) 2.0 * reson * (MY_FLOAT) cos(TWO_PI * freq / SRATE);
|
||||
}
|
||||
|
||||
void FormSwep :: setStates(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain)
|
||||
@@ -83,7 +83,7 @@ void FormSwep :: setTargets(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain)
|
||||
deltaFreq = aFreq - currentFreq;
|
||||
deltaReson = aReson - currentReson;
|
||||
deltaGain = aGain - currentGain;
|
||||
sweepState = 0.0;
|
||||
sweepState = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void FormSwep :: setSweepRate(MY_FLOAT aRate)
|
||||
@@ -91,6 +91,11 @@ void FormSwep :: setSweepRate(MY_FLOAT aRate)
|
||||
sweepRate = aRate;
|
||||
}
|
||||
|
||||
void FormSwep :: setSweepTime(MY_FLOAT aTime)
|
||||
{
|
||||
sweepRate = ONE_OVER_SRATE / aTime;
|
||||
}
|
||||
|
||||
void FormSwep :: setGain(MY_FLOAT aValue)
|
||||
{
|
||||
gain = aValue;
|
||||
@@ -103,7 +108,7 @@ MY_FLOAT FormSwep :: tick(MY_FLOAT sample) /* Perform Filter Operation */
|
||||
if (dirty) {
|
||||
sweepState += sweepRate;
|
||||
if (sweepState>= 1.0) {
|
||||
sweepState = 1.0;
|
||||
sweepState = (MY_FLOAT) 1.0;
|
||||
dirty = 0;
|
||||
currentReson = targetReson;
|
||||
reson = targetReson;
|
||||
@@ -118,7 +123,8 @@ MY_FLOAT FormSwep :: tick(MY_FLOAT sample) /* Perform Filter Operation */
|
||||
currentGain = gain + (deltaGain * sweepState);
|
||||
}
|
||||
poleCoeffs[1] = - (currentReson * currentReson);
|
||||
poleCoeffs[0] = 2.0 * currentReson * cos(TWO_PI * currentFreq / SRATE);
|
||||
poleCoeffs[0] = (MY_FLOAT) 2.0 * currentReson *
|
||||
(MY_FLOAT) cos(TWO_PI * currentFreq / SRATE);
|
||||
}
|
||||
|
||||
temp = currentGain * sample;
|
||||
|
||||
@@ -39,6 +39,7 @@ class FormSwep : public Filter
|
||||
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);
|
||||
void setSweepTime(MY_FLOAT aTime);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
22
HeavyMtl.cpp
22
HeavyMtl.cpp
@@ -14,21 +14,21 @@ HeavyMtl :: HeavyMtl() : FM4Alg3()
|
||||
"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);
|
||||
this->setRatio(0,(MY_FLOAT) (1.00 * 1.000));
|
||||
this->setRatio(1,(MY_FLOAT) (4.00 * 0.999));
|
||||
this->setRatio(2,(MY_FLOAT) (3.00 * 1.001));
|
||||
this->setRatio(3,(MY_FLOAT) (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;
|
||||
adsr[0]->setAllTimes((MY_FLOAT) 0.001,(MY_FLOAT) 0.001,(MY_FLOAT) 1.0,(MY_FLOAT) 0.01);
|
||||
adsr[1]->setAllTimes((MY_FLOAT) 0.001,(MY_FLOAT) 0.010,(MY_FLOAT) 1.0,(MY_FLOAT) 0.50);
|
||||
adsr[2]->setAllTimes((MY_FLOAT) 0.010,(MY_FLOAT) 0.005,(MY_FLOAT) 1.0,(MY_FLOAT) 0.20);
|
||||
adsr[3]->setAllTimes((MY_FLOAT) 0.030,(MY_FLOAT) 0.010,(MY_FLOAT) 0.2,(MY_FLOAT) 0.20);
|
||||
twozero->setGain((MY_FLOAT) 2.0);
|
||||
vibWave->setFreq((MY_FLOAT) 5.5);
|
||||
modDepth = (MY_FLOAT) 0.00;
|
||||
}
|
||||
|
||||
HeavyMtl :: ~HeavyMtl()
|
||||
|
||||
10
Instrmnt.cpp
10
Instrmnt.cpp
@@ -9,20 +9,29 @@ Instrmnt :: Instrmnt()
|
||||
{
|
||||
}
|
||||
|
||||
Instrmnt :: ~Instrmnt()
|
||||
{
|
||||
}
|
||||
|
||||
void Instrmnt :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
printf("Warning!! Instrument Class noteOn here!! %f %f\n",freq,amp);
|
||||
}
|
||||
|
||||
void Instrmnt :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
printf("Warning!! Instrument Class noteOff here!! %f\n",amp);
|
||||
}
|
||||
|
||||
void Instrmnt :: setFreq(MY_FLOAT freq)
|
||||
{
|
||||
printf("Warning!! Instrument Class setFreq here!! %f\n",freq);
|
||||
}
|
||||
|
||||
MY_FLOAT Instrmnt :: tick()
|
||||
{
|
||||
printf("Warning!! Instrument Class tick here!!\n");
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT Instrmnt :: lastOut()
|
||||
@@ -32,4 +41,5 @@ MY_FLOAT Instrmnt :: lastOut()
|
||||
|
||||
void Instrmnt :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
printf("Warning!! Instrument Class Control Change here!! %i %f\n",number,value);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ class Instrmnt : public Object
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Instrmnt();
|
||||
virtual ~Instrmnt();
|
||||
MY_FLOAT lastOut();
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
|
||||
166
JCRev.cpp
Normal file
166
JCRev.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
/*******************************************/
|
||||
/* JVRev Reverb Subclass */
|
||||
/* by Tim Stilson, 1998 */
|
||||
/* based on CLM JCRev */
|
||||
/* Integrated into STK by Gary Scavone */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* arrangement consists of 3 allpass */
|
||||
/* filters in series, followed by 4 comb */
|
||||
/* filters in parallel, an optional */
|
||||
/* lowpass filter, and two decorrelation */
|
||||
/* delay lines in parallel at the output. */
|
||||
/*******************************************/
|
||||
|
||||
#include "JCRev.h"
|
||||
|
||||
//#define LOWPASS
|
||||
|
||||
JCRev :: JCRev(MY_FLOAT T60)
|
||||
{
|
||||
/* These are the values from CLM's JCRev.ins ... I found that the
|
||||
impulse response sounded better with the shorter delay lengths.
|
||||
--Gary Scavone, 2/1998
|
||||
int lens[9] = {4799,4999,5399,5801,1051,337,113,573,487};
|
||||
*/
|
||||
int lens[9] = {1777,1847,1993,2137,389,127,43,211,179};
|
||||
int val, i;
|
||||
|
||||
if (SRATE < 44100.0) {
|
||||
double srscale = SRATE / 44100.0;
|
||||
for (i=0; i<9; i++) {
|
||||
val = (int) floor(srscale * lens[i]);
|
||||
if ((val & 1) == 0) val++;
|
||||
while (!this->isprime(val)) val += 2;
|
||||
lens[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
APdelayLine[i] = new DLineN(lens[i+4] + 2);
|
||||
APdelayLine[i]->setDelay(lens[i+4]);
|
||||
}
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
CdelayLine[i] = new DLineN(lens[i] + 2);
|
||||
CdelayLine[i]->setDelay(lens[i]);
|
||||
combCoeff[i] = pow(10,(-3 * lens[i] / (T60 * SRATE)));
|
||||
// printf("combCoeff[%d] = %f\n", i, combCoeff[i]);
|
||||
}
|
||||
outLdelayLine = new DLineN(lens[7] + 2);
|
||||
outLdelayLine->setDelay(lens[7]);
|
||||
outRdelayLine = new DLineN(lens[8] + 2);
|
||||
outRdelayLine->setDelay(lens[8]);
|
||||
allPassCoeff = 0.7;
|
||||
effectMix = 0.3;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
JCRev :: ~JCRev()
|
||||
{
|
||||
delete APdelayLine[0];
|
||||
delete APdelayLine[1];
|
||||
delete APdelayLine[2];
|
||||
delete CdelayLine[0];
|
||||
delete CdelayLine[1];
|
||||
delete CdelayLine[2];
|
||||
delete CdelayLine[3];
|
||||
delete outLdelayLine;
|
||||
delete outRdelayLine;
|
||||
}
|
||||
|
||||
void JCRev :: clear()
|
||||
{
|
||||
APdelayLine[0]->clear();
|
||||
APdelayLine[1]->clear();
|
||||
APdelayLine[2]->clear();
|
||||
CdelayLine[0]->clear();
|
||||
CdelayLine[1]->clear();
|
||||
CdelayLine[2]->clear();
|
||||
CdelayLine[3]->clear();
|
||||
outRdelayLine->clear();
|
||||
outLdelayLine->clear();
|
||||
lastOutL = 0.0;
|
||||
lastOutR = 0.0;
|
||||
combsum1=0.0;
|
||||
combsum2=0.0;
|
||||
combsum=0.0;
|
||||
}
|
||||
|
||||
void JCRev :: setEffectMix(MY_FLOAT mix)
|
||||
{
|
||||
effectMix = mix;
|
||||
}
|
||||
|
||||
MY_FLOAT JCRev :: lastOutput()
|
||||
{
|
||||
return (lastOutL + lastOutR) * 0.5;
|
||||
}
|
||||
|
||||
MY_FLOAT JCRev :: lastOutputL()
|
||||
{
|
||||
return lastOutL;
|
||||
}
|
||||
|
||||
MY_FLOAT JCRev :: lastOutputR()
|
||||
{
|
||||
return lastOutR;
|
||||
}
|
||||
|
||||
MY_FLOAT JCRev :: tick(MY_FLOAT input)
|
||||
{
|
||||
MY_FLOAT temp,temp0,temp1,temp2,temp3,temp4,temp5,temp6;
|
||||
MY_FLOAT filtout;
|
||||
|
||||
temp = APdelayLine[0]->lastOut();
|
||||
temp0 = allPassCoeff * temp;
|
||||
temp0 += input;
|
||||
APdelayLine[0]->tick(temp0);
|
||||
temp0 = -(allPassCoeff * temp0) + temp;
|
||||
|
||||
temp = APdelayLine[1]->lastOut();
|
||||
temp1 = allPassCoeff * temp;
|
||||
temp1 += temp0;
|
||||
APdelayLine[1]->tick(temp1);
|
||||
temp1 = -(allPassCoeff * temp1) + temp;
|
||||
|
||||
temp = APdelayLine[2]->lastOut();
|
||||
temp2 = allPassCoeff * temp;
|
||||
temp2 += temp1;
|
||||
APdelayLine[2]->tick(temp2);
|
||||
temp2 = -(allPassCoeff * temp2) + temp;
|
||||
|
||||
temp3 = temp2 + (combCoeff[0] * CdelayLine[0]->lastOut());
|
||||
temp4 = temp2 + (combCoeff[1] * CdelayLine[1]->lastOut());
|
||||
temp5 = temp2 + (combCoeff[2] * CdelayLine[2]->lastOut());
|
||||
temp6 = temp2 + (combCoeff[3] * CdelayLine[3]->lastOut());
|
||||
|
||||
CdelayLine[0]->tick(temp3);
|
||||
CdelayLine[1]->tick(temp4);
|
||||
CdelayLine[2]->tick(temp5);
|
||||
CdelayLine[3]->tick(temp6);
|
||||
|
||||
#ifdef LOWPASS
|
||||
combsum2=combsum1;
|
||||
combsum1=combsum;
|
||||
combsum = temp3+temp4+temp5+temp6;
|
||||
filtout= 0.5*combsum1+0.25*(combsum+combsum2);
|
||||
#else
|
||||
filtout = temp3+temp4+temp5+temp6;
|
||||
#endif
|
||||
|
||||
lastOutL = effectMix * (outLdelayLine->tick(filtout));
|
||||
lastOutR = effectMix * (outRdelayLine->tick(filtout));
|
||||
temp = (1.0 - effectMix) * input;
|
||||
lastOutL += temp;
|
||||
lastOutR += temp;
|
||||
|
||||
return (lastOutL + lastOutR) * 0.5;
|
||||
|
||||
}
|
||||
52
JCRev.h
Normal file
52
JCRev.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*******************************************/
|
||||
/* JVRev Reverb Subclass */
|
||||
/* by Tim Stilson, 1998 */
|
||||
/* based on CLM JCRev */
|
||||
/* Integrated into STK by Gary Scavone */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* arrangement consists of 3 allpass */
|
||||
/* filters in series, followed by 4 comb */
|
||||
/* filters in parallel, an optional */
|
||||
/* lowpass filter, and two decorrelation */
|
||||
/* delay lines in parallel at the output. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__JCRev_h)
|
||||
#define __JCRev_h
|
||||
|
||||
#include "Object.h"
|
||||
#include "Reverb.h"
|
||||
#include "DLineN.h"
|
||||
|
||||
class JCRev : public Reverb
|
||||
{
|
||||
protected:
|
||||
DLineN *APdelayLine[3];
|
||||
DLineN *CdelayLine[4];
|
||||
DLineN *outLdelayLine;
|
||||
DLineN *outRdelayLine;
|
||||
MY_FLOAT allPassCoeff;
|
||||
MY_FLOAT combCoeff[4];
|
||||
MY_FLOAT combsum,combsum1,combsum2;
|
||||
MY_FLOAT lastOutL;
|
||||
MY_FLOAT lastOutR;
|
||||
MY_FLOAT effectMix;
|
||||
public:
|
||||
JCRev(MY_FLOAT T60);
|
||||
~JCRev();
|
||||
void clear();
|
||||
void setEffectMix(MY_FLOAT mix);
|
||||
MY_FLOAT lastOutput();
|
||||
MY_FLOAT lastOutputL();
|
||||
MY_FLOAT lastOutputR();
|
||||
MY_FLOAT tick(MY_FLOAT input);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
10
JetTabl.cpp
10
JetTabl.cpp
@@ -11,21 +11,21 @@
|
||||
|
||||
JetTabl :: JetTabl()
|
||||
{
|
||||
lastOutput = 0.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
JetTabl :: ~JetTabl()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT JetTabl :: lookup(double sample) /* Perform "Table Lookup" */
|
||||
MY_FLOAT JetTabl :: lookup(MY_FLOAT sample) /* Perform "Table Lookup" */
|
||||
{ /* By Polynomial Calculation */
|
||||
lastOutput = sample *
|
||||
(sample*sample - 1.0); /* (x^3 - x) approximates sigmoid of jet */
|
||||
(sample*sample - (MY_FLOAT) 1.0); /* (x^3 - x) approximates sigmoid of jet */
|
||||
if (lastOutput > 1.0)
|
||||
lastOutput = 1.0; /* Saturation at +/- 1.0 */
|
||||
lastOutput = (MY_FLOAT) 1.0; /* Saturation at +/- 1.0 */
|
||||
if (lastOutput < -1.0)
|
||||
lastOutput = -1.0;
|
||||
lastOutput = (MY_FLOAT) -1.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
class JetTabl : public Object
|
||||
{
|
||||
protected:
|
||||
double lastOutput;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
JetTabl();
|
||||
~JetTabl();
|
||||
double lookup(double deltaP);
|
||||
double lastOut();
|
||||
MY_FLOAT lookup(MY_FLOAT deltaP);
|
||||
MY_FLOAT 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 .......
|
||||
19
LipFilt.cpp
19
LipFilt.cpp
@@ -15,8 +15,8 @@ LipFilt :: LipFilt()
|
||||
{
|
||||
MY_FLOAT coeffs[2];
|
||||
filter = new BiQuad;
|
||||
coeffs[0] = 0.0;
|
||||
coeffs[1] = 0.0;
|
||||
coeffs[0] = (MY_FLOAT) 0.0;
|
||||
coeffs[1] = (MY_FLOAT) 0.0;
|
||||
filter->setZeroCoeffs(coeffs);
|
||||
this->clear();
|
||||
}
|
||||
@@ -29,17 +29,17 @@ LipFilt :: ~LipFilt()
|
||||
void LipFilt :: clear()
|
||||
{
|
||||
filter->clear();
|
||||
lastOutput = 0.0;
|
||||
lastOutput = (MY_FLOAT) 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.*/
|
||||
coeffs[0] = (MY_FLOAT) 2.0 * (MY_FLOAT) 0.997 *
|
||||
(MY_FLOAT) cos(TWO_PI * frequency / SRATE); /* damping should change with */
|
||||
coeffs[1] = (MY_FLOAT) (-0.997 * 0.997); /* lip parameters, but not yet.*/
|
||||
filter->setPoleCoeffs(coeffs);
|
||||
filter->setGain(0.03);
|
||||
filter->setGain((MY_FLOAT) 0.03);
|
||||
}
|
||||
|
||||
/* NOTE: Here we should add lip tension */
|
||||
@@ -53,9 +53,10 @@ MY_FLOAT LipFilt :: tick(MY_FLOAT mouthSample,MY_FLOAT boreSample)
|
||||
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 */
|
||||
if (temp > 1.0) temp = (MY_FLOAT) 1.0; /* Saturation at + 1.0 */
|
||||
lastOutput = temp * mouthSample; /* Assume mouth input = area */
|
||||
lastOutput += (1.0 - temp) * boreSample; /* and Bore reflection is compliment. */
|
||||
lastOutput += ((MY_FLOAT) 1.0 - temp)
|
||||
* boreSample; /* and Bore reflection is compliment. */
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
|
||||
378
MD2SKINI.cpp
Normal file
378
MD2SKINI.cpp
Normal file
@@ -0,0 +1,378 @@
|
||||
/*******************************************/
|
||||
/* Simple Realtime MIDI to SKINI Parser */
|
||||
/* Gary P. Scavone, February 1998. */
|
||||
/* Revised for sockets, May & June 1998. */
|
||||
/* */
|
||||
/* This object takes MIDI from the input */
|
||||
/* stream (via the MIDIIO class), */
|
||||
/* parses it, and turns it into SKINI */
|
||||
/* messages. */
|
||||
/*******************************************/
|
||||
|
||||
#include "miditabl.h"
|
||||
#include "MIDIIO.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
int outAHere = 0;
|
||||
|
||||
#if defined(__SGI_REALTIME_)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
pid_t exit_thread;
|
||||
|
||||
void newString(void *)
|
||||
{
|
||||
char inputString[128];
|
||||
printf("Type 'ex<cr>' to quit.\n");
|
||||
while (!outAHere) {
|
||||
fgets(inputString, 128, stdin);
|
||||
if (inputString[0] == 'e' && inputString[1] == 'x') {
|
||||
outAHere = 1;
|
||||
}
|
||||
else printf("Type 'ex<cr>' to quit.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__USS_REALTIME_)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
pthread_t exit_thread;
|
||||
|
||||
void *newString(void *)
|
||||
{
|
||||
char inputString[128];
|
||||
printf("Type 'ex<cr>' to quit.\n");
|
||||
while (!outAHere) {
|
||||
fgets(inputString, 128, stdin);
|
||||
if (inputString[0] == 'e' && inputString[1] == 'x') {
|
||||
outAHere = 1;
|
||||
}
|
||||
else printf("Type 'ex<cr>' to quit.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#elif (defined(__WINDS_REALTIME_) || defined(__WINMM_REALTIME_) )
|
||||
|
||||
#include <process.h>
|
||||
#include <winsock.h>
|
||||
|
||||
unsigned long exit_thread;
|
||||
|
||||
void newString(void *)
|
||||
{
|
||||
char inputString[128];
|
||||
printf("Type 'ex<cr>' to quit.\n");
|
||||
while (!outAHere) {
|
||||
fgets(inputString, 128, stdin);
|
||||
if (inputString[0] == 'e' && inputString[1] == 'x') {
|
||||
outAHere = 1;
|
||||
}
|
||||
else printf("Type 'ex<cr>' to quit.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void errorf(void) {
|
||||
printf("useage: MD2SKINI <file name>\n");
|
||||
printf(" where the optional <file name> specifies a file\n");
|
||||
printf(" to which the SKINI output stream is written.\n");
|
||||
printf(" The SKINI output stream is always written to stdout,\n");
|
||||
printf(" whether an output file is specified or not.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void main(int argc,char *argv[])
|
||||
{
|
||||
long j;
|
||||
int oneOn = 0;
|
||||
MY_FLOAT byte2, byte3;
|
||||
int channel;
|
||||
int firstMessage = 1;
|
||||
int writeFileOut = 0;
|
||||
FILE *fileOut;
|
||||
MIDIIO *controller;
|
||||
|
||||
if (argc>2) {
|
||||
errorf();
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
fileOut = fopen(argv[1],"wb");
|
||||
writeFileOut = 1;
|
||||
}
|
||||
|
||||
MY_FLOAT dt=0.0;
|
||||
|
||||
controller = new MIDIIO();
|
||||
|
||||
/* Setup the exit thread. */
|
||||
#if defined(__SGI_REALTIME_)
|
||||
exit_thread = sproc(newString, PR_SALL);
|
||||
if (exit_thread == -1) {
|
||||
fprintf(stderr, "Unable to create exit thread.\n");
|
||||
printf("Exiting MD2SKINI process.\n");
|
||||
exit(0);
|
||||
}
|
||||
#elif defined(__USS_REALTIME_)
|
||||
int err = 0;
|
||||
err = pthread_create(&exit_thread, NULL, newString, NULL);
|
||||
if (err)
|
||||
{
|
||||
fprintf(stderr, "Unable to create exit thread.\n");
|
||||
printf("Exiting MD2SKINI process.\n");
|
||||
exit(0);
|
||||
}
|
||||
#elif (defined(__WINDS_REALTIME_) || defined(__WINMM_REALTIME_) )
|
||||
exit_thread = _beginthread(newString, 0, NULL);
|
||||
if (exit_thread == -1) {
|
||||
fprintf(stderr, "Unable to create exit thread.\n");
|
||||
printf("Exiting MD2SKINI process.\n");
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup the client socket */
|
||||
#if defined(__SOCKET)
|
||||
|
||||
WORD wVersionRequested = MAKEWORD(1,1);
|
||||
WSADATA wsaData;
|
||||
SOCKET theSocket;
|
||||
int nRet;
|
||||
|
||||
nRet = WSAStartup(wVersionRequested, &wsaData);
|
||||
if (wsaData.wVersion != wVersionRequested)
|
||||
{
|
||||
fprintf(stderr,"\n Wrong version\n");
|
||||
outAHere = 1;
|
||||
WSACleanup();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
theSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (theSocket == INVALID_SOCKET)
|
||||
{
|
||||
fprintf(stderr,"socket open failed\n");
|
||||
outAHere = 1;
|
||||
WSACleanup();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Fill in the address structure */
|
||||
SOCKADDR_IN saServer;
|
||||
|
||||
/* Modified to always use the loopback address of 127.0.0.1 */
|
||||
saServer.sin_family = AF_INET;
|
||||
saServer.sin_port = htons(2001); // Port number from command line
|
||||
saServer.sin_addr.S_un.S_addr = inet_addr( "127.0.0.1" );
|
||||
|
||||
/* connect to the server */
|
||||
nRet = connect(theSocket, (LPSOCKADDR)&saServer, sizeof(struct sockaddr));
|
||||
if (nRet == SOCKET_ERROR)
|
||||
{
|
||||
fprintf(stderr,"socket connect failed\n");
|
||||
closesocket(theSocket);
|
||||
outAHere = 1;
|
||||
WSACleanup();
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write SKINI messages to buffer 's'. This is the easiest way
|
||||
to allow this single executable to work for both socketing
|
||||
and printf's to stdout.
|
||||
*/
|
||||
char s[128];
|
||||
|
||||
while (!outAHere) {
|
||||
if (controller->nextMessage() > 0) {
|
||||
byte3 = controller->getByteThree();
|
||||
byte2 = controller->getByteTwo();
|
||||
channel = controller->getChannel();
|
||||
if (writeFileOut) dt = controller->getDeltaTime();
|
||||
if (firstMessage) { /* first MIDI message time stamp is meaningless */
|
||||
dt = 0.0;
|
||||
firstMessage = 0;
|
||||
}
|
||||
|
||||
switch(controller->getType()) {
|
||||
case __SK_NoteOn_:
|
||||
if (byte3 < 1.0) {
|
||||
if (oneOn == 1) {
|
||||
sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,64.0);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"NoteOff\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,64.0);
|
||||
}
|
||||
}
|
||||
oneOn -= 1;
|
||||
} else {
|
||||
sprintf(s,"NoteOn\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"NoteOn\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
|
||||
}
|
||||
oneOn += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case __SK_NoteOff_:
|
||||
if (byte3 < 2.0) byte3 = 64.0;
|
||||
if (oneOn == 1) {
|
||||
sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
|
||||
}
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"NoteOff\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
|
||||
}
|
||||
oneOn -= 1;
|
||||
break;
|
||||
|
||||
case __SK_PolyPressure_:
|
||||
sprintf(s,"PolyPressure\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"PolyPressure\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
|
||||
}
|
||||
break;
|
||||
|
||||
case __SK_ControlChange_:
|
||||
j = (int) byte2;
|
||||
switch(j) {
|
||||
case __SK_Volume_:
|
||||
sprintf(s,"Volume\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Volume\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_ModWheel_:
|
||||
sprintf(s,"ModWheel\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"ModWheel\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_Breath_:
|
||||
sprintf(s,"Breath\t\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Breath\t\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_FootControl_:
|
||||
sprintf(s,"FootControl\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"FootControl\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_Portamento_:
|
||||
sprintf(s,"Portamento\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Portamento\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_Balance_:
|
||||
sprintf(s,"Balance\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Balance\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_Pan_:
|
||||
sprintf(s,"Pan\t\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Pan\t\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_Sustain_:
|
||||
sprintf(s,"Sustain\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Sustain\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_Expression_:
|
||||
sprintf(s,"Expression\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Expression\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sprintf(s,"ControlChange\t%.3f %d %ld %.1f\n",0.0,channel,j,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"ControlChange\t%.3f %d %ld %.1f\n",dt,channel,j,byte3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case __SK_ProgramChange_:
|
||||
j = (int) byte2;
|
||||
sprintf(s,"ProgramChange\t%.3f %d %ld\n",0.0,channel,j);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"ProgramChange\t%.3f %d %ld\n",dt,channel,j);
|
||||
}
|
||||
break;
|
||||
|
||||
case __SK_ChannelPressure_:
|
||||
sprintf(s,"ChannelPressure\t%.3f %d %.1f\n",0.0,channel,byte2);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"ChannelPressure\t%.3f %d %.1f\n",dt,channel,byte2);
|
||||
}
|
||||
break;
|
||||
|
||||
case __SK_PitchBend_:
|
||||
sprintf(s,"PitchBend\t%.3f %d %f\n",0.0,channel,byte2);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"PitchBend\t%.3f %d %f\n",dt,channel,byte2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sprintf(s,"// Unknown\t%.3f %d %f %f\n",0.0,channel,byte2,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"// Unknown\t\t%.3f %d %f %f\n",dt,channel,byte2,byte3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(__SOCKET)
|
||||
nRet = send(theSocket, s, strlen(s), 0);
|
||||
if (nRet == SOCKET_ERROR)
|
||||
{
|
||||
fprintf(stderr,"send failed\n");
|
||||
closesocket(theSocket);
|
||||
outAHere = 1;
|
||||
WSACleanup();
|
||||
exit(0);
|
||||
}
|
||||
#else
|
||||
printf("%s", s);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
memset(s, 0, sizeof(s));
|
||||
#if defined(__OS_Win_)
|
||||
} else Sleep ( (DWORD) 2);
|
||||
#else
|
||||
} else usleep( (unsigned long) 2000);
|
||||
#endif
|
||||
}
|
||||
|
||||
sprintf(s,"Exiting MD2SKINI process ... bye!\n");
|
||||
#if defined(__SOCKET)
|
||||
nRet = send(theSocket, s, strlen(s), 0);
|
||||
closesocket(theSocket);
|
||||
WSACleanup();
|
||||
#else
|
||||
printf("%s", s);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
if (writeFileOut) {
|
||||
printf("Wrote SKINI output to file %s.\n", argv[1]);
|
||||
fclose(fileOut);
|
||||
}
|
||||
delete controller;
|
||||
|
||||
#if defined(__SGI_REALTIME_)
|
||||
kill(exit_thread, SIGKILL);
|
||||
#endif
|
||||
}
|
||||
|
||||
574
MIDIIO.cpp
Normal file
574
MIDIIO.cpp
Normal file
@@ -0,0 +1,574 @@
|
||||
/******************************************/
|
||||
/* MIDIIO.cpp */
|
||||
/* Realtime MIDI I/O Object for STK, */
|
||||
/* by Gary P. Scavone, 1998. */
|
||||
/* Based in part on code by Perry */
|
||||
/* Cook (SGI), Paul Leonard (Linux), */
|
||||
/* the RoseGarden team (Linux), and */
|
||||
/* Bill Putnam (Win95/NT). */
|
||||
/* */
|
||||
/* At the moment, this object only */
|
||||
/* handles MIDI Input, though MIDI */
|
||||
/* Output code can go here when someone */
|
||||
/* decides they need it (and writes it). */
|
||||
/* */
|
||||
/* This object opens a MIDI Input device */
|
||||
/* and parses MIDI messages into a MIDI */
|
||||
/* buffer. Time stamp info is converted */
|
||||
/* to deltaTime. MIDI data is stored as */
|
||||
/* MY_FLOAT to conform with SKINI. */
|
||||
/******************************************/
|
||||
|
||||
#include "MIDIIO.h"
|
||||
|
||||
#define MIDI_BUFFER_SIZE 1024
|
||||
int writeOffset;
|
||||
int readOffset;
|
||||
|
||||
|
||||
#if defined(__SGI_REALTIME_)
|
||||
|
||||
/*************************************/
|
||||
/* __SGI_REALTIME_ */
|
||||
/*************************************/
|
||||
|
||||
#include <dmedia/midi.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <signal.h>
|
||||
|
||||
MDport inport;
|
||||
|
||||
MDevent *midiBuffer;
|
||||
|
||||
pid_t midi_input_pid;
|
||||
|
||||
void midiInputThread(void *)
|
||||
{
|
||||
MDevent newMessage;
|
||||
int status;
|
||||
|
||||
while (1) {
|
||||
mdReceive(inport, &newMessage, 1);
|
||||
status = (newMessage.msg[0] & MD_STATUSMASK);
|
||||
|
||||
// Ignore Active Sensing messages
|
||||
if (!((status & 0xff) == 0xfe || (status & 0xff) == 0xf8)) {
|
||||
midiBuffer[writeOffset] = newMessage;
|
||||
writeOffset++;
|
||||
|
||||
if( writeOffset >= MIDI_BUFFER_SIZE )
|
||||
writeOffset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MIDIIO :: MIDIIO()
|
||||
{
|
||||
int nports;
|
||||
|
||||
nports = mdInit();
|
||||
printf("%d MIDI devices available\n", nports);
|
||||
inport = mdOpenInPort(NULL);
|
||||
if (inport == NULL) {
|
||||
fprintf(stderr,"Cannot open MIDI device.\n");
|
||||
printf("Exiting MIDIIO Process.\n");
|
||||
exit(0);
|
||||
}
|
||||
mdSetStampMode(inport, MD_NOSTAMP);
|
||||
|
||||
// Set up the circular buffer for the Midi Input Messages
|
||||
midiBuffer = new MDevent[MIDI_BUFFER_SIZE];
|
||||
readOffset = 0;
|
||||
writeOffset = 0;
|
||||
|
||||
midi_input_pid = sproc(midiInputThread, PR_SALL);
|
||||
if (midi_input_pid == -1) {
|
||||
fprintf(stderr, "unable to create MIDI input thread...aborting.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
MIDIIO :: ~MIDIIO()
|
||||
{
|
||||
kill (midi_input_pid, SIGKILL);
|
||||
mdClosePort(inport);
|
||||
delete [] midiBuffer;
|
||||
}
|
||||
|
||||
int MIDIIO :: nextMessage()
|
||||
{
|
||||
int status;
|
||||
int byte1;
|
||||
int byte2;
|
||||
MDevent lastEvent;
|
||||
static unsigned long long lastTimeStamp = 0;
|
||||
|
||||
if ( readOffset == writeOffset ) return 0;
|
||||
|
||||
lastEvent = midiBuffer[readOffset];
|
||||
|
||||
readOffset++;
|
||||
if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0;
|
||||
|
||||
status = (lastEvent.msg[0] & MD_STATUSMASK);
|
||||
byte1 = lastEvent.msg[1];
|
||||
byte2 = lastEvent.msg[2];
|
||||
channel = (lastEvent.msg[0] & MD_CHANNELMASK);
|
||||
|
||||
if ((status == MD_PROGRAMCHANGE) ||
|
||||
(status == MD_CHANNELPRESSURE))
|
||||
{
|
||||
messageType = status;
|
||||
byteTwo = (float) byte1;
|
||||
deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001);
|
||||
lastTimeStamp = lastEvent.stamp;
|
||||
}
|
||||
else if ((status == MD_NOTEON) || (status == MD_NOTEOFF) ||
|
||||
(status == MD_CONTROLCHANGE) || (status == MD_POLYKEYPRESSURE))
|
||||
{
|
||||
messageType = status;
|
||||
byteTwo = (float) byte1;
|
||||
byteThree = (float) byte2;
|
||||
deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001);
|
||||
lastTimeStamp = lastEvent.stamp;
|
||||
}
|
||||
else if (status == MD_PITCHBENDCHANGE)
|
||||
{
|
||||
messageType = status;
|
||||
byteTwo = (float) byte1 * NORM_7;
|
||||
byteTwo += (float) byte2;
|
||||
deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001);
|
||||
lastTimeStamp = lastEvent.stamp;
|
||||
}
|
||||
else
|
||||
{
|
||||
messageType = -1;
|
||||
}
|
||||
|
||||
return messageType;
|
||||
}
|
||||
|
||||
|
||||
#elif defined(__USS_REALTIME_)
|
||||
|
||||
/*************************************/
|
||||
/* __USS_REALTIME_ */
|
||||
/*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include <pthread.h>
|
||||
|
||||
int _seqfd;
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
typedef struct {
|
||||
byte data[4];
|
||||
unsigned long time;
|
||||
} MIDIMESSAGE;
|
||||
|
||||
MIDIMESSAGE *midiBuffer;
|
||||
|
||||
/* System Messages */
|
||||
#define MIDI_SYSTEM_MSG ((byte)0xF0)
|
||||
#define MessageType(MSG) (byte)((MSG) & ((byte)0xF0))
|
||||
|
||||
#define SEQUENCER_PATH "/dev/sequencer"
|
||||
|
||||
/* MIDI time code at 100 ticks per second. */
|
||||
#define OSS_MIDI_CLOCK_RATE 100
|
||||
|
||||
pthread_t midi_input_thread;
|
||||
|
||||
void *midiInputThread(void *)
|
||||
{
|
||||
byte NumArgs = 0;
|
||||
byte ArgsLeft = 0;
|
||||
unsigned long lastTime = 0;
|
||||
unsigned long newTime = 0;
|
||||
byte InBytes[4];
|
||||
static MIDIMESSAGE newMessage;
|
||||
int n;
|
||||
|
||||
while (1) {
|
||||
if ((n = read(_seqfd, &InBytes, sizeof(InBytes))) == -1) {
|
||||
fprintf(stderr,"Error reading " SEQUENCER_PATH "\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
switch ( InBytes[0] )
|
||||
{
|
||||
case SEQ_WAIT:
|
||||
/* MIDI clock ticks ... the first MIDI message deltaTime is calculated
|
||||
* with respect to the start of the MIDI clock.
|
||||
*/
|
||||
newTime = ((InBytes[3]<<16)|(InBytes[2]<<8)| InBytes[1]);
|
||||
break;
|
||||
|
||||
case SEQ_ECHO:
|
||||
/* no echo events yet defined */
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"ECHO EVENT\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SEQ_MIDIPUTC:
|
||||
/* Determination of a full MIDI message from the input MIDI stream is based
|
||||
here on the observation that MIDI status bytes and subsequent data bytes
|
||||
are NOT returned in the same read() call. Rather, they are spread out
|
||||
over multiple read() returns, with only a single value per return. So,
|
||||
if we find a status byte, we then determine the number of expected
|
||||
operands and process that number of subsequent read()s to determine the
|
||||
complete MIDI message.
|
||||
*/
|
||||
if (InBytes[1] & 0x80) { /* Status Byte */
|
||||
if (MessageType(InBytes[1]) == MIDI_SYSTEM_MSG)
|
||||
{
|
||||
NumArgs = 0; /* no timing info */
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "SYSTEM MESSAGE\n");
|
||||
#endif
|
||||
}
|
||||
else if (MessageType(InBytes[1]) == MIDI_PGM_CHANGE ||
|
||||
MessageType(InBytes[1]) == MIDI_CHN_PRESSURE)
|
||||
{
|
||||
NumArgs = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
NumArgs = 2;
|
||||
}
|
||||
newMessage.data[0] = InBytes[1];
|
||||
ArgsLeft = NumArgs;
|
||||
newMessage.data[1] = 0;
|
||||
newMessage.data[2] = 0;
|
||||
}
|
||||
|
||||
if (ArgsLeft && !(InBytes[1] & 0x80)) { /* not a status byte */
|
||||
if (ArgsLeft == NumArgs)
|
||||
newMessage.data[1] = InBytes[1];
|
||||
else
|
||||
{
|
||||
newMessage.data[2] = InBytes[1];
|
||||
}
|
||||
|
||||
--ArgsLeft;
|
||||
|
||||
/* If MIDI message complete, then setup for running status mode
|
||||
(another event of the same type without status byte).
|
||||
*/
|
||||
if ( !ArgsLeft ) {
|
||||
if (MessageType(newMessage.data[0]) == (int) MIDI_PGM_CHANGE ||
|
||||
MessageType(newMessage.data[0]) == (int) MIDI_CHN_PRESSURE)
|
||||
{
|
||||
ArgsLeft = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ArgsLeft = 2;
|
||||
}
|
||||
newMessage.time = newTime - lastTime;
|
||||
lastTime = newTime;
|
||||
|
||||
// Put newMessage in the circular buffer
|
||||
midiBuffer[writeOffset] = newMessage;
|
||||
writeOffset++;
|
||||
|
||||
if( writeOffset >= MIDI_BUFFER_SIZE )
|
||||
writeOffset = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MIDIIO :: MIDIIO()
|
||||
{
|
||||
int err = 0;
|
||||
_seqfd = 0;
|
||||
|
||||
#ifdef NONBLOCKING_MIDI
|
||||
if((_seqfd = open(SEQUENCER_PATH, O_RDONLY+O_NONBLOCK, 0)) == -1) {
|
||||
#else
|
||||
if((_seqfd = open(SEQUENCER_PATH, O_RDONLY, 0)) == -1) {
|
||||
#endif
|
||||
fprintf(stderr,"Cannot open " SEQUENCER_PATH ". \n");
|
||||
printf("Exiting MIDIIO Process.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Set up the circular buffer for the Midi Input Messages
|
||||
midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE];
|
||||
readOffset = 0;
|
||||
writeOffset = 0;
|
||||
|
||||
err = pthread_create(&midi_input_thread, NULL, midiInputThread, NULL);
|
||||
if (err)
|
||||
{
|
||||
fprintf(stderr, "Unable to create MIDI input thread.\n");
|
||||
printf("Exiting MIDIIO Process.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
MIDIIO :: ~MIDIIO()
|
||||
{
|
||||
if (_seqfd != 0) close(_seqfd);
|
||||
delete [] midiBuffer;
|
||||
}
|
||||
|
||||
int MIDIIO::nextMessage()
|
||||
{
|
||||
MIDIMESSAGE lastEvent;
|
||||
unsigned long micros = 2000;
|
||||
|
||||
if ( readOffset == writeOffset ) return 0;
|
||||
|
||||
lastEvent = midiBuffer[readOffset];
|
||||
|
||||
readOffset++;
|
||||
if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0;
|
||||
|
||||
messageType = (int) (lastEvent.data[0] & 0xf0);
|
||||
channel = (int) (lastEvent.data[0] & 0x0f);
|
||||
byteTwo = (float) lastEvent.data[1];
|
||||
if (messageType == (int) MIDI_PITCH_BEND)
|
||||
byteTwo = (float) lastEvent.data[2] + (byteTwo * NORM_7);
|
||||
else
|
||||
byteThree = (float) lastEvent.data[2];
|
||||
deltaTime = (float) lastEvent.time / OSS_MIDI_CLOCK_RATE;
|
||||
|
||||
return messageType;
|
||||
}
|
||||
|
||||
|
||||
#elif (defined(__WINDS_REALTIME_) || defined(__WINMM_REALTIME_) )
|
||||
|
||||
/*************************************/
|
||||
/* __WIN_REALTIME_ */
|
||||
/*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "MIDIIO.h"
|
||||
|
||||
#define MIDI_NOTEON 0x90
|
||||
#define MIDI_NOTEOFF 0x80
|
||||
#define MIDI_POLYKEYPRESSURE 0xA0
|
||||
#define MIDI_CHANNELPRESSURE 0xD0
|
||||
#define MIDI_PROGRAMCHANGE 0xC0
|
||||
#define MIDI_CONTROLCHANGE 0xB0
|
||||
#define MIDI_PITCHBEND 0xE0
|
||||
|
||||
typedef struct {
|
||||
DWORD data;
|
||||
DWORD time;
|
||||
} MIDIMESSAGE;
|
||||
|
||||
MIDIMESSAGE *midiBuffer;
|
||||
|
||||
static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus,
|
||||
DWORD instancePtr, DWORD midiMessage, DWORD timestamp)
|
||||
{
|
||||
MIDIMESSAGE newMessage;
|
||||
|
||||
switch (inputStatus) {
|
||||
case MIM_OPEN:
|
||||
#ifdef TESTING_MIDI_IN
|
||||
printf("MIM_OPEN\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MIM_CLOSE:
|
||||
#ifdef TESTING_MIDI_IN
|
||||
printf("MIM_CLOSE\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MIM_DATA:
|
||||
#ifdef TESTING_MIDI_IN
|
||||
printf("MIM_DATA\n");
|
||||
#endif
|
||||
// Ignore Active Sensing messages
|
||||
if ((midiMessage & 0xff) == 0xfe || (midiMessage & 0xff) == 0xf8) {
|
||||
break;
|
||||
}
|
||||
newMessage.data = midiMessage;
|
||||
newMessage.time = timestamp;
|
||||
|
||||
// Put newMessage in the circular buffer
|
||||
midiBuffer[writeOffset] = newMessage;
|
||||
writeOffset++;
|
||||
|
||||
if( writeOffset >= MIDI_BUFFER_SIZE )
|
||||
writeOffset = 0;
|
||||
break;
|
||||
|
||||
case MIM_ERROR:
|
||||
fprintf(stderr,"Invalid MIDI message received!\n");
|
||||
#ifdef TESTING_MIDI_IN
|
||||
printf("MIM_ERROR\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MIM_LONGDATA:
|
||||
/* System exclusive buffer is returned */
|
||||
break;
|
||||
|
||||
case MIM_LONGERROR:
|
||||
#ifdef TESTING_MIDI_IN
|
||||
printf("MIM_LONGERROR\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HMIDIIN hMidiIn ; // Handle to Midi Output Device
|
||||
|
||||
MIDIIO :: MIDIIO()
|
||||
{
|
||||
MMRESULT result;
|
||||
UINT uDeviceID;
|
||||
MIDIINCAPS deviceCaps;
|
||||
UINT i;
|
||||
char inputString[128];
|
||||
|
||||
uDeviceID = midiInGetNumDevs();
|
||||
printf("%i MIDI Input Devices Available.\n",uDeviceID);
|
||||
if (uDeviceID == 0) {
|
||||
printf("Exiting MIDIIO Process.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for (i=0; i<uDeviceID; i++) {
|
||||
result = midiInGetDevCaps(i, &deviceCaps, sizeof(MIDIINCAPS));
|
||||
printf("MIDI Device %d is %s.\n", i, deviceCaps.szPname);
|
||||
}
|
||||
|
||||
if (uDeviceID > 1) {
|
||||
printf("\nType the MIDI Device to open: ");
|
||||
fgets(inputString, 128, stdin);
|
||||
uDeviceID = (UINT) atoi(inputString);
|
||||
}
|
||||
else uDeviceID -= 1;
|
||||
|
||||
// Open the port and return any errors
|
||||
result = midiInOpen(&hMidiIn, uDeviceID, (DWORD)&midiInputCallback, (DWORD)NULL, CALLBACK_FUNCTION);
|
||||
if (result != MMSYSERR_NOERROR) {
|
||||
fprintf(stderr,"Cannot open MIDI Input Device %d!\n", uDeviceID);
|
||||
printf("Exiting MIDIIO Process.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Set up the circular buffer for the Midi Input Messages
|
||||
midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE];
|
||||
readOffset = 0;
|
||||
writeOffset = 0;
|
||||
|
||||
midiInStart( hMidiIn );
|
||||
}
|
||||
|
||||
MIDIIO :: ~MIDIIO()
|
||||
{
|
||||
midiInReset( hMidiIn );
|
||||
midiInStop( hMidiIn );
|
||||
midiInClose( hMidiIn );
|
||||
delete [] midiBuffer;
|
||||
}
|
||||
|
||||
int MIDIIO :: nextMessage()
|
||||
{
|
||||
int status;
|
||||
int byte1;
|
||||
int byte2;
|
||||
MIDIMESSAGE lastEvent;
|
||||
static DWORD lastTime = 0;
|
||||
static DWORD newTime = 0;
|
||||
|
||||
if ( readOffset == writeOffset ) return 0;
|
||||
|
||||
lastEvent = midiBuffer[readOffset];
|
||||
|
||||
readOffset++;
|
||||
if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0;
|
||||
|
||||
status = (int) (lastEvent.data & 0xff);
|
||||
byte1 = (int) (lastEvent.data & 0xff00) >> 8;
|
||||
byte2 = (int) (lastEvent.data & 0xff0000) >> 16;
|
||||
channel = (int) (status & 0x0f);
|
||||
newTime = lastEvent.time;
|
||||
deltaTime = (float) (newTime - lastTime) * 0.001;
|
||||
lastTime = newTime;
|
||||
|
||||
if ((status == MIDI_PROGRAMCHANGE) ||
|
||||
(status == MIDI_CHANNELPRESSURE))
|
||||
{
|
||||
messageType = status;
|
||||
byteTwo = (float) byte1;
|
||||
}
|
||||
else if ((status == MIDI_NOTEON) || (status == MIDI_NOTEOFF) ||
|
||||
(status == MIDI_CONTROLCHANGE) || (status == MIDI_POLYKEYPRESSURE))
|
||||
{
|
||||
messageType = status;
|
||||
byteTwo = (float) byte1;
|
||||
byteThree = (float) byte2;
|
||||
}
|
||||
else if (status == MIDI_PITCHBEND)
|
||||
{
|
||||
messageType = status;
|
||||
byteTwo = (float) (byte1 * NORM_7);
|
||||
byteTwo += (float) byte2;
|
||||
}
|
||||
else
|
||||
{
|
||||
messageType = -1;
|
||||
}
|
||||
|
||||
return messageType;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void MIDIIO :: printMessage()
|
||||
{
|
||||
printf("type = %d, channel = %d, byte2 = %f, byte3 = %f\n",
|
||||
this->getType(), this->getChannel(), this->getByteTwo(),
|
||||
this->getByteThree());
|
||||
}
|
||||
|
||||
int MIDIIO :: getType()
|
||||
{
|
||||
return messageType;
|
||||
}
|
||||
|
||||
int MIDIIO :: getChannel()
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
|
||||
MY_FLOAT MIDIIO :: getByteTwo()
|
||||
{
|
||||
return byteTwo;
|
||||
}
|
||||
|
||||
MY_FLOAT MIDIIO :: getByteThree()
|
||||
{
|
||||
return byteThree;
|
||||
}
|
||||
|
||||
MY_FLOAT MIDIIO :: getDeltaTime()
|
||||
{
|
||||
return deltaTime;
|
||||
}
|
||||
56
MIDIIO.h
Normal file
56
MIDIIO.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/******************************************/
|
||||
/* MIDIIO.h */
|
||||
/* Realtime MIDI I/O Object for STK, */
|
||||
/* by Gary P. Scavone, 1998. */
|
||||
/* Based in part on code by Perry */
|
||||
/* Cook (SGI), Paul Leonard (Linux), */
|
||||
/* the RoseGarden team (Linux), and */
|
||||
/* Bill Putnam (Win95/NT). */
|
||||
/* */
|
||||
/* At the moment, this object only */
|
||||
/* handles MIDI Input, though MIDI */
|
||||
/* Output code can go here when someone */
|
||||
/* decides they need it (and writes it). */
|
||||
/* */
|
||||
/* This object opens a MIDI Input device */
|
||||
/* and parses MIDI data. Time stamp */
|
||||
/* info is converted to deltaTime. */
|
||||
/* MIDI data is stored as MY_FLOAT to */
|
||||
/* conform with SKINI. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__MIDIIO_h)
|
||||
#define __MIDIIO_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class MIDIIO : public Object
|
||||
{
|
||||
protected:
|
||||
int messageType;
|
||||
int channel;
|
||||
float byteTwo;
|
||||
float byteThree;
|
||||
MY_FLOAT deltaTime;
|
||||
public:
|
||||
MIDIIO();
|
||||
~MIDIIO();
|
||||
void printMessage();
|
||||
int nextMessage();
|
||||
int getType();
|
||||
int getChannel();
|
||||
MY_FLOAT getByteTwo();
|
||||
MY_FLOAT getByteThree();
|
||||
MY_FLOAT getDeltaTime();
|
||||
};
|
||||
|
||||
#if (defined(__WINDS_REALTIME_) || defined(__WINMM_REALTIME_) )
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus,
|
||||
DWORD instancePtr, DWORD midiMessage, DWORD timestamp);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
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
|
||||
275
Makefile
275
Makefile
@@ -1,244 +1,65 @@
|
||||
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 \
|
||||
# STK98 Makefile - Global version for Unix systems which have GNU
|
||||
# Makefile utilities installed. If this Makefile does not work on
|
||||
# your system, try using the platform specific Makefiles (.sgi,
|
||||
# .next, and .linux).
|
||||
|
||||
OS = $(shell uname)
|
||||
|
||||
O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \
|
||||
RawWave.o RawWvIn.o RawLoop.o \
|
||||
Modulatr.o Filter.o OneZero.o \
|
||||
OnePole.o TwoZero.o TwoPole.o DCBlock.o \
|
||||
BiQuad.o DLineA.o DLineL.o DLineN.o VoicMang.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 SKINI11.o Simple.o \
|
||||
SingWave.o VoicForm.o FMVoices.o swapstuf.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
|
||||
Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Shakers.o \
|
||||
Plucked.o Mandolin.o Clarinet.o Flute.o Moog1.o \
|
||||
Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \
|
||||
HeavyMtl.o PercFlut.o BeeThree.o DrumSynt.o \
|
||||
\
|
||||
WvOut.o SndWvOut.o WavWvOut.o MatWvOut.o \
|
||||
Reverb.o PRCRev.o JCRev.o NRev.o
|
||||
|
||||
RM = /bin/rm
|
||||
|
||||
# This is for NeXT
|
||||
# CC = cc -O
|
||||
# INSTR = testMono testMult DrumSynt textVoic
|
||||
ifeq ($(OS),NEXTSTEP) # These are for NeXT
|
||||
CC = cc -arch m68k -arch i386 -Wall
|
||||
INSTR = syntmono
|
||||
endif
|
||||
|
||||
ifeq ($(OS),IRIX) # These are for SGI
|
||||
INSTR = MD2SKINI syntmono
|
||||
CC = CC -O # -g -fullwarn -D__SGI_CC__
|
||||
O_FILES += RTWvOut.o RTSoundIO.o MIDIIO.o
|
||||
LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm
|
||||
endif
|
||||
|
||||
# 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
|
||||
ifeq ($(OS),Linux) # These are for Linux
|
||||
INSTR = syntmono MD2SKINI
|
||||
CC = gcc -O3 # -g -pg -O3
|
||||
O_FILES += RTWvOut.o RTSoundIO.o MIDIIO.o
|
||||
LIBRARY = -lpthread -lm
|
||||
endif
|
||||
|
||||
# .cpp.o:
|
||||
# $(CC) -c $*.cpp
|
||||
.SUFFIXES: .cpp
|
||||
.cpp.o: Object.h
|
||||
$(CC) -c $*.cpp
|
||||
|
||||
all: $(INSTR)
|
||||
|
||||
testTextIn: $(LIBRARY) testTextIn.cpp $(O_FILES) MIDIInpt.o
|
||||
$(CC) $(MEDIALINK) -o testTextIn testTextIn.cpp $(O_FILES) $(LIBRARY)
|
||||
syntmono: syntmono.cpp $(O_FILES)
|
||||
$(CC) $(INCLUDE) -o syntmono syntmono.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
|
||||
MD2SKINI: MD2SKINI.cpp $(O_FILES)
|
||||
$(CC) -o MD2SKINI MD2SKINI.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
clean :
|
||||
rm $(INSTR)
|
||||
rm *.o
|
||||
rm $(INSTR)
|
||||
|
||||
cleanIns :
|
||||
rm $(INSTR)
|
||||
|
||||
47
Makefile.NeXT
Normal file
47
Makefile.NeXT
Normal file
@@ -0,0 +1,47 @@
|
||||
# STK98 Makefile - NeXTStep solo version
|
||||
|
||||
O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \
|
||||
RawWave.o RawWvIn.o RawLoop.o \
|
||||
Modulatr.o Filter.o OneZero.o \
|
||||
OnePole.o TwoZero.o TwoPole.o DCBlock.o \
|
||||
BiQuad.o DLineA.o DLineL.o DLineN.o VoicMang.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 SKINI11.o Simple.o \
|
||||
SingWave.o VoicForm.o FMVoices.o swapstuf.o \
|
||||
\
|
||||
Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Shakers.o \
|
||||
Plucked.o Mandolin.o Clarinet.o Flute.o Moog1.o \
|
||||
Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \
|
||||
HeavyMtl.o PercFlut.o BeeThree.o DrumSynt.o \
|
||||
\
|
||||
WvOut.o SndWvOut.o WavWvOut.o MatWvOut.o \
|
||||
Reverb.o PRCRev.o JCRev.o NRev.o
|
||||
|
||||
RM = /bin/rm
|
||||
|
||||
CC = cc -arch m68k -arch i386 -Wall
|
||||
INSTR = syntmono
|
||||
|
||||
.SUFFIXES: .cpp
|
||||
.cpp.o: Object.h
|
||||
$(CC) -c $*.cpp
|
||||
|
||||
all: $(INSTR)
|
||||
|
||||
syntmono: syntmono.cpp $(O_FILES)
|
||||
$(CC) $(INCLUDE) -o syntmono syntmono.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
MD2SKINI: MD2SKINI.cpp $(O_FILES)
|
||||
$(CC) -o MD2SKINI MD2SKINI.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
clean :
|
||||
rm *.o
|
||||
rm $(INSTR)
|
||||
|
||||
cleanIns :
|
||||
rm $(INSTR)
|
||||
|
||||
strip :
|
||||
strip $(INSTR)
|
||||
68
Makefile.all
Normal file
68
Makefile.all
Normal file
@@ -0,0 +1,68 @@
|
||||
# STK98 Makefile - Global version for Unix systems which have GNU
|
||||
# Makefile utilities installed. If this Makefile does not work on
|
||||
# your system, try using the platform specific Makefiles (.sgi,
|
||||
# .next, and .linux).
|
||||
|
||||
OS = $(shell uname)
|
||||
|
||||
O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \
|
||||
RawWave.o RawWvIn.o RawLoop.o \
|
||||
Modulatr.o Filter.o OneZero.o \
|
||||
OnePole.o TwoZero.o TwoPole.o DCBlock.o \
|
||||
BiQuad.o DLineA.o DLineL.o DLineN.o VoicMang.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 SKINI11.o Simple.o \
|
||||
SingWave.o VoicForm.o FMVoices.o swapstuf.o \
|
||||
\
|
||||
Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Shakers.o \
|
||||
Plucked.o Mandolin.o Clarinet.o Flute.o Moog1.o \
|
||||
Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \
|
||||
HeavyMtl.o PercFlut.o BeeThree.o DrumSynt.o \
|
||||
\
|
||||
WvOut.o SndWvOut.o WavWvOut.o MatWvOut.o \
|
||||
Reverb.o PRCRev.o JCRev.o NRev.o
|
||||
|
||||
RM = /bin/rm
|
||||
|
||||
ifeq ($(OS),NEXTSTEP) # These are for NeXT
|
||||
CC = cc -arch m68k -arch i386 -Wall
|
||||
INSTR = syntmono
|
||||
endif
|
||||
|
||||
ifeq ($(OS),IRIX) # These are for SGI
|
||||
INSTR = MD2SKINI syntmono
|
||||
CC = CC -O # -g -fullwarn -D__SGI_CC__
|
||||
O_FILES += RTWvOut.o RTSoundIO.o MIDIIO.o
|
||||
LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm
|
||||
endif
|
||||
|
||||
ifeq ($(OS),Linux) # These are for Linux
|
||||
INSTR = syntmono MD2SKINI
|
||||
CC = gcc -O3 # -g -pg -O3
|
||||
O_FILES += RTWvOut.o RTSoundIO.o MIDIIO.o
|
||||
LIBRARY = -lpthread -lm
|
||||
endif
|
||||
|
||||
.SUFFIXES: .cpp
|
||||
.cpp.o: Object.h
|
||||
$(CC) -c $*.cpp
|
||||
|
||||
all: $(INSTR)
|
||||
|
||||
syntmono: syntmono.cpp $(O_FILES)
|
||||
$(CC) $(INCLUDE) -o syntmono syntmono.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
MD2SKINI: MD2SKINI.cpp $(O_FILES)
|
||||
$(CC) -o MD2SKINI MD2SKINI.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
clean :
|
||||
rm *.o
|
||||
rm $(INSTR)
|
||||
|
||||
cleanIns :
|
||||
rm $(INSTR)
|
||||
|
||||
strip :
|
||||
strip $(INSTR)
|
||||
49
Makefile.linux
Normal file
49
Makefile.linux
Normal file
@@ -0,0 +1,49 @@
|
||||
# STK98 Makefile - Linux solo version
|
||||
|
||||
O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \
|
||||
RawWave.o RawWvIn.o RawLoop.o \
|
||||
Modulatr.o Filter.o OneZero.o \
|
||||
OnePole.o TwoZero.o TwoPole.o DCBlock.o \
|
||||
BiQuad.o DLineA.o DLineL.o DLineN.o VoicMang.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 SKINI11.o Simple.o \
|
||||
SingWave.o VoicForm.o FMVoices.o swapstuf.o \
|
||||
\
|
||||
Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Shakers.o \
|
||||
Plucked.o Mandolin.o Clarinet.o Flute.o Moog1.o \
|
||||
Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \
|
||||
HeavyMtl.o PercFlut.o BeeThree.o DrumSynt.o \
|
||||
\
|
||||
WvOut.o SndWvOut.o WavWvOut.o MatWvOut.o \
|
||||
Reverb.o PRCRev.o JCRev.o NRev.o \
|
||||
RTWvOut.o RTSoundIO.o MIDIIO.o
|
||||
|
||||
RM = /bin/rm
|
||||
|
||||
INSTR = syntmono MD2SKINI
|
||||
CC = gcc -O3 # -g -pg -O3
|
||||
LIBRARY = -lpthread -lm
|
||||
|
||||
.SUFFIXES: .cpp
|
||||
.cpp.o: Object.h
|
||||
$(CC) -c $*.cpp
|
||||
|
||||
all: $(INSTR)
|
||||
|
||||
syntmono: syntmono.cpp $(O_FILES)
|
||||
$(CC) $(INCLUDE) -o syntmono syntmono.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
MD2SKINI: MD2SKINI.cpp $(O_FILES)
|
||||
$(CC) -o MD2SKINI MD2SKINI.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
clean :
|
||||
rm *.o
|
||||
rm $(INSTR)
|
||||
|
||||
cleanIns :
|
||||
rm $(INSTR)
|
||||
|
||||
strip :
|
||||
strip $(INSTR)
|
||||
49
Makefile.sgi
Normal file
49
Makefile.sgi
Normal file
@@ -0,0 +1,49 @@
|
||||
# STK98 Makefile - SGI solo version
|
||||
|
||||
O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \
|
||||
RawWave.o RawWvIn.o RawLoop.o \
|
||||
Modulatr.o Filter.o OneZero.o \
|
||||
OnePole.o TwoZero.o TwoPole.o DCBlock.o \
|
||||
BiQuad.o DLineA.o DLineL.o DLineN.o VoicMang.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 SKINI11.o Simple.o \
|
||||
SingWave.o VoicForm.o FMVoices.o swapstuf.o \
|
||||
\
|
||||
Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Shakers.o \
|
||||
Plucked.o Mandolin.o Clarinet.o Flute.o Moog1.o \
|
||||
Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \
|
||||
HeavyMtl.o PercFlut.o BeeThree.o DrumSynt.o \
|
||||
\
|
||||
WvOut.o SndWvOut.o WavWvOut.o MatWvOut.o \
|
||||
Reverb.o PRCRev.o JCRev.o NRev.o \
|
||||
RTWvOut.o RTSoundIO.o MIDIIO.o
|
||||
|
||||
RM = /bin/rm
|
||||
|
||||
INSTR = MD2SKINI syntmono
|
||||
CC = CC -O # -g -fullwarn -D__SGI_CC__
|
||||
LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm
|
||||
|
||||
.SUFFIXES: .cpp
|
||||
.cpp.o: Object.h
|
||||
$(CC) -c $*.cpp
|
||||
|
||||
all: $(INSTR)
|
||||
|
||||
syntmono: syntmono.cpp $(O_FILES)
|
||||
$(CC) $(INCLUDE) -o syntmono syntmono.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
MD2SKINI: MD2SKINI.cpp $(O_FILES)
|
||||
$(CC) -o MD2SKINI MD2SKINI.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
clean :
|
||||
rm *.o
|
||||
rm $(INSTR)
|
||||
|
||||
cleanIns :
|
||||
rm $(INSTR)
|
||||
|
||||
strip :
|
||||
strip $(INSTR)
|
||||
74
Mandolin.cpp
74
Mandolin.cpp
@@ -17,24 +17,46 @@
|
||||
/********************************************/
|
||||
|
||||
#include "Mandolin.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
Mandolin :: Mandolin(MY_FLOAT lowestFreq) : Plucked2(lowestFreq)
|
||||
{
|
||||
soundfile = new RawWave("rawwaves/mandpluk.raw");
|
||||
soundfile->normalize(0.05); /* Empirical hack here */
|
||||
soundfile->setLooping(0);
|
||||
int i;
|
||||
|
||||
soundfile[0] = new RawWave("rawwaves/mand1.raw");
|
||||
soundfile[1] = new RawWave("rawwaves/mand2.raw");
|
||||
soundfile[2] = new RawWave("rawwaves/mand3.raw");
|
||||
soundfile[3] = new RawWave("rawwaves/mand4.raw");
|
||||
soundfile[4] = new RawWave("rawwaves/mand5.raw");
|
||||
soundfile[5] = new RawWave("rawwaves/mand6.raw");
|
||||
soundfile[6] = new RawWave("rawwaves/mand7.raw");
|
||||
soundfile[7] = new RawWave("rawwaves/mand8.raw");
|
||||
soundfile[8] = new RawWave("rawwaves/mand9.raw");
|
||||
soundfile[9] = new RawWave("rawwaves/mand10.raw");
|
||||
soundfile[10] = new RawWave("rawwaves/mand11.raw");
|
||||
soundfile[11] = new RawWave("rawwaves/mand12.raw");
|
||||
for (i=0;i<12;i++) {
|
||||
// soundfile[i]->normalize((MY_FLOAT) 0.1); /* Empirical hack here */
|
||||
soundfile[i]->setLooping(0);
|
||||
}
|
||||
directBody = 1.0;
|
||||
mic = 0;
|
||||
dampTime = 0;
|
||||
waveDone = 1;
|
||||
}
|
||||
|
||||
Mandolin :: ~Mandolin()
|
||||
{
|
||||
}
|
||||
|
||||
void Mandolin :: pluck(MY_FLOAT amplitude)
|
||||
{ /* this function gets interesting here, */
|
||||
soundfile->reset(); /* because pluck may be longer than */
|
||||
soundfile[mic]->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 */
|
||||
(MY_FLOAT) 0.5 * pluckPos * lastLength); /* Set Pick Position */
|
||||
/* which puts zeroes at pos*length */
|
||||
dampTime = (long) lastLength; /* See tick method below */
|
||||
waveDone = 0;
|
||||
@@ -57,15 +79,18 @@ void Mandolin :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
|
||||
void Mandolin :: setBodySize(MY_FLOAT size)
|
||||
{
|
||||
soundfile->setRate(size);
|
||||
int i;
|
||||
for (i=0;i<12;i++) {
|
||||
soundfile[i]->setRate(size);
|
||||
}
|
||||
}
|
||||
|
||||
MY_FLOAT Mandolin :: tick()
|
||||
{
|
||||
MY_FLOAT temp = 0;
|
||||
MY_FLOAT temp = (MY_FLOAT) 0;
|
||||
if (!waveDone) {
|
||||
waveDone = soundfile->informTick(); /* as long as it goes . . . */
|
||||
temp = soundfile->lastOut() * pluckAmp; /* scaled pluck excitation */
|
||||
waveDone = soundfile[mic]->informTick(); /* as long as it goes . . . */
|
||||
temp = soundfile[mic]->lastOut() * pluckAmp; /* scaled pluck excitation */
|
||||
temp = temp - combDelay->tick(temp); /* with comb filtering */
|
||||
}
|
||||
if (dampTime>=0) { /* Damping hack to help avoid */
|
||||
@@ -73,11 +98,11 @@ MY_FLOAT Mandolin :: tick()
|
||||
lastOutput = delayLine->tick( /* Calculate 1st delay */
|
||||
filter->tick( /* filterered reflection */
|
||||
temp + /* plus pluck excitation */
|
||||
(delayLine->lastOut() * 0.7)));
|
||||
(delayLine->lastOut() * (MY_FLOAT) 0.7)));
|
||||
lastOutput += delayLine2->tick( /* and 2nd delay */
|
||||
filter2->tick( /* just like the 1st */
|
||||
temp +
|
||||
(delayLine2->lastOut() * 0.7))); /* that's the whole thing!! */
|
||||
(delayLine2->lastOut() * (MY_FLOAT) 0.7))); /* that's the whole thing!! */
|
||||
}
|
||||
else { /* No damping hack after 1 period */
|
||||
lastOutput = delayLine->tick( /* Calculate 1st delay */
|
||||
@@ -91,7 +116,7 @@ MY_FLOAT Mandolin :: tick()
|
||||
(delayLine2->lastOut()
|
||||
* loopGain)));
|
||||
}
|
||||
lastOutput *= 2.0;
|
||||
lastOutput *= (MY_FLOAT) 0.3 / 32768.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
@@ -100,17 +125,20 @@ 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);
|
||||
if (number == __SK_BodySize_)
|
||||
this->setBodySize(value * (MY_FLOAT) NORM_7 * (MY_FLOAT) 2.0);
|
||||
else if (number == __SK_PickPosition_)
|
||||
this->setPluckPos(value * (MY_FLOAT) NORM_7);
|
||||
else if (number == __SK_StringDamping_)
|
||||
this->setBaseLoopGain((MY_FLOAT) 0.97 + (value * (MY_FLOAT) NORM_7 * (MY_FLOAT) 0.03));
|
||||
else if (number == __SK_StringDetune_)
|
||||
this->setDetune((MY_FLOAT) 1.0 - (value * (MY_FLOAT) NORM_7 * (MY_FLOAT) 0.1));
|
||||
else if (number == __SK_AfterTouch_)
|
||||
this->pluck(value * (MY_FLOAT) NORM_7);
|
||||
else if (number == 411) {
|
||||
mic = (int) value % 12;
|
||||
}
|
||||
else {
|
||||
printf("Mandolin : Undefined Control Number!!\n");
|
||||
printf("Mandolin : Undefined Control Number!! %i\n",number);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,14 @@
|
||||
class Mandolin : public Plucked2
|
||||
{
|
||||
protected:
|
||||
RawWave *soundfile;
|
||||
RawWave *soundfile[12];
|
||||
MY_FLOAT directBody;
|
||||
int mic;
|
||||
long dampTime;
|
||||
int waveDone;
|
||||
public:
|
||||
Mandolin(MY_FLOAT lowestFreq);
|
||||
virtual ~Mandolin();
|
||||
void pluck(MY_FLOAT amplitude);
|
||||
void pluck(MY_FLOAT amplitude,MY_FLOAT position);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
|
||||
52
Marimba.cpp
52
Marimba.cpp
@@ -9,33 +9,35 @@
|
||||
/*******************************************/
|
||||
|
||||
#include "Marimba.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
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;
|
||||
wave->setRate((MY_FLOAT) 0.5); /* normal stick */
|
||||
this->setRatioAndReson(0, (MY_FLOAT) 1.00,(MY_FLOAT) 0.9996); /* Set all 132.0 */
|
||||
this->setRatioAndReson(1, (MY_FLOAT) 3.99,(MY_FLOAT) 0.9994); /* of our 523.0 */
|
||||
this->setRatioAndReson(2,(MY_FLOAT) 10.65,(MY_FLOAT) 0.9994); /* default 1405.0 */
|
||||
this->setRatioAndReson(3,-(MY_FLOAT) 2443.0,(MY_FLOAT) 0.999); /* resonances 2443.0 */
|
||||
this->setFiltGain(0,(MY_FLOAT) 0.04); /* and */
|
||||
this->setFiltGain(1,(MY_FLOAT) 0.01); /* gains */
|
||||
this->setFiltGain(2,(MY_FLOAT) 0.01); /* for each */
|
||||
this->setFiltGain(3,(MY_FLOAT) 0.008); /* resonance */
|
||||
directGain = (MY_FLOAT) 0.1;
|
||||
multiStrike = 0;
|
||||
}
|
||||
|
||||
Marimba :: ~Marimba()
|
||||
{
|
||||
delete wave;
|
||||
}
|
||||
|
||||
void Marimba :: setStickHardness(MY_FLOAT hardness)
|
||||
{
|
||||
stickHardness = hardness;
|
||||
wave->setRate(0.25 * pow(4.0,stickHardness));
|
||||
masterGain = 0.1 + (1.8 * stickHardness);
|
||||
wave->setRate((MY_FLOAT) (0.25 * (MY_FLOAT) pow(4.0,stickHardness)));
|
||||
masterGain = (MY_FLOAT) 0.1 + ((MY_FLOAT) 1.8 * stickHardness);
|
||||
}
|
||||
|
||||
void Marimba :: setStrikePosition(MY_FLOAT position)
|
||||
@@ -43,12 +45,12 @@ 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. */
|
||||
temp = (MY_FLOAT) sin(temp2);
|
||||
this->setFiltGain(0,(MY_FLOAT) 0.12 * temp); /* 1st mode function of pos. */
|
||||
temp = (MY_FLOAT) sin(0.05 + (3.9 * temp2));
|
||||
this->setFiltGain(1,(MY_FLOAT) -0.03 * temp); /* 2nd mode function of pos. */
|
||||
temp = (MY_FLOAT) sin(-0.05 + (11 * temp2));
|
||||
this->setFiltGain(2,(MY_FLOAT) 0.11 * temp); /* 3rd mode function of pos. */
|
||||
}
|
||||
|
||||
void Marimba :: setModulationSpeed(MY_FLOAT mSpeed)
|
||||
@@ -63,7 +65,7 @@ void Marimba :: setModulationDepth(MY_FLOAT mDepth)
|
||||
void Marimba :: strike(MY_FLOAT amplitude)
|
||||
{
|
||||
int temp;
|
||||
temp = random() >> 26;
|
||||
temp = rand() >> 10;
|
||||
if (temp < 2) {
|
||||
multiStrike = 1;
|
||||
#if defined(_debug_)
|
||||
@@ -85,15 +87,15 @@ 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)
|
||||
if (number == __SK_StickHardness_)
|
||||
this->setStickHardness(value * NORM_7);
|
||||
else if (number == MIDI_control2)
|
||||
else if (number == __SK_StrikePosition_)
|
||||
this->setStrikePosition(value * NORM_7);
|
||||
else if (number == MIDI_control3)
|
||||
vibr->setFreq((value * NORM_7 * 12.0));
|
||||
else if (number == MIDI_mod_wheel)
|
||||
else if (number == __SK_ModFrequency_)
|
||||
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
|
||||
else if (number == __SK_ModWheel_)
|
||||
vibrGain = (value * NORM_7);
|
||||
else if (number == MIDI_after_touch)
|
||||
else if (number == __SK_AfterTouch_Cont_)
|
||||
this->strike(value * NORM_7);
|
||||
else {
|
||||
printf("Marimba : Undefined Control Number!!\n");
|
||||
|
||||
214
MatWvOut.cpp
Normal file
214
MatWvOut.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
/*******************************************/
|
||||
/* Matlab MAT File Output Class, */
|
||||
/* by Gary P. Scavone, 1998. */
|
||||
/* This object creates a Matlab MAT-file */
|
||||
/* structure and fills it with buffers of */
|
||||
/* samples (doubles). */
|
||||
/* */
|
||||
/* The Matlab MAT-file format is not */
|
||||
/* available to the general public. I */
|
||||
/* spent several days reverse-engineering */
|
||||
/* the file format to create this class. */
|
||||
/* I couldn't figure out what a few of */
|
||||
/* the header fields correspond to, but */
|
||||
/* for the purposes of STK, this */
|
||||
/* shouldn't create any problems. */
|
||||
/*******************************************/
|
||||
|
||||
#include "MatWvOut.h"
|
||||
|
||||
/******** Matlab Matfile Header Struct *******/
|
||||
struct matheaderform {
|
||||
char heading[124];
|
||||
short a[2];
|
||||
long b[10];
|
||||
/* There's more, but it's of variable length */
|
||||
};
|
||||
|
||||
FILE *openMatFile(int chans,char *fileName) {
|
||||
struct matheaderform hdr;
|
||||
FILE *fd;
|
||||
char tempName[128];
|
||||
int i, namelen;
|
||||
long longtmp, headsize;
|
||||
|
||||
strcpy(hdr.heading,"MATLAB 5.0 MAT-file, Generated by STK98. This file format was hacked by Gary P. Scavone, CCRMA, Stanford University, 1998.");
|
||||
|
||||
for (i=strlen(hdr.heading);i<124;i++) hdr.heading[i] = ' ';
|
||||
|
||||
hdr.a[0] = (short) 256;
|
||||
hdr.a[1] = (short) 'M';
|
||||
hdr.a[1] <<= 8;
|
||||
hdr.a[1] += 'I';
|
||||
hdr.b[0] = (long) 14;
|
||||
hdr.b[1] = (long) 0; /* Size of file after this point to end (in bytes) */
|
||||
hdr.b[2] = (long) 6;
|
||||
hdr.b[3] = (long) 8;
|
||||
hdr.b[4] = (long) 6;
|
||||
hdr.b[5] = (long) 0;
|
||||
hdr.b[6] = (long) 5;
|
||||
hdr.b[7] = (long) 8;
|
||||
hdr.b[8] = (long) chans; /* This is the number of rows */
|
||||
hdr.b[9] = (long) 0; /* This is the number of columns */
|
||||
|
||||
strcpy(tempName,fileName);
|
||||
strcat(tempName,".mat");
|
||||
|
||||
fd = fopen(tempName,"w+b");
|
||||
if (!fd) {
|
||||
printf("Couldn't create matfile %s !!!!!!!!\n",fileName);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
printf("Creating matfile %s.\n", tempName);
|
||||
fwrite(&hdr,sizeof(char),168,fd); /* Write the fixed portion of the header */
|
||||
|
||||
/* The next 4 bytes can be viewed as two shorts, but they are byteswapped
|
||||
as a long. The first short value seems to always be one; the second
|
||||
short will be the length of the variable name IF IT IS <= 4; if the
|
||||
variable name length is >4, this short is zero and the length is put
|
||||
in the next 4 bytes. The variable name length is limited to 31
|
||||
characters (32 with a '\n'). The actual variable name then follows.
|
||||
The variable name is "zero-padded" out to the following minimum
|
||||
lengths (in bits): 4, 8, 16, 24, 32.
|
||||
*/
|
||||
namelen = strlen(fileName);
|
||||
if (namelen > 31) { /* Check length of variable name (file name) */
|
||||
fprintf(stderr, "File name too long ... should be 31 characters or less.\n");
|
||||
fclose(fd);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (namelen > 4) {
|
||||
longtmp = 1;
|
||||
fwrite(&longtmp,sizeof(long),1,fd);
|
||||
fwrite(&namelen,sizeof(long),1,fd);
|
||||
headsize = 44 + namelen;
|
||||
} else {
|
||||
longtmp = namelen;
|
||||
longtmp <<= 16;
|
||||
longtmp += 1;
|
||||
fwrite(&longtmp,sizeof(long),1,fd);
|
||||
headsize = 40 + namelen;
|
||||
}
|
||||
|
||||
fwrite(fileName,sizeof(char),namelen,fd); /* Write the variable (file) name */
|
||||
if (namelen < 5)
|
||||
longtmp = 4 - namelen;
|
||||
else if (namelen < 9)
|
||||
longtmp = 8 - namelen;
|
||||
else if (namelen < 17)
|
||||
longtmp = 16 - namelen;
|
||||
else if (namelen < 25)
|
||||
longtmp = 24 - namelen;
|
||||
else longtmp = 32 - namelen;
|
||||
|
||||
headsize += longtmp + 8; /* Add length (8) of following bytes */
|
||||
fseek(fd,longtmp,SEEK_CUR);
|
||||
|
||||
longtmp = 9;
|
||||
fwrite(&longtmp,sizeof(long),1,fd);
|
||||
longtmp = 0; /* Size of data in bytes (8 per sample) */
|
||||
fwrite(&longtmp,sizeof(long),1,fd);
|
||||
|
||||
fseek(fd,132,SEEK_SET);
|
||||
fwrite(&headsize,sizeof(long),1,fd); /* Write header size ... will update at end */
|
||||
fseek(fd,0,SEEK_END);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
MatWvOut :: MatWvOut(char *fileName)
|
||||
{
|
||||
chans = 1;
|
||||
pan = 0.5;
|
||||
fd = openMatFile(chans,fileName);
|
||||
counter = 0;
|
||||
totalCount = 0;
|
||||
}
|
||||
|
||||
MatWvOut :: MatWvOut(int channels, char *fileName)
|
||||
{
|
||||
chans = channels;
|
||||
pan = 0.5;
|
||||
fd = openMatFile(chans,fileName);
|
||||
counter = 0;
|
||||
totalCount = 0;
|
||||
}
|
||||
|
||||
MatWvOut :: ~MatWvOut()
|
||||
{
|
||||
double temp;
|
||||
long headsize, temp1;
|
||||
|
||||
fwrite(data,sizeof(double),counter,fd);
|
||||
temp = (double) totalCount * ONE_OVER_SRATE;
|
||||
printf("%f Seconds Computed\n",temp);
|
||||
fseek(fd,164,SEEK_SET);
|
||||
fwrite(&totalCount,sizeof(long),1,fd); /* Write number of columns */
|
||||
fseek(fd,132,SEEK_SET);
|
||||
fread(&headsize,sizeof(long),1,fd);
|
||||
temp1 = headsize;
|
||||
headsize += (long) (totalCount * 8 * 2);
|
||||
fseek(fd,132,SEEK_SET);
|
||||
fwrite(&headsize,sizeof(long),1,fd); /* Write file size (minus some header info) */
|
||||
fseek(fd,temp1+128,SEEK_SET);
|
||||
temp1 = totalCount * 8 * 2;
|
||||
fwrite(&temp1,sizeof(long),1,fd); /* Write data size (in bytes) */
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
long MatWvOut :: getCounter()
|
||||
{
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
MY_FLOAT MatWvOut :: getTime()
|
||||
{
|
||||
return (MY_FLOAT) totalCount * ONE_OVER_SRATE;
|
||||
}
|
||||
|
||||
void MatWvOut :: tick(MY_FLOAT sample)
|
||||
{
|
||||
if (chans==1) {
|
||||
data[counter++] = (double) (sample);
|
||||
}
|
||||
else {
|
||||
data[counter++] = (double) (sample * (1.0 - pan));
|
||||
data[counter++] = (double) (sample * pan);
|
||||
}
|
||||
totalCount += 1;
|
||||
if (counter == MAT_BUFFER_SIZE) {
|
||||
fwrite(data,sizeof(double),MAT_BUFFER_SIZE,fd);
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MatWvOut :: tick(MY_FLOAT lsamp, MY_FLOAT rsamp)
|
||||
{
|
||||
if (chans==1) {
|
||||
data[counter++] = (double) (lsamp + rsamp);
|
||||
}
|
||||
else {
|
||||
data[counter++] = (double) (lsamp);
|
||||
data[counter++] = (double) (rsamp);
|
||||
}
|
||||
totalCount += 1;
|
||||
if (counter == MAT_BUFFER_SIZE) {
|
||||
fwrite(data,sizeof(double),MAT_BUFFER_SIZE,fd);
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MatWvOut :: setMonoPan(MY_FLOAT aPan)
|
||||
{
|
||||
pan = aPan;
|
||||
if (aPan < 0.0) {
|
||||
pan = 0.0;
|
||||
printf("Pan < 0.0, correcting to 0.0\n");
|
||||
}
|
||||
if (aPan > 1.0) {
|
||||
pan = 1.0;
|
||||
printf("Pan > 1.0, correcting to 1.0\n");
|
||||
}
|
||||
}
|
||||
46
MatWvOut.h
Normal file
46
MatWvOut.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*******************************************/
|
||||
/* Matlab MAT File Output Class, */
|
||||
/* by Gary P. Scavone, 1998. */
|
||||
/* This object creates a Matlab MAT-file */
|
||||
/* structure and fills it with buffers of */
|
||||
/* samples (doubles). */
|
||||
/* */
|
||||
/* The Matlab MAT-file format is not */
|
||||
/* available to the general public. I */
|
||||
/* spent several days reverse-engineering */
|
||||
/* the file format to create this class. */
|
||||
/* I couldn't figure out what a few of */
|
||||
/* the header fields correspond to, but */
|
||||
/* for the purposes of STK, this */
|
||||
/* shouldn't create any problems. */
|
||||
/*******************************************/
|
||||
|
||||
#include "Object.h"
|
||||
#include "WvOut.h"
|
||||
|
||||
#if !defined(__MatWvOut_h)
|
||||
#define __MatWvOut_h
|
||||
|
||||
#define MAT_BUFFER_SIZE 1024
|
||||
|
||||
class MatWvOut : public WvOut
|
||||
{
|
||||
protected:
|
||||
FILE *fd;
|
||||
double data[MAT_BUFFER_SIZE]; /* not MY_FLOAT because MAT uses doubles */
|
||||
long counter;
|
||||
long totalCount;
|
||||
int chans;
|
||||
MY_FLOAT pan;
|
||||
public:
|
||||
MatWvOut(char *infileName);
|
||||
MatWvOut(int channels, char *infileName);
|
||||
~MatWvOut();
|
||||
long getCounter();
|
||||
MY_FLOAT getTime();
|
||||
void setMonoPan(MY_FLOAT aPan);
|
||||
void tick(MY_FLOAT sample);
|
||||
void tick(MY_FLOAT lsamp, MY_FLOAT rsamp);
|
||||
};
|
||||
|
||||
#endif // defined(__MatWvOut_h)
|
||||
43
Modal4.cpp
43
Modal4.cpp
@@ -21,33 +21,32 @@ Modal4 :: Modal4()
|
||||
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
vibr->normalize();
|
||||
vibr->setFreq(6.0);
|
||||
vibrGain = 0.05;
|
||||
vibr->setFreq((MY_FLOAT) 6.0);
|
||||
vibrGain = (MY_FLOAT) 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);
|
||||
directGain = (MY_FLOAT) 0.0;
|
||||
masterGain = (MY_FLOAT) 1.0;
|
||||
baseFreq = (MY_FLOAT) 440.0;
|
||||
this->setRatioAndReson(0,(MY_FLOAT) 1.00,(MY_FLOAT) 0.9997); /* Set some */
|
||||
this->setRatioAndReson(1,(MY_FLOAT) 1.30,(MY_FLOAT) 0.9997); /* silly */
|
||||
this->setRatioAndReson(2,(MY_FLOAT) 1.77,(MY_FLOAT) 0.9997); /* default */
|
||||
this->setRatioAndReson(3,(MY_FLOAT) 2.37,(MY_FLOAT) 0.9997); /* values here */
|
||||
this->setFiltGain(0,(MY_FLOAT) 0.01);
|
||||
this->setFiltGain(1,(MY_FLOAT) 0.01);
|
||||
this->setFiltGain(2,(MY_FLOAT) 0.01);
|
||||
this->setFiltGain(3,(MY_FLOAT) 0.01);
|
||||
this->clear();
|
||||
filters[0]->setEqualGainZeroes();
|
||||
filters[1]->setEqualGainZeroes();
|
||||
filters[2]->setEqualGainZeroes();
|
||||
filters[3]->setEqualGainZeroes();
|
||||
stickHardness = 0.5;
|
||||
strikePosition = 0.561;
|
||||
stickHardness = (MY_FLOAT) 0.5;
|
||||
strikePosition = (MY_FLOAT) 0.561;
|
||||
}
|
||||
|
||||
Modal4 :: ~Modal4()
|
||||
{
|
||||
delete envelope;
|
||||
delete wave;
|
||||
delete filters[0];
|
||||
delete filters[1];
|
||||
delete filters[2];
|
||||
@@ -84,7 +83,7 @@ void Modal4 :: setRatioAndReson(int whichOne, MY_FLOAT ratio,MY_FLOAT reson)
|
||||
}
|
||||
else {
|
||||
temp = ratio;
|
||||
while (temp*baseFreq > SRATE_OVER_TWO) temp *= 0.5;
|
||||
while (temp*baseFreq > SRATE_OVER_TWO) temp *= (MY_FLOAT) 0.5;
|
||||
ratios[whichOne] = temp;
|
||||
#if defined(_debug_)
|
||||
printf("Modal4 : Aliasing would occur here, correcting.\n");
|
||||
@@ -117,9 +116,9 @@ void Modal4 :: strike(MY_FLOAT amplitude)
|
||||
{
|
||||
int i;
|
||||
MY_FLOAT temp;
|
||||
envelope->setRate(1.0);
|
||||
envelope->setRate((MY_FLOAT) 1.0);
|
||||
envelope->setTarget(amplitude);
|
||||
onepole->setPole(1.0 - amplitude);
|
||||
onepole->setPole((MY_FLOAT) 1.0 - amplitude);
|
||||
envelope->tick();
|
||||
wave->reset();
|
||||
for (i=0;i<4;i++) {
|
||||
@@ -142,7 +141,7 @@ void Modal4 :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
|
||||
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) */
|
||||
this->damp((MY_FLOAT) 1.0 - (amp * (MY_FLOAT) 0.03)); /* (high amplitude means fast damping) */
|
||||
#if defined(_debug_)
|
||||
printf("Modal4 : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
@@ -177,11 +176,11 @@ MY_FLOAT Modal4 :: tick()
|
||||
temp2 += directGain * temp;
|
||||
|
||||
if (vibrGain != 0.0) {
|
||||
temp = 1.0 + (vibr->tick() * vibrGain); /* Calculate AM */
|
||||
temp = (MY_FLOAT) 1.0 + (vibr->tick() * vibrGain); /* Calculate AM */
|
||||
temp2 = temp * temp2; /* and apply to master out */
|
||||
}
|
||||
|
||||
lastOutput = temp2 * 2.0;
|
||||
lastOutput = temp2 * (MY_FLOAT) 2.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
|
||||
2
Modal4.h
2
Modal4.h
@@ -34,7 +34,7 @@ class Modal4 : public Instrmnt
|
||||
MY_FLOAT resons[4];
|
||||
public:
|
||||
Modal4();
|
||||
~Modal4();
|
||||
virtual ~Modal4();
|
||||
void clear();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void setRatioAndReson(int whichOne, MY_FLOAT ratio, MY_FLOAT reson);
|
||||
|
||||
25
Modulatr.cpp
25
Modulatr.cpp
@@ -5,20 +5,19 @@
|
||||
/* natural human modulation function. */
|
||||
/*******************************************/
|
||||
|
||||
#define POLE_POS 0.999
|
||||
#define RND_SCALE 10.0
|
||||
#define POLE_POS (MY_FLOAT) 0.999
|
||||
#define RND_SCALE (MY_FLOAT) 10.0
|
||||
|
||||
#include "Modulatr.h"
|
||||
|
||||
Modulatr :: Modulatr()
|
||||
{
|
||||
vibwave = new RawWave("rawwaves/sinewave.raw");
|
||||
vibwave = new RawLoop("rawwaves/sinewave.raw");
|
||||
vibwave->normalize();
|
||||
vibwave->setFreq(6.0);
|
||||
vibwave->setLooping(1);
|
||||
vibAmt = 0.04;
|
||||
vibwave->setFreq((MY_FLOAT) 6.0);
|
||||
vibAmt = (MY_FLOAT) 0.04;
|
||||
noise = new SubNoise(330);
|
||||
rndAmt = 0.005;
|
||||
rndAmt = (MY_FLOAT) 0.005;
|
||||
onepole = new OnePole;
|
||||
onepole->setPole(POLE_POS);
|
||||
onepole->setGain(rndAmt * RND_SCALE);
|
||||
@@ -33,33 +32,33 @@ Modulatr :: ~Modulatr()
|
||||
|
||||
void Modulatr :: reset()
|
||||
{
|
||||
lastOutput = 0.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void Modulatr :: setVibFreq(double vibFreq)
|
||||
void Modulatr :: setVibFreq(MY_FLOAT vibFreq)
|
||||
{
|
||||
vibwave->setFreq(vibFreq);
|
||||
}
|
||||
|
||||
void Modulatr :: setVibAmt(double vibAmount)
|
||||
void Modulatr :: setVibAmt(MY_FLOAT vibAmount)
|
||||
{
|
||||
vibAmt = vibAmount;
|
||||
}
|
||||
|
||||
void Modulatr :: setRndAmt(double rndAmount)
|
||||
void Modulatr :: setRndAmt(MY_FLOAT rndAmount)
|
||||
{
|
||||
rndAmt = rndAmount;
|
||||
onepole->setGain(RND_SCALE * rndAmt);
|
||||
}
|
||||
|
||||
double Modulatr :: tick()
|
||||
MY_FLOAT Modulatr :: tick()
|
||||
{
|
||||
lastOutput = vibAmt * vibwave->tick(); /* Compute periodic and */
|
||||
lastOutput += onepole->tick(noise->tick()); /* random modulations */
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
double Modulatr :: lastOut()
|
||||
MY_FLOAT Modulatr :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
20
Modulatr.h
20
Modulatr.h
@@ -9,28 +9,28 @@
|
||||
#define __Modulatr_h
|
||||
|
||||
#include "Object.h"
|
||||
#include "RawWave.h"
|
||||
#include "RawLoop.h"
|
||||
#include "SubNoise.h"
|
||||
#include "OnePole.h"
|
||||
|
||||
class Modulatr : public Object
|
||||
{
|
||||
protected:
|
||||
RawWave *vibwave;
|
||||
RawLoop *vibwave;
|
||||
SubNoise *noise;
|
||||
OnePole *onepole;
|
||||
double vibAmt;
|
||||
double rndAmt;
|
||||
double lastOutput;
|
||||
MY_FLOAT vibAmt;
|
||||
MY_FLOAT rndAmt;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Modulatr();
|
||||
~Modulatr();
|
||||
void reset();
|
||||
void setVibFreq(double vibFreq);
|
||||
void setVibAmt(double vibAmount);
|
||||
void setRndAmt(double rndAmount);
|
||||
double tick();
|
||||
double lastOut();
|
||||
void setVibFreq(MY_FLOAT vibFreq);
|
||||
void setVibAmt(MY_FLOAT vibAmount);
|
||||
void setRndAmt(MY_FLOAT rndAmount);
|
||||
MY_FLOAT tick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
57
Moog1.cpp
57
Moog1.cpp
@@ -10,22 +10,21 @@
|
||||
/******************************************/
|
||||
|
||||
#include "Moog1.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
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 */
|
||||
loops[0] = new RawLoop("rawwaves/impuls20.raw");
|
||||
loops[1] = new RawLoop("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;
|
||||
loops[1]->setFreq((MY_FLOAT) 6.122);
|
||||
adsr->setAllTimes((MY_FLOAT) 0.001,(MY_FLOAT) 1.5,(MY_FLOAT) 0.6,(MY_FLOAT) 0.250);
|
||||
filterQ = (MY_FLOAT) 0.85;
|
||||
filterRate = (MY_FLOAT) 0.0001;
|
||||
modDepth = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
Moog1 :: ~Moog1()
|
||||
@@ -38,7 +37,7 @@ Moog1 :: ~Moog1()
|
||||
void Moog1 :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
attacks[0]->setFreq(baseFreq * 0.01);
|
||||
attacks[0]->setFreq(baseFreq * (MY_FLOAT) 0.01);
|
||||
loops[0]->setFreq(baseFreq);
|
||||
}
|
||||
|
||||
@@ -48,17 +47,17 @@ void Moog1 :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
|
||||
this->setFreq(freq);
|
||||
this->keyOn();
|
||||
attackGain = amp * 0.5;
|
||||
attackGain = amp * (MY_FLOAT) 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);
|
||||
temp = filterQ + (MY_FLOAT) 0.05;
|
||||
filters[0]->setStates((MY_FLOAT) 2000.0,temp,(MY_FLOAT) 2.0 * ((MY_FLOAT) 1.0 - temp));
|
||||
filters[1]->setStates((MY_FLOAT) 2000.0,temp,(MY_FLOAT) 2.0 * ((MY_FLOAT) 1.0 - temp));
|
||||
temp = filterQ + (MY_FLOAT) 0.099;
|
||||
filters[0]->setTargets((MY_FLOAT) freq,temp,(MY_FLOAT) 2.0 * ((MY_FLOAT) 1.0 - temp));
|
||||
filters[1]->setTargets((MY_FLOAT) freq,temp,(MY_FLOAT) 2.0 * ((MY_FLOAT) 1.0 - temp));
|
||||
filters[0]->setSweepRate(filterRate * (MY_FLOAT) 22050.0 / SRATE);
|
||||
filters[1]->setSweepRate(filterRate * (MY_FLOAT) 22050.0 / SRATE);
|
||||
#if defined(_debug_)
|
||||
printf("Moog1 : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
@@ -71,7 +70,7 @@ void Moog1 :: setModulationSpeed(MY_FLOAT mSpeed)
|
||||
|
||||
void Moog1 :: setModulationDepth(MY_FLOAT mDepth)
|
||||
{
|
||||
modDepth = mDepth * 0.5;
|
||||
modDepth = mDepth * (MY_FLOAT) 0.5;
|
||||
}
|
||||
|
||||
void Moog1 :: controlChange(int number, MY_FLOAT value)
|
||||
@@ -79,15 +78,15 @@ 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)
|
||||
if (number == __SK_FilterQ_)
|
||||
filterQ = (MY_FLOAT) 0.80 + ((MY_FLOAT) 0.1 * value * NORM_7);
|
||||
else if (number == __SK_FilterSweepRate_)
|
||||
filterRate = (value * NORM_7 * (MY_FLOAT) 0.0002);
|
||||
else if (number == __SK_ModFrequency_)
|
||||
this->setModulationSpeed(value * NORM_7 * (MY_FLOAT) 12.0);
|
||||
else if (number == __SK_ModWheel_)
|
||||
this->setModulationDepth(value * NORM_7);
|
||||
else if (number == MIDI_after_touch)
|
||||
else if (number == __SK_AfterTouch_Cont_)
|
||||
adsr->setTarget(value * NORM_7);
|
||||
else {
|
||||
printf("Moog1 : Undefined Control Number!!\n");
|
||||
@@ -100,7 +99,7 @@ MY_FLOAT Moog1 :: tick()
|
||||
|
||||
if (modDepth!=0.0) {
|
||||
temp = loops[1]->tick() * modDepth;
|
||||
loops[0]->setFreq(baseFreq * (1.0 + temp));
|
||||
loops[0]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp));
|
||||
}
|
||||
lastOutput = SamplFlt :: tick();
|
||||
return lastOutput;
|
||||
|
||||
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
|
||||
138
NRev.cpp
Normal file
138
NRev.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/******************************************/
|
||||
/* NRev Reverb Subclass */
|
||||
/* by Tim Stilson, 1998 */
|
||||
/* based on CLM NRev */
|
||||
/* Integrated into STK by Gary Scavone */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* arrangement consists of 6 comb */
|
||||
/* filters in parallel, followed by 3 */
|
||||
/* allpass filters, a lowpass filter, */
|
||||
/* and another allpass in series, */
|
||||
/* followed by two allpass filters in */
|
||||
/* parallel with corresponding right and */
|
||||
/* left outputs. */
|
||||
/******************************************/
|
||||
|
||||
#include "NRev.h"
|
||||
|
||||
NRev :: NRev(MY_FLOAT T60)
|
||||
{
|
||||
int lens[15]={1433,1601,1867,2053,2251,2399,347,113,37,59,53,43,37,29,19};
|
||||
double srscale= SRATE / 25641.0;
|
||||
int val;
|
||||
int i;
|
||||
|
||||
for (i=0; i<15; i++)
|
||||
{
|
||||
val = (int)floor(srscale*lens[i]);
|
||||
if ((val & 1) == 0) val++;
|
||||
while (!this->isprime(val)) val+=2;
|
||||
lens[i]=val;
|
||||
}
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
CdelayLine[i] = new DLineN((long) (lens[i]) + 2);
|
||||
CdelayLine[i]->setDelay((long) (lens[i]));
|
||||
combCoef[i] = pow(10,(-3 * lens[i] / (T60 * SRATE)));
|
||||
}
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
APdelayLine[i] = new DLineN((long) (lens[i+6]) + 2);
|
||||
APdelayLine[i]->setDelay((long) (lens[i+6]));
|
||||
}
|
||||
|
||||
allPassCoeff = 0.7;
|
||||
effectMix = 0.3;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
NRev :: ~NRev()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<6; i++) delete CdelayLine[i];
|
||||
for (i=0; i<8; i++) delete APdelayLine[i];
|
||||
}
|
||||
|
||||
void NRev :: clear()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<6; i++) CdelayLine[i]->clear();
|
||||
for (i=0; i<8; i++) APdelayLine[i]->clear();
|
||||
lastOutL = 0.0;
|
||||
lastOutR = 0.0;
|
||||
lpLastout = 0.0;
|
||||
}
|
||||
|
||||
void NRev :: setEffectMix(MY_FLOAT mix)
|
||||
{
|
||||
effectMix = mix;
|
||||
}
|
||||
|
||||
MY_FLOAT NRev :: lastOutput()
|
||||
{
|
||||
return (lastOutL + lastOutR) * 0.5;
|
||||
}
|
||||
|
||||
MY_FLOAT NRev :: lastOutputL()
|
||||
{
|
||||
return lastOutL;
|
||||
}
|
||||
|
||||
MY_FLOAT NRev :: lastOutputR()
|
||||
{
|
||||
return lastOutR;
|
||||
}
|
||||
|
||||
MY_FLOAT NRev :: tick(MY_FLOAT input)
|
||||
{
|
||||
MY_FLOAT temp,temp0,temp1,temp2,temp3;
|
||||
int i;
|
||||
|
||||
temp0 = 0.0;
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
temp = input + (combCoef[i] * CdelayLine[i]->lastOut());
|
||||
temp0 += CdelayLine[i]->tick(temp);
|
||||
}
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
temp = APdelayLine[i]->lastOut();
|
||||
temp1 = allPassCoeff * temp;
|
||||
temp1 += temp0;
|
||||
APdelayLine[i]->tick(temp1);
|
||||
temp0 = -(allPassCoeff * temp1) + temp;
|
||||
}
|
||||
lpLastout = 0.7*lpLastout + 0.3*temp0; // onepole LP filter
|
||||
temp = APdelayLine[3]->lastOut();
|
||||
temp1 = allPassCoeff * temp;
|
||||
temp1 += lpLastout;
|
||||
APdelayLine[3]->tick(temp1);
|
||||
temp1 = -(allPassCoeff * temp1) + temp;
|
||||
|
||||
temp = APdelayLine[4]->lastOut();
|
||||
temp2 = allPassCoeff * temp;
|
||||
temp2 += temp1;
|
||||
APdelayLine[4]->tick(temp2);
|
||||
lastOutL = effectMix*(-(allPassCoeff * temp2) + temp);
|
||||
|
||||
temp = APdelayLine[5]->lastOut();
|
||||
temp3 = allPassCoeff * temp;
|
||||
temp3 += temp1;
|
||||
APdelayLine[5]->tick(temp3);
|
||||
lastOutR = effectMix*(-(allPassCoeff * temp3) + temp);
|
||||
|
||||
temp = (1.0 - effectMix) * input;
|
||||
lastOutL += temp;
|
||||
lastOutR += temp;
|
||||
|
||||
return (lastOutL + lastOutR) * 0.5;
|
||||
|
||||
}
|
||||
52
NRev.h
Normal file
52
NRev.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/******************************************/
|
||||
/* NRev Reverb Subclass */
|
||||
/* by Tim Stilson, 1998 */
|
||||
/* based on CLM NRev */
|
||||
/* Integrated into STK by Gary Scavone */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* arrangement consists of 6 comb */
|
||||
/* filters in parallel, followed by 3 */
|
||||
/* allpass filters, a lowpass filter, */
|
||||
/* and another allpass in series, */
|
||||
/* followed by two allpass filters in */
|
||||
/* parallel with corresponding right and */
|
||||
/* left outputs. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__NRev_h)
|
||||
#define __NRev_h
|
||||
|
||||
#include "Object.h"
|
||||
#include "Reverb.h"
|
||||
#include "DLineN.h"
|
||||
|
||||
class NRev : public Reverb
|
||||
{
|
||||
protected:
|
||||
DLineN *APdelayLine[8];
|
||||
DLineN *CdelayLine[6];
|
||||
MY_FLOAT allPassCoeff;
|
||||
MY_FLOAT combCoef[6];
|
||||
MY_FLOAT lpLastout;
|
||||
MY_FLOAT lastOutL;
|
||||
MY_FLOAT lastOutR;
|
||||
MY_FLOAT effectMix;
|
||||
public:
|
||||
NRev(MY_FLOAT T60);
|
||||
~NRev();
|
||||
void clear();
|
||||
void setEffectMix(MY_FLOAT mix);
|
||||
MY_FLOAT lastOutput();
|
||||
MY_FLOAT lastOutputL();
|
||||
MY_FLOAT lastOutputR();
|
||||
MY_FLOAT tick(MY_FLOAT input);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
33
Noise.cpp
33
Noise.cpp
@@ -5,34 +5,35 @@
|
||||
/*******************************************/
|
||||
|
||||
#include "Noise.h"
|
||||
#ifdef __NeXT_
|
||||
#include <libc.h>
|
||||
#endif
|
||||
|
||||
#if defined(__OS_Win_) /* For Windows95 or NT */
|
||||
#define ONE_OVER_RANDLIMIT 0.00006103516
|
||||
#else /* This is for Linux, NeXT and SGI */
|
||||
#define ONE_OVER_RANDLIMIT 0.00000000093132258
|
||||
#endif
|
||||
|
||||
Noise :: Noise() : Object()
|
||||
{
|
||||
lastOutput = 0.0;
|
||||
lastOutput = (MY_FLOAT) 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 */
|
||||
|
||||
/* THIS ONE IS WIN95 */
|
||||
#if defined(__OS_Win_) /* For Windows95 or NT */
|
||||
lastOutput = (MY_FLOAT) (rand() - 16383);
|
||||
#else /* This is for Linux, NeXT and SGI */
|
||||
lastOutput = (MY_FLOAT) random() - 1073741823.0;
|
||||
lastOutput *= ONE_OVER_RANDLIMIT;
|
||||
#endif
|
||||
|
||||
lastOutput *= (MY_FLOAT) ONE_OVER_RANDLIMIT;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
|
||||
4
Noise.h
4
Noise.h
@@ -15,8 +15,8 @@ class Noise : public Object
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Noise();
|
||||
~Noise();
|
||||
virtual MY_FLOAT tick();
|
||||
virtual ~Noise();
|
||||
MY_FLOAT tick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
|
||||
@@ -7,20 +7,14 @@
|
||||
/*******************************************/
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
// #include "byteswap.c"
|
||||
|
||||
/* 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()
|
||||
|
||||
130
Object.h
130
Object.h
@@ -1,10 +1,10 @@
|
||||
/*******************************************/
|
||||
/*********************************************/
|
||||
/* 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
|
||||
@@ -17,49 +17,87 @@
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
int MIDI_control1;
|
||||
int MIDI_control2;
|
||||
int MIDI_control3;
|
||||
int MIDI_mod_wheel;
|
||||
int MIDI_after_touch;
|
||||
protected:
|
||||
Object();
|
||||
~Object();
|
||||
virtual ~Object();
|
||||
};
|
||||
|
||||
/* Only use one of __SGI_ __NeXT_ __DOS_ */
|
||||
/* And choice of __SGI_REALTIME or not */
|
||||
/* #define __OS_NeXT_ */
|
||||
#define __OS_IRIX_
|
||||
/* #define __OS_Linux_ */
|
||||
/* #define __OS_Win_ */
|
||||
|
||||
#define __SGI_
|
||||
#define __SGI_REALTIME
|
||||
/* #define __NeXT_ */
|
||||
#if defined(__OS_NeXT_) /* For NeXTStep - Black or White Hardware */
|
||||
#define __NeXT_
|
||||
#elif defined(__OS_IRIX_) /* For SGI */
|
||||
#define __SGI_REALTIME_
|
||||
typedef int bool;
|
||||
#elif defined(__OS_Linux_) /* For Linux */
|
||||
#define __USS_REALTIME_
|
||||
#define __LITTLE_ENDIAN__
|
||||
#elif defined(__OS_Win_) /* For Windows95 or NT */
|
||||
#define __WINDS_REALTIME_ /* For Direct Sound API */
|
||||
/* #define __WINMM_REALTIME_ */ /* For Win MM API */
|
||||
#define __SOCKET
|
||||
#define __LITTLE_ENDIAN__
|
||||
#endif
|
||||
|
||||
/* Real-time output buffer size. If clicks are occuring in the
|
||||
* output sound stream, a larger buffer size may help. Larger
|
||||
* buffer sizes, however, produce more latency between input and
|
||||
* output.
|
||||
*/
|
||||
#define RT_BUFFER_SIZE 256
|
||||
|
||||
/* This sets the maximum number of simultaneous
|
||||
* (within a buffer) MIDI messages that can be
|
||||
* serviced before messages begin to be lost or
|
||||
* overwritten. It should be a function of
|
||||
* RT_BUFFER_SIZE
|
||||
*/
|
||||
#define MAX_IN_STRINGS 25
|
||||
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#define SRATE (MY_FLOAT) 44100.0
|
||||
#define SRATE_OVER_TWO (MY_FLOAT) 22050.0
|
||||
#define ONE_OVER_SRATE (MY_FLOAT) 0.00002267573696
|
||||
#define RATE_NORM (MY_FLOAT) 0.5
|
||||
#define TWO_PI_OVER_SRATE (MY_FLOAT) 0.0001424758573
|
||||
|
||||
/* 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
|
||||
|
||||
/*
|
||||
#define SRATE (MY_FLOAT) 22050.0
|
||||
#define SRATE_OVER_TWO (MY_FLOAT) 11025.0
|
||||
#define ONE_OVER_SRATE (MY_FLOAT) 0.00004535147392
|
||||
#define RATE_NORM (MY_FLOAT) 1.0
|
||||
#define TWO_PI_OVER_SRATE (MY_FLOAT) 0.0002849517146
|
||||
*/
|
||||
/* SRATE here is 16000, others are derived accordingly */
|
||||
/*
|
||||
#define SRATE (MY_FLOAT) 16000.0
|
||||
#define SRATE_OVER_TWO (MY_FLOAT) 8000.0
|
||||
#define ONE_OVER_SRATE (MY_FLOAT) 0.0000625
|
||||
#define RATE_NORM (MY_FLOAT) 1.375
|
||||
#define TWO_PI_OVER_SRATE (MY_FLOAT) 0.000392699
|
||||
*/
|
||||
|
||||
/* 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
|
||||
/*
|
||||
#define SRATE (MY_FLOAT) 8000.0
|
||||
#define SRATE_OVER_TWO (MY_FLOAT) 4000
|
||||
#define ONE_OVER_SRATE (MY_FLOAT) 0.00012500000000
|
||||
#define RATE_NORM (MY_FLOAT) 2.75625
|
||||
#define TWO_PI_OVER_SRATE (MY_FLOAT) 0.0002849517146
|
||||
*/
|
||||
/* 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
|
||||
#if !defined(PI)
|
||||
#define PI (MY_FLOAT) 3.14159265359
|
||||
#endif
|
||||
#define TWO_PI (MY_FLOAT) 6.28318530718
|
||||
#define ONE_OVER_TWO_PI (MY_FLOAT) 0.15915494309
|
||||
#define SQRT_TWO 1.414213562
|
||||
|
||||
/* States for Envelopes, etc. */
|
||||
|
||||
@@ -68,24 +106,28 @@ class Object
|
||||
#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 */
|
||||
/* Machine dependent stuff, possibly useful for optimization.
|
||||
* For example, changing double to float here increasesf
|
||||
* 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 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 MY_FLOAT float
|
||||
#define MY_FLOAT_SIZE 4
|
||||
*/
|
||||
|
||||
/* 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*/
|
||||
/* MIDI definitions */
|
||||
#define NORM_7 (MY_FLOAT) 0.0078125 /* this is 1/128 */
|
||||
|
||||
#endif
|
||||
|
||||
20
OnePole.cpp
20
OnePole.cpp
@@ -17,11 +17,11 @@
|
||||
|
||||
OnePole :: OnePole() : Filter()
|
||||
{
|
||||
poleCoeff = 0.9;
|
||||
gain = 1.0;
|
||||
sgain = 0.1;
|
||||
poleCoeff = (MY_FLOAT) 0.9;
|
||||
gain = (MY_FLOAT) 1.0;
|
||||
sgain = (MY_FLOAT) 0.1;
|
||||
outputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
|
||||
outputs[0] = 0.0;
|
||||
outputs[0] = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
OnePole :: ~OnePole()
|
||||
@@ -31,26 +31,26 @@ OnePole :: ~OnePole()
|
||||
|
||||
void OnePole :: clear()
|
||||
{
|
||||
outputs[0] = 0.0;
|
||||
lastOutput = 0.0;
|
||||
outputs[0] = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 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);
|
||||
sgain = gain * ((MY_FLOAT) 1.0 - poleCoeff);
|
||||
else
|
||||
sgain = gain * (1.0 + poleCoeff);
|
||||
sgain = gain * ((MY_FLOAT) 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 */
|
||||
sgain = gain * ((MY_FLOAT) 1.0 - poleCoeff); /* Normalize gain to 1.0 max */
|
||||
else
|
||||
sgain = gain * (1.0 + poleCoeff);
|
||||
sgain = gain * ((MY_FLOAT) 1.0 + poleCoeff);
|
||||
}
|
||||
|
||||
MY_FLOAT OnePole :: tick(MY_FLOAT sample) /* Perform Filter Operation */
|
||||
|
||||
18
OneZero.cpp
18
OneZero.cpp
@@ -17,9 +17,9 @@
|
||||
|
||||
OneZero :: OneZero()
|
||||
{
|
||||
gain = 1.0;
|
||||
zeroCoeff = 1.0;
|
||||
sgain = 0.5;
|
||||
gain = (MY_FLOAT) 1.0;
|
||||
zeroCoeff = (MY_FLOAT) 1.0;
|
||||
sgain = (MY_FLOAT) 0.5;
|
||||
inputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
|
||||
this->clear();
|
||||
}
|
||||
@@ -31,26 +31,26 @@ OneZero :: ~OneZero()
|
||||
|
||||
void OneZero :: clear()
|
||||
{
|
||||
inputs[0] = 0.0;
|
||||
lastOutput = 0.0;
|
||||
inputs[0] = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 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);
|
||||
sgain = gain / ((MY_FLOAT) 1.0 + zeroCoeff);
|
||||
else
|
||||
sgain = gain / (1.0 - zeroCoeff);
|
||||
sgain = gain / ((MY_FLOAT) 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);
|
||||
sgain = gain / ((MY_FLOAT) 1.0 + zeroCoeff);
|
||||
else
|
||||
sgain = gain / (1.0 - zeroCoeff);
|
||||
sgain = gain / ((MY_FLOAT) 1.0 - zeroCoeff);
|
||||
}
|
||||
|
||||
MY_FLOAT OneZero :: tick(MY_FLOAT sample) /* Perform Filter Operation */
|
||||
|
||||
113
PRCRev.cpp
Normal file
113
PRCRev.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/*******************************************/
|
||||
/* PRCRev, a simple reverb unit */
|
||||
/* by Perry Cook, 1996. */
|
||||
/* Incorporated into the Reverb superclass */
|
||||
/* by Gary Scavone, 1998. */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* structure consists of 2 allpass units */
|
||||
/* in series followed by 2 comb filters in */
|
||||
/* parallel. */
|
||||
/*******************************************/
|
||||
|
||||
#include "PRCRev.h"
|
||||
|
||||
PRCRev :: PRCRev(MY_FLOAT T60)
|
||||
{
|
||||
int lens[4]={353,1097,1777,2137};
|
||||
double srscale = SRATE / 44100.0;
|
||||
int val, i;
|
||||
|
||||
if (SRATE < 44100.0) {
|
||||
for (i=0; i<4; i++) {
|
||||
val = (int) floor(srscale * lens[i]);
|
||||
if ((val & 1) == 0) val++;
|
||||
while (!this->isprime(val)) val += 2;
|
||||
lens[i] = val;
|
||||
}
|
||||
}
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
APdelayLine[i] = new DLineN(lens[i] + 2);
|
||||
APdelayLine[i]->setDelay(lens[i]);
|
||||
CdelayLine[i] = new DLineN(lens[i+2] + 2);
|
||||
CdelayLine[i]->setDelay(lens[i+2]);
|
||||
combCoeff[i] = pow(10,(-3 * lens[i+2] / (T60 * SRATE)));
|
||||
}
|
||||
|
||||
allPassCoeff = (MY_FLOAT) 0.7;
|
||||
effectMix = (MY_FLOAT) 0.5;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
PRCRev :: ~PRCRev()
|
||||
{
|
||||
delete APdelayLine[0];
|
||||
delete APdelayLine[1];
|
||||
delete CdelayLine[0];
|
||||
delete CdelayLine[1];
|
||||
}
|
||||
|
||||
void PRCRev :: clear()
|
||||
{
|
||||
APdelayLine[0]->clear();
|
||||
APdelayLine[1]->clear();
|
||||
CdelayLine[0]->clear();
|
||||
CdelayLine[1]->clear();
|
||||
lastOutL = (MY_FLOAT) 0.0;
|
||||
lastOutR = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void PRCRev :: setEffectMix(MY_FLOAT mix)
|
||||
{
|
||||
effectMix = mix;
|
||||
}
|
||||
|
||||
MY_FLOAT PRCRev :: lastOutput()
|
||||
{
|
||||
return (lastOutL + lastOutR) * (MY_FLOAT) 0.5;
|
||||
}
|
||||
|
||||
MY_FLOAT PRCRev :: lastOutputL()
|
||||
{
|
||||
return lastOutL;
|
||||
}
|
||||
|
||||
MY_FLOAT PRCRev :: lastOutputR()
|
||||
{
|
||||
return lastOutR;
|
||||
}
|
||||
|
||||
MY_FLOAT PRCRev :: tick(MY_FLOAT input)
|
||||
{
|
||||
MY_FLOAT temp,temp0,temp1,temp2,temp3;
|
||||
|
||||
temp = APdelayLine[0]->lastOut();
|
||||
temp0 = allPassCoeff * temp;
|
||||
temp0 += input;
|
||||
APdelayLine[0]->tick(temp0);
|
||||
temp0 = -(allPassCoeff * temp0) + temp;
|
||||
|
||||
temp = APdelayLine[1]->lastOut();
|
||||
temp1 = allPassCoeff * temp;
|
||||
temp1 += temp0;
|
||||
APdelayLine[1]->tick(temp1);
|
||||
temp1 = -(allPassCoeff * temp1) + temp;
|
||||
|
||||
temp2 = temp1 + (combCoeff[0] * CdelayLine[0]->lastOut());
|
||||
temp3 = temp1 + (combCoeff[1] * CdelayLine[1]->lastOut());
|
||||
|
||||
lastOutL = effectMix * (CdelayLine[0]->tick(temp2));
|
||||
lastOutR = effectMix * (CdelayLine[1]->tick(temp3));
|
||||
temp = (MY_FLOAT) (1.0 - effectMix) * input;
|
||||
lastOutL += temp;
|
||||
lastOutR += temp;
|
||||
|
||||
return (lastOutL + lastOutR) * (MY_FLOAT) 0.5;
|
||||
|
||||
}
|
||||
43
PRCRev.h
Normal file
43
PRCRev.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*******************************************/
|
||||
/* PRCRev, a simple reverb unit */
|
||||
/* by Perry Cook, 1996. */
|
||||
/* Incorporated into the Reverb superclass */
|
||||
/* by Gary Scavone, 1998. */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__PRCRev_h)
|
||||
#define __PRCRev_h
|
||||
|
||||
#include "Reverb.h"
|
||||
#include "DLineN.h"
|
||||
|
||||
class PRCRev : public Reverb
|
||||
{
|
||||
protected:
|
||||
DLineN *APdelayLine[2];
|
||||
DLineN *CdelayLine[2];
|
||||
MY_FLOAT allPassCoeff;
|
||||
MY_FLOAT combCoeff[2];
|
||||
MY_FLOAT lastOutL;
|
||||
MY_FLOAT lastOutR;
|
||||
MY_FLOAT effectMix;
|
||||
public:
|
||||
PRCRev(MY_FLOAT T60);
|
||||
~PRCRev();
|
||||
void clear();
|
||||
void setEffectMix(MY_FLOAT mix);
|
||||
MY_FLOAT lastOutput();
|
||||
MY_FLOAT lastOutputL();
|
||||
MY_FLOAT lastOutputR();
|
||||
MY_FLOAT tick(MY_FLOAT input);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
32
PercFlut.cpp
32
PercFlut.cpp
@@ -14,20 +14,24 @@ PercFlut :: PercFlut() : FM4Alg4()
|
||||
"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);
|
||||
this->setRatio(0,(MY_FLOAT) (1.50 * 1.000));
|
||||
this->setRatio(1,(MY_FLOAT) (3.00 * 0.995));
|
||||
this->setRatio(2,(MY_FLOAT) (2.99 * 1.005));
|
||||
this->setRatio(3,(MY_FLOAT) (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;
|
||||
adsr[0]->setAllTimes((MY_FLOAT) 0.05,(MY_FLOAT) 0.05,
|
||||
__FM4Op_susLevels[14],(MY_FLOAT) 0.05);
|
||||
adsr[1]->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.50,
|
||||
__FM4Op_susLevels[13],(MY_FLOAT) 0.5);
|
||||
adsr[2]->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.30,
|
||||
__FM4Op_susLevels[11],(MY_FLOAT) 0.05);
|
||||
adsr[3]->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.05,
|
||||
__FM4Op_susLevels[13],(MY_FLOAT) 0.01);
|
||||
twozero->setGain((MY_FLOAT) 0.0);
|
||||
modDepth = (MY_FLOAT) 0.005;
|
||||
}
|
||||
|
||||
void PercFlut :: setFreq(MY_FLOAT frequency)
|
||||
@@ -37,10 +41,10 @@ void PercFlut :: setFreq(MY_FLOAT 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];
|
||||
gains[0] = amp * __FM4Op_gains[99] * 0.5;
|
||||
gains[1] = amp * __FM4Op_gains[71] * 0.5;
|
||||
gains[2] = amp * __FM4Op_gains[93] * 0.5;
|
||||
gains[3] = amp * __FM4Op_gains[85] * 0.5;
|
||||
this->setFreq(freq);
|
||||
this->keyOn();
|
||||
#if defined(_debug_)
|
||||
|
||||
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"};
|
||||
18
Plucked.cpp
18
Plucked.cpp
@@ -12,7 +12,7 @@
|
||||
Plucked :: Plucked(MY_FLOAT lowestFreq)
|
||||
{
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
loopGain = 0.999;
|
||||
loopGain = (MY_FLOAT) 0.999;
|
||||
delayLine = new DLineA(length);
|
||||
loopFilt = new OneZero;
|
||||
pickFilt = new OnePole;
|
||||
@@ -38,19 +38,19 @@ void Plucked :: clear()
|
||||
void Plucked :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
MY_FLOAT delay;
|
||||
delay = ((MY_FLOAT) SRATE / frequency) - 0.5; /* length - delays */
|
||||
delay = (SRATE / frequency) - (MY_FLOAT) 0.5; /* length - delays */
|
||||
delayLine->setDelay(delay);
|
||||
loopGain = 0.995 + (frequency * 0.000005);
|
||||
if (loopGain>1.0) loopGain = 0.99999;
|
||||
loopGain = (MY_FLOAT) 0.995 + (frequency * (MY_FLOAT) 0.000005);
|
||||
if (loopGain>1.0) loopGain = (MY_FLOAT) 0.99999;
|
||||
}
|
||||
|
||||
void Plucked :: pluck(MY_FLOAT amplitude)
|
||||
{
|
||||
long i;
|
||||
pickFilt->setPole(0.999 - (amplitude*0.15));
|
||||
pickFilt->setGain(amplitude * 0.5);
|
||||
pickFilt->setPole((MY_FLOAT) 0.999 - (amplitude * (MY_FLOAT) 0.15));
|
||||
pickFilt->setGain(amplitude * (MY_FLOAT) 0.5);
|
||||
for (i=0;i<length;i++)
|
||||
delayLine->tick(delayLine->lastOut() * 0.6 /* fill delay with noise */
|
||||
delayLine->tick(delayLine->lastOut() * (MY_FLOAT) 0.6 /* fill delay with noise */
|
||||
+ pickFilt->tick(noise->tick())); /* additively with current */
|
||||
/* contents */
|
||||
}
|
||||
@@ -66,7 +66,7 @@ void Plucked :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
|
||||
void Plucked :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
loopGain = 1.0 - amp;
|
||||
loopGain = (MY_FLOAT) 1.0 - amp;
|
||||
#if defined(_debug_)
|
||||
printf("Plucked : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
@@ -78,7 +78,7 @@ MY_FLOAT Plucked :: tick()
|
||||
loopFilt->tick( /* here's the whole inner */
|
||||
delayLine->lastOut() /* loop of the instrument!! */
|
||||
* loopGain));
|
||||
lastOutput *= 3.0;
|
||||
lastOutput *= (MY_FLOAT) 3.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
|
||||
32
Plucked2.cpp
32
Plucked2.cpp
@@ -12,18 +12,18 @@
|
||||
Plucked2 :: Plucked2(MY_FLOAT lowestFreq)
|
||||
{
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
baseLoopGain = 0.995;
|
||||
loopGain = 0.999;
|
||||
baseLoopGain = (MY_FLOAT) 0.995;
|
||||
loopGain = (MY_FLOAT) 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;
|
||||
pluckAmp = (MY_FLOAT) 0.3;
|
||||
pluckPos = (MY_FLOAT) 0.4;
|
||||
detuning = (MY_FLOAT) 0.995;
|
||||
lastFreq = lowestFreq * (MY_FLOAT) 2.0;
|
||||
lastLength = length * (MY_FLOAT) 0.5;
|
||||
}
|
||||
|
||||
Plucked2 :: ~Plucked2()
|
||||
@@ -48,17 +48,17 @@ 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;
|
||||
delayLine->setDelay((lastLength / detuning) - (MY_FLOAT) 0.5);
|
||||
delayLine2->setDelay((lastLength * detuning) - (MY_FLOAT) 0.5);
|
||||
loopGain = baseLoopGain + (frequency * (MY_FLOAT) 0.000005);
|
||||
if (loopGain>1.0) loopGain = (MY_FLOAT) 0.99999;
|
||||
}
|
||||
|
||||
void Plucked2 :: setDetune(MY_FLOAT detune)
|
||||
{
|
||||
detuning = detune;
|
||||
delayLine->setDelay((lastLength / detuning) - 0.5);
|
||||
delayLine2->setDelay((lastLength * detuning) - 0.5);
|
||||
delayLine->setDelay((lastLength / detuning) - (MY_FLOAT) 0.5);
|
||||
delayLine2->setDelay((lastLength * detuning) - (MY_FLOAT) 0.5);
|
||||
}
|
||||
|
||||
void Plucked2 :: setFreqAndDetune(MY_FLOAT frequency,MY_FLOAT detune)
|
||||
@@ -76,13 +76,13 @@ void Plucked2 :: setPluckPos(MY_FLOAT position)
|
||||
void Plucked2 :: setBaseLoopGain(MY_FLOAT aGain)
|
||||
{
|
||||
baseLoopGain = aGain;
|
||||
loopGain = baseLoopGain + (lastFreq * 0.000005);
|
||||
if (loopGain>1.0) loopGain = 0.99999;
|
||||
loopGain = baseLoopGain + (lastFreq * (MY_FLOAT) 0.000005);
|
||||
if (loopGain>1.0) loopGain = (MY_FLOAT) 0.99999;
|
||||
}
|
||||
|
||||
void Plucked2 :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
loopGain = (1.0 - amp) * 0.5;
|
||||
loopGain = ((MY_FLOAT) 1.0 - amp) * (MY_FLOAT) 0.5;
|
||||
#if defined(_debug_)
|
||||
printf("Plucked2 : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,7 @@ class Plucked2 : public Instrmnt
|
||||
MY_FLOAT pluckPos;
|
||||
public:
|
||||
Plucked2(MY_FLOAT lowestFreq);
|
||||
~Plucked2();
|
||||
virtual ~Plucked2();
|
||||
void clear();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void setDetune(MY_FLOAT detune);
|
||||
|
||||
42
README-Linux.txt
Normal file
42
README-Linux.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
STK98v2: A ToolKit of Audio Synthesis Classes and Instruments in C++
|
||||
|
||||
By Perry R. Cook, 1995-98
|
||||
With recent help by Gary P. Scavone
|
||||
|
||||
Please read the file README.txt for more general STK information.
|
||||
|
||||
STK98 for Linux is currently using the OSS sound and MIDI API. The free version of OSS will probably work, though it doesn't work with as many soundcards as the commercial version (costs about $20).
|
||||
|
||||
STK98 should compile without much trouble, after you make the appropriate settings in Object.h and select an appropriate Makefile. Since all Linux systems should come with the GNU makefile utilities, you should be able to use either Makefile.all or Makefile.linux (which should be renamed "Makefile" before using). Typing "make" should initiate the compilation process.
|
||||
|
||||
NOTE REGARDING PTHREADS: The only issue which seems to crop up on different versions of Linux concerns threads. I am using the MIT pthreads API. Under RedHat Linux 4.x, I had to specifically include <pthread/mit/pthread.h> (the default pthread library didn't work). However, under RedHat Linux 5.0, the default works and the <pthread/mit/> path doesn't exist. I've decided to assume the default works. If you get errors with regard to pthreads when you compile, you'll have to search your system for the MIT pthread distribution and change the appropriate include statements in MIDIIO.cpp, MD2SKINI.cpp, and syntmono.cpp.
|
||||
|
||||
Once everything is compiled, you can use the scripts in "TCLSpecs" to run GUIs or invoke direct MIDI input controls. However, these scripts have been written for Tcl/Tk 8.0 ... they seem to work OK on older versions of Tcl/Tk under Linux, but not under IRIX. Tcl/Tk is free, so you might as well download the newest version.
|
||||
|
||||
Two primary executables are created during compilation - syntmono and MD2SKINI. Syntmono is the core STK synthesis server. All distributed STK instruments are run using syntmono. MD2SKINI takes raw MIDI input, converts it to SKINI format, and outputs the result to stdout or a socket port ID (under Windoze). Control data (in the form of SKINI messages) can be fed to syntmono through three principal means - SKINI scorefiles, MD2SKINI output, and Tcl/Tk GUIs. A variety of SKINI scorefiles are distributed with STK98 and can be found in the "scores" directory. Under all platforms, a scorefile can be piped or redirected to syntmono in the following way:
|
||||
|
||||
more scores/streetsf.ski | syntmono Clarinet -r
|
||||
or
|
||||
syntmono Clarinet -r < scores/streetsf.ski
|
||||
|
||||
A number of Tcl/Tk GUIs are provided in the "TCLSpecs" directory, though you will have to install Tcl/Tk on your system to use them. Realtime SKINI control data (via MD2SKINI or GUIs) can be piped to syntmono on Unix platforms in the following way:
|
||||
|
||||
MD2SKINI | syntmono Clarinet -r -i
|
||||
or
|
||||
wish < TCLSpecs/TCLPhys.tcl | syntmono Clarinet -r -i
|
||||
|
||||
|
||||
/******************************************************/
|
||||
|
||||
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.
|
||||
|
||||
/******************************************************/
|
||||
|
||||
38
README-SGI.txt
Normal file
38
README-SGI.txt
Normal file
@@ -0,0 +1,38 @@
|
||||
STK98v2: A ToolKit of Audio Synthesis Classes and Instruments in C++
|
||||
|
||||
By Perry R. Cook, 1995-98
|
||||
With recent help by Gary P. Scavone
|
||||
|
||||
Please read the file README.txt for more general STK information.
|
||||
|
||||
STK98 should compile without much trouble, after you make the appropriate settings in Object.h and select an appropriate Makefile. Apparently, SGI systems are not distributed with the GNU makefile utilities, so your safest bet is to use Makefile.sgi (which should be renamed "Makefile" before using). If you do have the GNU makefile utilities on your system, you could also use Makefile.all (which is convenient if you are on a network with a variety of different computer systems). Typing "make" should initiate the compilation process.
|
||||
|
||||
Once everything is compiled, you can use the scripts in "TCLSpecs" to run GUIs or invoke direct MIDI input controls.
|
||||
|
||||
Two primary executables are created during compilation - syntmono and MD2SKINI. Syntmono is the core STK synthesis server. All distributed STK instruments are run using syntmono. MD2SKINI takes raw MIDI input, converts it to SKINI format, and outputs the result to stdout or a socket port ID (under Windoze). Control data (in the form of SKINI messages) can be fed to syntmono through three principal means - SKINI scorefiles, MD2SKINI output, and Tcl/Tk GUIs. A variety of SKINI scorefiles are distributed with STK98 and can be found in the "scores" directory. Under all platforms, a scorefile can be piped or redirected to syntmono in the following way:
|
||||
|
||||
more scores/streetsf.ski | syntmono Clarinet -r
|
||||
or
|
||||
syntmono Clarinet -r < scores/streetsf.ski
|
||||
|
||||
A number of Tcl/Tk GUIs are provided in the "TCLSpecs" directory, though you will have to install Tcl/Tk on your system to use them. Realtime SKINI control data (via MD2SKINI or GUIs) can be piped to syntmono on Unix platforms in the following way:
|
||||
|
||||
MD2SKINI | syntmono Clarinet -r -i
|
||||
or
|
||||
wish < TCLSpecs/TCLPhys.tcl | syntmono Clarinet -r -i
|
||||
|
||||
|
||||
/******************************************************/
|
||||
|
||||
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.
|
||||
|
||||
/******************************************************/
|
||||
|
||||
65
README-Win.txt
Normal file
65
README-Win.txt
Normal file
@@ -0,0 +1,65 @@
|
||||
STK98v2: A ToolKit of Audio Synthesis Classes and Instruments in C++
|
||||
|
||||
By Perry R. Cook, 1995-98
|
||||
With recent help by Gary P. Scavone
|
||||
|
||||
Please read the file README.txt for more general STK information.
|
||||
|
||||
Realtime sound output under Win95 is supported using either the Direct Sound (dsound.lib) API or the old WinMM (winmm.lib) API. The Direct Sound version appears to well out-perform the older API. All new versions of Win95/NT come with the Direct Sound library, but early versions did not. If you have trouble running the distributed executables (compiled for Direct Sound API), then you probably don't have Direct Sound installed on your system. You can download the necessary Direct Sound stuff from Microsoft's WWW pages (http://www.microsoft.com/directx/download.asp). If all else fails, you should be able to compile using the winmm.lib routines ... more latency, but at least it will work.
|
||||
|
||||
Realtime MIDI input is supported using the winmm.lib API.
|
||||
|
||||
A Visual C++ workspace has been created for STK98, with two projects - syntmono and MD2SKINI. Everything has already been configured for you. The intermediate .obj files will be written to either the "Release" or "Debug" directories, but the executable files will be written to the main STK98 directory (where they need to be for proper execution). If you should somehow lose or hose the VC++ workspace file (STK98v2.dsw), then you will have to do a LOT of configuring to recreate it ... it's probably easier just to download the distribution again from our WWW sites. Anyway, for your benefit and mine, here is a list of things that need to be added to the various "Project Settings":
|
||||
|
||||
1. Under General: Set "Output files:" to <blank> (this will put the executable in the main STK directory.
|
||||
|
||||
2. Under C/C++ > Code Generation: Set "Use run-time library:" to Multithreaded.
|
||||
|
||||
3. Under Link > General: Add winmm.lib, dsound.lib, and Wsock32.lib to the end of the Object/library modules list.
|
||||
|
||||
4. Add all the necessary files to the project.
|
||||
|
||||
NOTE: For some of my personal STK files, I've had trouble compiling in VC++ with the "Optimize Speed" optimization setting (in Project Settings -> C/C++ -> Optimizations:). The files compile, but don't work the way they should when executed. These same files, however, have worked when compiled with the "Default" optimization setting. I've heard that there are bugs with some of these optimization settings.
|
||||
|
||||
Remember that items 1-3 above need to be done for each project and for each configuration. There might be an easy way to make global changes, but I couldn't figure it out.
|
||||
|
||||
To use the Tcl/Tk GUIs, you will have to install Tcl/Tk. I got version 8.0 and it works very well (and installed easily). The distribution is available on the WWW and is free.
|
||||
|
||||
In order for socketing to work, it is necessary to have the TCP protocol installed on your computer. This can be done from the "Network" control panel.
|
||||
|
||||
Finally, to use it all -
|
||||
|
||||
PLAY SKINI SCOREFILES IN REALTIME:
|
||||
|
||||
syntmono Clarinet -r < scores/streetsf.ski
|
||||
|
||||
USE TCL/TK GUIs FOR REALTIME CONTROL:
|
||||
|
||||
1. Open a DOS console window and start syntmono (eg. syntmono Clarinet -r -i).
|
||||
|
||||
2. Double click on a Tcl/Tk file in TCLSpecs (eg. TCLPhys.tcl) from the Windows Explorer to start the GUI. Select the "communications" menu item and "Socket" and make the connection.
|
||||
|
||||
3. Start moving the sliders to control the instrument.
|
||||
|
||||
USE REALTIME MIDI INPUT FOR CONTROL:
|
||||
|
||||
1. Open a DOS console window and start syntmono (eg. syntmono Clarinet -r -i).
|
||||
|
||||
2. Open another DOS console window and start MD2SKINI (assumes you already have
|
||||
MIDI setup correctly for your computer).
|
||||
|
||||
|
||||
/******************************************************/
|
||||
|
||||
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.
|
||||
|
||||
/******************************************************/
|
||||
|
||||
98
README.txt
98
README.txt
@@ -1,54 +1,37 @@
|
||||
TK96CPP
|
||||
A ToolKit of Audio Synthesis Classes
|
||||
and Instruments in C++
|
||||
Perry Cook, 1995-96
|
||||
STK98v2: A ToolKit of Audio Synthesis Classes and Instruments in C++
|
||||
|
||||
Please read the Legal and Ethical notes at the
|
||||
bottom of this document.
|
||||
By Perry R. Cook, 1995-98
|
||||
With recent help by Gary P. Scavone
|
||||
|
||||
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.
|
||||
Please read the Legal and Ethical notes at the bottom of this document.
|
||||
|
||||
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.
|
||||
STK has undergone a large number of revisions, changes, and additions since its initial release in 1996. With this version 2.0 release, it has been completely ported to Linux and Win95 (not tested on WinNT but should work), as well as SGI and NeXTStep (no real time capabilities under NeXTStep). See the individual README's (eg. README-linux) for platform specific information and system requirements. In general, you will have to specify your system type in Object.h and then use either the Makefile (Unix platforms) or the VC++ workspace file (STK98v2.dsw) to compile the code.
|
||||
|
||||
For more documentation on this ToolKit, the classes,
|
||||
etc, read the file HIERARCH.txt and the individual
|
||||
class definitions.
|
||||
STK now features realtime sound output and MIDI input under SGI, Linux (OSS), and Win95/NT (Direct Sound and Winmm routines). It is also possible to generate simultaneous .snd, .wav, and .mat (Matlab) output file types, as well as SKINI scorefiles using MD2SKINI.
|
||||
|
||||
SGI vs. NeXT vs. Intel vs. the world:
|
||||
See Object.h and Makefile for machine-specific
|
||||
items.
|
||||
Two primary executables are created during compilation - syntmono and MD2SKINI. Syntmono is the core STK synthesis server. All distributed STK instruments are run using syntmono. MD2SKINI takes raw MIDI input, converts it to SKINI format, and outputs the result to stdout or a socket port ID (under Windoze). Control data (in the form of SKINI messages) can be fed to syntmono through three principal means - SKINI scorefiles, MD2SKINI output, and Tcl/Tk GUIs. A variety of SKINI scorefiles are distributed with STK98 and can be found in the "scores" directory. Under all platforms, a scorefile can be piped or redirected to syntmono in the following way:
|
||||
|
||||
Initial public release. Some objects still beta.
|
||||
more scores/streetsf.ski | syntmono Clarinet -r
|
||||
or
|
||||
syntmono Clarinet -r < scores/streetsf.ski
|
||||
|
||||
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).
|
||||
A number of Tcl/Tk GUIs are provided in the "TCLSpecs" directory, though you will have to install Tcl/Tk version 8.0 or higher on your system to use them (older versions of Tcl/Tk under Linux seem to be more forgiving than under IRIX). Realtime SKINI control data (via MD2SKINI or GUIs) can be piped to syntmono on Unix platforms and perhaps under WinNT in the following way:
|
||||
|
||||
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.
|
||||
MD2SKINI | syntmono Clarinet -r -i
|
||||
or
|
||||
wish < TCLSpecs/TCLPhys.tcl | syntmono Clarinet -r -i
|
||||
|
||||
It is not possible to use realtime pipes under Win95, so socket communication is used instead. Perhaps in the future, all STK communications will be conducted using sockets. For socket communication, it is necessary to first start the syntmono socket server. For the time being, a default (hardwired) socket port of 2001 is being used by syntmono. After syntmono is running (and waiting for a socket client connection), either MD2SKINI or a Tcl/Tk GUI can be started. When using the GUI, it is necessary to invoke the "communications" menu item and select "socket" to establish the connection.
|
||||
|
||||
For more documentation on this ToolKit, the classes, etc, read the file HIERARCH.txt and the individual class definitions. Also check the platform specific README's for specific system requirements.
|
||||
|
||||
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.
|
||||
|
||||
Perry's comments 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
|
||||
@@ -91,27 +74,18 @@ processing?" The answers lie below.
|
||||
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
|
||||
/******************************************************/
|
||||
|
||||
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.
|
||||
***********************************************************
|
||||
|
||||
466
RTSoundIO.cpp
Normal file
466
RTSoundIO.cpp
Normal file
@@ -0,0 +1,466 @@
|
||||
/******************************************/
|
||||
/* RTSoundIO.cpp */
|
||||
/* Realtime Sound I/O Object for STK, */
|
||||
/* by Gary P. Scavone, 1998. */
|
||||
/* Based in part on code by Doug */
|
||||
/* Scott (SGI), Tim Stilson (Linux), */
|
||||
/* Bill Putnam (Win Wav), and */
|
||||
/* R. Marsanyi (DirectSound). */
|
||||
/* */
|
||||
/* At the moment, this object only */
|
||||
/* handles realtime sound output, though */
|
||||
/* input code can go here when someone */
|
||||
/* decides they need it (and writes it). */
|
||||
/* */
|
||||
/* This object provides a standard API */
|
||||
/* across all platforms for STK realtime */
|
||||
/* sound output. At the moment, this */
|
||||
/* object is only used by RTWvOut. */
|
||||
/******************************************/
|
||||
|
||||
#include "RTSoundIO.h"
|
||||
|
||||
#if defined(__SGI_REALTIME_)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels)
|
||||
{
|
||||
ALconfig audio_port_config;
|
||||
int lookaheadbuffers = 8; // number of lookahead buffers
|
||||
long pvbuf[2];
|
||||
int nbuf, totalBufSize;
|
||||
|
||||
audio_port_config = ALnewconfig();
|
||||
if(ALsetchannels(audio_port_config, channels) < 0) {
|
||||
fprintf(stderr,"Cannot initialize audio port\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Size the output queue */
|
||||
nbuf = (channels == 2) ? lookaheadbuffers : lookaheadbuffers/2;
|
||||
totalBufSize = RT_BUFFER_SIZE * nbuf;
|
||||
if(ALsetqueuesize(audio_port_config, totalBufSize) < 0) {
|
||||
fprintf(stderr,"Cannot initialize audio port\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if(audio_port) ALcloseport(audio_port);
|
||||
audio_port = ALopenport("sgi.driver", "w", audio_port_config);
|
||||
if(!audio_port) {
|
||||
fprintf(stderr,"Cannot initialize audio port\n");
|
||||
exit(0);
|
||||
}
|
||||
ALfreeconfig(audio_port_config);
|
||||
audio_port_config = 0;
|
||||
|
||||
pvbuf[0] = AL_OUTPUT_RATE;
|
||||
pvbuf[1] = (long) srate;
|
||||
ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 2); /* set output SR */
|
||||
/* tell port to accept refill at buffers - 1 */
|
||||
ALsetfillpoint(audio_port,RT_BUFFER_SIZE * (lookaheadbuffers - 1));
|
||||
}
|
||||
|
||||
RTSoundIO :: ~RTSoundIO()
|
||||
{
|
||||
if(audio_port) ALcloseport(audio_port);
|
||||
audio_port=0;
|
||||
}
|
||||
|
||||
int RTSoundIO :: playBuffer(short *buf, int bufsize)
|
||||
{
|
||||
ALwritesamps(audio_port, buf, bufsize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(__USS_REALTIME_)
|
||||
|
||||
#define ABS(x) ((x < 0) ? (-x) : (x))
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/soundcard.h>
|
||||
|
||||
RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels)
|
||||
{
|
||||
int lookaheadbuffers = 8; // number of lookahead buffers
|
||||
int nbuf, totalBufSize;
|
||||
|
||||
char DEVICE_NAME[100];
|
||||
int format;
|
||||
int stereo; /* 0=mono, 1=stereo */
|
||||
int stereoset;
|
||||
int speed;
|
||||
int BUFFER_SIZE_LOG;
|
||||
int fragsize;
|
||||
|
||||
BUFFER_SIZE_LOG = (int)(log10((double)RT_BUFFER_SIZE)/log10(2.0));
|
||||
|
||||
if (channels > 2)
|
||||
{
|
||||
fprintf(stderr,"Unsupported # of output channels!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (channels == 2) stereo = 1;
|
||||
else stereo = 0;
|
||||
|
||||
strcpy(DEVICE_NAME,"/dev/dspW");
|
||||
|
||||
if ((audio_fd = open(DEVICE_NAME, O_WRONLY, 0)) == -1)
|
||||
{ /* Opening device failed */
|
||||
fprintf(stderr,"Cannot open audio device: %s\n",DEVICE_NAME);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Size the output queue */
|
||||
nbuf = (channels == 2) ? lookaheadbuffers : lookaheadbuffers/2;
|
||||
totalBufSize = RT_BUFFER_SIZE * nbuf;
|
||||
|
||||
fragsize = (nbuf << 16) + BUFFER_SIZE_LOG;
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &fragsize))
|
||||
{
|
||||
close(audio_fd);
|
||||
fprintf(stderr,"Error setting audio buffer size!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
format = AFMT_S16_LE;
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format)==-1)
|
||||
{ /* Fatal error */
|
||||
close(audio_fd);
|
||||
fprintf(stderr,"SNDCTL_DSP_SETFMT error\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (format != AFMT_S16_LE)
|
||||
{
|
||||
close(audio_fd);
|
||||
fprintf(stderr,"Soundcard doesn't support 16-bit signed LE format\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
stereoset = stereo;
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereoset)==-1)
|
||||
{ /* Fatal error */
|
||||
close(audio_fd);
|
||||
fprintf(stderr,"SNDCTL_DSP_STEREO\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (stereoset != stereo)
|
||||
{
|
||||
close(audio_fd);
|
||||
fprintf(stderr,"The sound card did not set correct stereo mode\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
speed = (int)srate;
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1)
|
||||
{ /* Fatal error */
|
||||
close(audio_fd);
|
||||
fprintf(stderr,"SNDCTL_DSP_SPEED\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (ABS(speed - srate)>100)
|
||||
{
|
||||
close(audio_fd);
|
||||
fprintf(stderr,"The device doesn't support the requested speed.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
RTSoundIO :: ~RTSoundIO()
|
||||
{
|
||||
if(audio_fd) close(audio_fd);
|
||||
audio_fd=0;
|
||||
}
|
||||
|
||||
int RTSoundIO :: playBuffer(short *buf, int bufsize)
|
||||
{
|
||||
/* The OSS write() routine takes the buffer size in bytes, thus the
|
||||
multiplication by two.
|
||||
*/
|
||||
int len;
|
||||
|
||||
if ((len = write(audio_fd, buf, 2*bufsize)) == -1)
|
||||
{
|
||||
fprintf(stderr,"Audio write error!\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(__WINDS_REALTIME_)
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels)
|
||||
{
|
||||
HRESULT result;
|
||||
HWND hWnd;
|
||||
DWORD dwDataLen;
|
||||
WAVEFORMATEX wfFormat;
|
||||
DSBUFFERDESC dsbdDesc;
|
||||
BYTE *pDSBuffData;
|
||||
|
||||
/* Initialize pointers to NULL */
|
||||
m_pDirectSound = NULL;
|
||||
m_pDSBuffer = NULL;
|
||||
|
||||
/* Create the DS object */
|
||||
if ((result = DirectSoundCreate(NULL, &m_pDirectSound, NULL)) != DS_OK)
|
||||
{
|
||||
fprintf(stderr,"Cannot open default sound device!!\n");
|
||||
exit(0);
|
||||
}
|
||||
hWnd = GetForegroundWindow();
|
||||
if ((result = m_pDirectSound->SetCooperativeLevel(hWnd, DSSCL_EXCLUSIVE)) != DS_OK)
|
||||
{
|
||||
fprintf(stderr,"DS Constructor: couldn't set cooperative level!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Initialize the DS buffer */
|
||||
|
||||
/* Define the wave format structure */
|
||||
wfFormat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfFormat.nChannels = channels;
|
||||
wfFormat.nSamplesPerSec = (unsigned long) srate;
|
||||
wfFormat.wBitsPerSample = 8 * sizeof(short);
|
||||
wfFormat.nBlockAlign = wfFormat.nChannels * wfFormat.wBitsPerSample / 8;
|
||||
wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign;
|
||||
wfFormat.cbSize = 0;
|
||||
|
||||
/* Setup the DS buffer description */
|
||||
m_cbBufSize = RT_BUFFER_SIZE * sizeof(short) * 8;
|
||||
ZeroMemory(&dsbdDesc, sizeof(DSBUFFERDESC));
|
||||
dsbdDesc.dwSize = sizeof(DSBUFFERDESC);
|
||||
dsbdDesc.dwFlags = DSBCAPS_GLOBALFOCUS;
|
||||
dsbdDesc.dwBufferBytes = m_cbBufSize;
|
||||
dsbdDesc.lpwfxFormat = &wfFormat;
|
||||
|
||||
/* Create the DS buffer */
|
||||
if ((result = m_pDirectSound->CreateSoundBuffer(&dsbdDesc,
|
||||
&m_pDSBuffer, NULL)) != DS_OK)
|
||||
{
|
||||
fprintf(stderr,"DS Constructor: couldn't create sound buffer!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Lock the DS buffer */
|
||||
if ((result = m_pDSBuffer->Lock(0, m_cbBufSize, (LPLPVOID)&pDSBuffData,
|
||||
&dwDataLen, NULL, NULL, 0)) != DS_OK)
|
||||
{
|
||||
fprintf(stderr,"DS Constructor: couldn't lock sound buffer!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Zero the DS buffer */
|
||||
ZeroMemory(pDSBuffData, dwDataLen);
|
||||
|
||||
/* Unlock the DS buffer */
|
||||
if ((result = m_pDSBuffer->Unlock(pDSBuffData, dwDataLen, NULL, 0)) != DS_OK)
|
||||
{
|
||||
fprintf(stderr,"DS Constructor: couldn't unlock sound buffer!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
m_cbBufOffset = 0; // reset last write position to start of buffer
|
||||
|
||||
/* Start the buffer playback */
|
||||
if ((result = m_pDSBuffer->Play( 0, 0, DSBPLAY_LOOPING ) != DS_OK))
|
||||
{
|
||||
fprintf(stderr,"DS Constructor: couldn't play sound buffer!\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
RTSoundIO :: ~RTSoundIO()
|
||||
{
|
||||
// Cleanup the sound buffer
|
||||
if (m_pDSBuffer)
|
||||
{
|
||||
m_pDSBuffer->Stop();
|
||||
m_pDSBuffer->Release();
|
||||
m_pDSBuffer = NULL;
|
||||
}
|
||||
|
||||
// Cleanup the DS object
|
||||
if (m_pDirectSound)
|
||||
{
|
||||
m_pDirectSound->Release();
|
||||
m_pDirectSound = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int RTSoundIO :: playBuffer(short *buf, int bufsize)
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD status;
|
||||
LPVOID lpbuf1 = NULL;
|
||||
LPVOID lpbuf2 = NULL;
|
||||
DWORD dwsize1 = 0;
|
||||
DWORD dwsize2 = 0;
|
||||
DWORD playPos, safePos, endWrite;
|
||||
DWORD millis;
|
||||
|
||||
// Should be playing, right?
|
||||
hr = m_pDSBuffer->GetStatus( &status );
|
||||
if (!(status && DSBSTATUS_PLAYING))
|
||||
{
|
||||
printf("Buffer not playing!\n");
|
||||
}
|
||||
|
||||
// Sleep until we have enough room in buffer.
|
||||
hr = m_pDSBuffer->GetCurrentPosition( &playPos, &safePos );
|
||||
if( hr != DS_OK ) return -1;
|
||||
if( playPos < m_cbBufOffset ) playPos += m_cbBufSize; // unwrap offset
|
||||
|
||||
endWrite = m_cbBufOffset + RT_BUFFER_SIZE * sizeof(short);
|
||||
while ( playPos < endWrite ) {
|
||||
// Calculate number of milliseconds until we will have room, as
|
||||
// time = distance * (milliseconds/second) / ((bytes/sample) * (samples/second)),
|
||||
// rounded up.
|
||||
millis = (DWORD) (1.0 + ((endWrite - playPos) * 1000.0) / ( sizeof(short) * SRATE));
|
||||
|
||||
// Sleep for that long
|
||||
Sleep( millis );
|
||||
|
||||
// Wake up, find out where we are now
|
||||
hr = m_pDSBuffer->GetCurrentPosition( &playPos, &safePos );
|
||||
if( hr != DS_OK ) return -1;
|
||||
if( playPos < m_cbBufOffset ) playPos += m_cbBufSize; // unwrap offset
|
||||
}
|
||||
|
||||
// Lock free space in the DS
|
||||
hr = m_pDSBuffer->Lock (m_cbBufOffset, RT_BUFFER_SIZE * sizeof(short), &lpbuf1, &dwsize1, &lpbuf2, &dwsize2, 0);
|
||||
if (hr == DS_OK)
|
||||
{
|
||||
// Copy the buffer into the DS
|
||||
CopyMemory(lpbuf1, buf, dwsize1);
|
||||
if(NULL != lpbuf2) CopyMemory(lpbuf2, buf+dwsize1, dwsize2);
|
||||
|
||||
// Update our buffer offset and unlock sound buffer
|
||||
m_cbBufOffset = (m_cbBufOffset + dwsize1 + dwsize2) % m_cbBufSize;
|
||||
m_pDSBuffer->Unlock (lpbuf1, dwsize1, lpbuf2, dwsize2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(__WINMM_REALTIME_)
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define FRAMETIME (long) (1000.0 * RT_BUFFER_SIZE / SRATE)
|
||||
|
||||
RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels)
|
||||
{
|
||||
MMRESULT result;
|
||||
WAVEFORMATEX wfx;
|
||||
int bufferSize = RT_BUFFER_SIZE;
|
||||
|
||||
audioPort = NULL;
|
||||
|
||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfx.nChannels = channels;
|
||||
wfx.nSamplesPerSec = (unsigned long) srate;
|
||||
wfx.nBlockAlign = sizeof(short) * channels;
|
||||
wfx.nAvgBytesPerSec = (unsigned long) srate * wfx.nBlockAlign;
|
||||
wfx.wBitsPerSample = 8 * sizeof(short);
|
||||
wfx.cbSize = 0;
|
||||
|
||||
/* Open a Wave Out device using the wave mapper to guide us */
|
||||
result = waveOutOpen(&audioPort,WAVE_MAPPER,&wfx,(DWORD)NULL,(DWORD)NULL,CALLBACK_NULL);
|
||||
if (result != MMSYSERR_NOERROR) {
|
||||
fprintf(stderr,"Cannot open audio port!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for( outBufNum = 0; outBufNum < (UINT)NUM_OUT_BUFFERS; outBufNum++ )
|
||||
{
|
||||
/* set up a couple of wave headers */
|
||||
whOut[outBufNum].lpData = (LPSTR)calloc(channels*bufferSize, sizeof(short));
|
||||
if (whOut[outBufNum].lpData == NULL){
|
||||
waveOutClose( audioPort );
|
||||
fprintf(stderr,"Error initializing audio buffers!\n");
|
||||
exit(0);
|
||||
}
|
||||
whOut[outBufNum].dwBufferLength = channels*bufferSize*sizeof(short);
|
||||
whOut[outBufNum].dwBytesRecorded = 0;
|
||||
whOut[outBufNum].dwUser = 1;
|
||||
//whOut[outBufNum].dwFlags = 0;
|
||||
whOut[outBufNum].dwFlags = WHDR_DONE;
|
||||
whOut[outBufNum].dwLoops = 0;
|
||||
whOut[outBufNum].lpNext = NULL;
|
||||
whOut[outBufNum].reserved = 0;
|
||||
}
|
||||
|
||||
/* Write the first buffer out to get things going */
|
||||
outBufNum = 0;
|
||||
result = waveOutPrepareHeader(audioPort, &whOut[outBufNum],sizeof(WAVEHDR));
|
||||
result = waveOutWrite(audioPort, &whOut[outBufNum], sizeof(WAVEHDR));
|
||||
|
||||
/* Keep track of time so that we know how long we can sleep */
|
||||
lastWriteTime = timeGetTime();
|
||||
}
|
||||
|
||||
RTSoundIO :: ~RTSoundIO()
|
||||
{
|
||||
MMRESULT result;
|
||||
long timeToGo;
|
||||
|
||||
/* Close Audio Port */
|
||||
if (audioPort != NULL) {
|
||||
result = waveOutReset(audioPort);
|
||||
for( outBufNum = 0; outBufNum < (UINT)NUM_OUT_BUFFERS; outBufNum++ )
|
||||
{
|
||||
/* Loop until the next waveheader indicates that we are done */
|
||||
while( !(whOut[outBufNum].dwFlags & WHDR_DONE) )
|
||||
{
|
||||
//printf(".");
|
||||
timeToGo = (long) (FRAMETIME - (timeGetTime()-lastWriteTime));
|
||||
if( timeToGo > 0 ) Sleep( (long) timeToGo );
|
||||
}
|
||||
/* Unprepare the header */
|
||||
result = waveOutUnprepareHeader(audioPort, &whOut[outBufNum],sizeof(WAVEHDR));
|
||||
if (whOut[outBufNum].lpData != NULL) {
|
||||
free(whOut[outBufNum].lpData);
|
||||
whOut[outBufNum].lpData = NULL;
|
||||
}
|
||||
}
|
||||
result = waveOutClose(audioPort);
|
||||
}
|
||||
}
|
||||
|
||||
int RTSoundIO :: playBuffer(short *buf, int bufsize)
|
||||
{
|
||||
MMRESULT result;
|
||||
long timeToGo;
|
||||
|
||||
outBufNum++;
|
||||
if( outBufNum >= (UINT)NUM_OUT_BUFFERS ) outBufNum = 0;
|
||||
|
||||
/* Loop until the next waveheader indicates that we are done */
|
||||
while( !(whOut[outBufNum].dwFlags & WHDR_DONE) )
|
||||
{
|
||||
//printf(".");
|
||||
timeToGo = (long) (FRAMETIME - (timeGetTime()-lastWriteTime));
|
||||
//timeToGo = (long) (FRAMETIME * 0.5);
|
||||
if( timeToGo > 0 ) Sleep( (long) timeToGo );
|
||||
}
|
||||
result = waveOutUnprepareHeader(audioPort, &whOut[outBufNum], sizeof(WAVEHDR));
|
||||
|
||||
memcpy( whOut[outBufNum].lpData, buf, bufsize*sizeof(short));
|
||||
result = waveOutPrepareHeader(audioPort, &whOut[outBufNum], sizeof(WAVEHDR));
|
||||
result = waveOutWrite(audioPort, &whOut[outBufNum], sizeof(WAVEHDR));
|
||||
lastWriteTime = timeGetTime();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
61
RTSoundIO.h
Normal file
61
RTSoundIO.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/******************************************/
|
||||
/* RTSoundIO.h */
|
||||
/* Realtime Sound I/O Object for STK, */
|
||||
/* by Gary P. Scavone, 1998. */
|
||||
/* Based in part on code by Doug */
|
||||
/* Scott (SGI), Tim Stilson (Linux), */
|
||||
/* Bill Putnam (Win Wav), and */
|
||||
/* R. Marsanyi (DirectSound). */
|
||||
/* */
|
||||
/* At the moment, this object only */
|
||||
/* handles realtime sound output, though */
|
||||
/* input code can go here when someone */
|
||||
/* decides they need it (and writes it). */
|
||||
/* */
|
||||
/* This object provides a standard API */
|
||||
/* across all platforms for STK realtime */
|
||||
/* sound output. At the moment, this */
|
||||
/* object is only used by RTWvOut. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__RTSOUNDIO_h)
|
||||
#define __RTSOUNDIO_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
#if defined(__SGI_REALTIME_)
|
||||
#include <audio.h>
|
||||
#elif defined(__WINDS_REALTIME_)
|
||||
#include <windows.h>
|
||||
#include "include/dsound.h"
|
||||
#elif defined(__WINMM_REALTIME_)
|
||||
#include <windows.h>
|
||||
#include <MMSystem.h>
|
||||
#define NUM_OUT_BUFFERS 6
|
||||
#endif
|
||||
|
||||
class RTSoundIO : public Object
|
||||
{
|
||||
protected:
|
||||
#if defined(__SGI_REALTIME_)
|
||||
ALport audio_port;
|
||||
#elif defined(__USS_REALTIME_)
|
||||
int audio_fd;
|
||||
#elif defined(__WINDS_REALTIME_)
|
||||
LPDIRECTSOUND m_pDirectSound;
|
||||
LPDIRECTSOUNDBUFFER m_pDSBuffer;
|
||||
UINT m_cbBufOffset;
|
||||
UINT m_cbBufSize;
|
||||
#elif defined(__WINMM_REALTIME_)
|
||||
HWAVEOUT audioPort;
|
||||
WAVEHDR whOut[NUM_OUT_BUFFERS];
|
||||
UINT outBufNum;
|
||||
DWORD lastWriteTime;
|
||||
#endif
|
||||
public:
|
||||
RTSoundIO(MY_FLOAT srate, int channels);
|
||||
~RTSoundIO();
|
||||
int playBuffer(short *buf, int bufsize);
|
||||
};
|
||||
|
||||
#endif
|
||||
56
RTWvOut.cpp
Normal file
56
RTWvOut.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*******************************************/
|
||||
/* Raw Wave File Output Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This version opens a mono NeXT .snd */
|
||||
/* file 16bit data at 22KHz, and */
|
||||
/* pokes buffers of samples into it. */
|
||||
/*******************************************/
|
||||
|
||||
/*******************************************/
|
||||
/* SGI Real-Time Wave File Output Class, */
|
||||
/* by Perry R. Cook, 1996 */
|
||||
/* This Object can opens the SGI soundout */
|
||||
/* device, and pokes buffers of samples */
|
||||
/* into it. The real code that does the */
|
||||
/* is from Doug Scott of SGI. */
|
||||
/*******************************************/
|
||||
|
||||
/*******************************************/
|
||||
/* USS Real-Time Wave File Output Class, */
|
||||
/* by Tim Stilson, 1996 */
|
||||
/* based on code by Perry R. Cook, 1996 */
|
||||
/* This Object opens the USS sound output */
|
||||
/* device, and pokes buffers of samples */
|
||||
/* into it. */
|
||||
/*******************************************/
|
||||
|
||||
#include "RTWvOut.h"
|
||||
|
||||
RTWvOut :: RTWvOut()
|
||||
{
|
||||
soundIO = new RTSoundIO(SRATE, 1);
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
RTWvOut :: ~RTWvOut()
|
||||
{
|
||||
soundIO->playBuffer(data,counter);
|
||||
counter = 0;
|
||||
while (counter<RT_BUFFER_SIZE) {
|
||||
data[counter++] = 0;
|
||||
}
|
||||
soundIO->playBuffer(data,counter);
|
||||
soundIO->playBuffer(data,counter); // Are these extra writes necessary in USS?
|
||||
soundIO->playBuffer(data,counter);
|
||||
delete soundIO;
|
||||
}
|
||||
|
||||
void RTWvOut :: tick(MY_FLOAT sample)
|
||||
{
|
||||
|
||||
data[counter++] = (short) (sample * 32000.0);
|
||||
if (counter >= RT_BUFFER_SIZE) {
|
||||
soundIO->playBuffer(data,counter);
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
46
RTWvOut.h
Normal file
46
RTWvOut.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*******************************************/
|
||||
/* Real-Time Output Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* Separated into just realtime by */
|
||||
/* Tim Stilson, 1996 */
|
||||
/*******************************************/
|
||||
|
||||
/*******************************************/
|
||||
/* SGI Real-Time Wave File Output Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This Object can opens the SGI soundout */
|
||||
/* device, and pokes buffers of samples */
|
||||
/* into it. The real code that does the */
|
||||
/* is originally from Doug Scott of SGI. */
|
||||
/*******************************************/
|
||||
|
||||
/*******************************************/
|
||||
/* USS Real-Time Wave File Output Class, */
|
||||
/* by Tim Stilson, 1996 */
|
||||
/* based on code by Perry R. Cook, 1996 */
|
||||
/* This Object opens the USS sound output */
|
||||
/* device, and pokes buffers of samples */
|
||||
/* into it. */
|
||||
/*******************************************/
|
||||
|
||||
|
||||
#include "Object.h"
|
||||
#include "WvOut.h"
|
||||
#include "RTSoundIO.h"
|
||||
|
||||
#if !defined(__RTWvOut_h)
|
||||
#define __RTWvOut_h
|
||||
|
||||
class RTWvOut : public WvOut
|
||||
{
|
||||
protected:
|
||||
RTSoundIO *soundIO;
|
||||
short data[RT_BUFFER_SIZE];
|
||||
long counter;
|
||||
public:
|
||||
RTWvOut();
|
||||
~RTWvOut();
|
||||
void tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif // defined(__RTWvOut_h)
|
||||
24
RawLoop.cpp
24
RawLoop.cpp
@@ -1,3 +1,4 @@
|
||||
|
||||
/*******************************************/
|
||||
/* Raw Looped Soundfile Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
@@ -9,6 +10,8 @@
|
||||
|
||||
#include "RawLoop.h"
|
||||
|
||||
#include "swapstuf.h"
|
||||
|
||||
RawLoop :: RawLoop(char *fileName)
|
||||
{
|
||||
long i;
|
||||
@@ -26,14 +29,17 @@ RawLoop :: RawLoop(char *fileName)
|
||||
data = (MY_FLOAT *) malloc(MY_FLOAT_SIZE * (length + 1));
|
||||
i = 0;
|
||||
while (fread(&temp,2,1,fd)) {
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
temp = SwapShort (temp);
|
||||
#endif
|
||||
data[i] = temp;
|
||||
i++;
|
||||
}
|
||||
data[length] = data[0];
|
||||
fclose(fd);
|
||||
time = 0.0;
|
||||
phaseOffset = 0.0;
|
||||
rate = 1.0;
|
||||
time = (MY_FLOAT) 0.0;
|
||||
phaseOffset = (MY_FLOAT) 0.0;
|
||||
rate = (MY_FLOAT) 1.0;
|
||||
}
|
||||
|
||||
RawLoop :: ~RawLoop()
|
||||
@@ -43,24 +49,24 @@ RawLoop :: ~RawLoop()
|
||||
|
||||
void RawLoop :: reset()
|
||||
{
|
||||
time = 0.0;
|
||||
lastOutput = 0.0;
|
||||
time = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void RawLoop :: normalize()
|
||||
{
|
||||
this->normalize(1.0);
|
||||
this->normalize((MY_FLOAT) 1.0);
|
||||
}
|
||||
|
||||
void RawLoop :: normalize(MY_FLOAT newPeak)
|
||||
{
|
||||
long i;
|
||||
MY_FLOAT max = 0.0;
|
||||
MY_FLOAT max = (MY_FLOAT) 0.0;
|
||||
for (i=0;i<=length;i++)
|
||||
if (fabs(data[i]) > max)
|
||||
max = fabs(data[i]);
|
||||
max = (MY_FLOAT) fabs((double) data[i]);
|
||||
if (max > 0.0) {
|
||||
max = 1.0 / max;
|
||||
max = (MY_FLOAT) 1.0 / max;
|
||||
max *= newPeak;
|
||||
for (i=0;i<=length;i++)
|
||||
data[i] *= max;
|
||||
|
||||
42
RawWave.cpp
42
RawWave.cpp
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "RawWave.h"
|
||||
|
||||
#include "swapstuf.h"
|
||||
|
||||
RawWave :: RawWave(char *fileName)
|
||||
{
|
||||
long i;
|
||||
@@ -21,21 +23,25 @@ RawWave :: RawWave(char *fileName)
|
||||
}
|
||||
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)) {
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
temp = SwapShort (temp);
|
||||
#endif
|
||||
data[i] = temp;
|
||||
i++;
|
||||
}
|
||||
data[length] = data[length-1];
|
||||
fclose(fd);
|
||||
looping = 0;
|
||||
time = length;
|
||||
phaseOffset = 0.0;
|
||||
rate = 1.0;
|
||||
time = (MY_FLOAT) length;
|
||||
phaseOffset = (MY_FLOAT) 0.0;
|
||||
rate = (MY_FLOAT) 1.0;
|
||||
allDone = 0;
|
||||
}
|
||||
|
||||
@@ -46,9 +52,9 @@ RawWave :: RawWave(MY_FLOAT *someData, long aLength)
|
||||
data = someData;
|
||||
myData = 0;
|
||||
looping = 0;
|
||||
time = 0.0;
|
||||
phaseOffset = 0.0;
|
||||
rate = 1.0;
|
||||
time = (MY_FLOAT) 0.0;
|
||||
phaseOffset = (MY_FLOAT) 0.0;
|
||||
rate = (MY_FLOAT) 1.0;
|
||||
}
|
||||
|
||||
RawWave :: ~RawWave()
|
||||
@@ -61,25 +67,25 @@ RawWave :: ~RawWave()
|
||||
|
||||
void RawWave :: reset()
|
||||
{
|
||||
time = 0.0;
|
||||
lastOutput = 0.0;
|
||||
time = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
allDone = 0;
|
||||
}
|
||||
|
||||
void RawWave :: normalize()
|
||||
{
|
||||
this->normalize(1.0);
|
||||
this->normalize((MY_FLOAT) 1.0);
|
||||
}
|
||||
|
||||
void RawWave :: normalize(MY_FLOAT newPeak)
|
||||
{
|
||||
long i;
|
||||
MY_FLOAT max = 0.0;
|
||||
MY_FLOAT max = (MY_FLOAT) 0.0;
|
||||
for (i=0;i<=length;i++)
|
||||
if (fabs(data[i]) > max)
|
||||
max = fabs(data[i]);
|
||||
max = (MY_FLOAT) fabs(data[i]);
|
||||
if (max > 0.0) {
|
||||
max = 1.0 / max;
|
||||
max = (MY_FLOAT) 1.0 / max;
|
||||
max *= newPeak;
|
||||
for (i=0;i<=length;i++)
|
||||
data[i] *= max;
|
||||
@@ -93,7 +99,7 @@ void RawWave :: setRate(MY_FLOAT aRate)
|
||||
|
||||
void RawWave :: setFreq(MY_FLOAT aFreq)
|
||||
{
|
||||
rate = length * ONE_OVER_SRATE * aFreq;
|
||||
rate = length * (MY_FLOAT) ONE_OVER_SRATE * aFreq;
|
||||
}
|
||||
|
||||
void RawWave :: addTime(MY_FLOAT aTime) /* Add an absolute time */
|
||||
@@ -113,7 +119,7 @@ void RawWave :: addPhaseOffset(MY_FLOAT anAngle)
|
||||
|
||||
void RawWave :: setLooping(int aLoopStatus)
|
||||
{
|
||||
time = 0;
|
||||
time = (MY_FLOAT) 0;
|
||||
looping = aLoopStatus;
|
||||
if (looping) data[length] = data[0];
|
||||
}
|
||||
@@ -155,11 +161,11 @@ int RawWave :: informTick()
|
||||
}
|
||||
else {
|
||||
if (time >= length) { /* Check for end of sound */
|
||||
time = length-1; /* stick at end */
|
||||
time = length-(MY_FLOAT) 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 */
|
||||
time = (MY_FLOAT) 0.0; /* stick at beg */
|
||||
}
|
||||
|
||||
temp_time = time;
|
||||
@@ -174,9 +180,9 @@ int RawWave :: informTick()
|
||||
}
|
||||
else {
|
||||
if (temp_time >= length) /* Check for end of sound */
|
||||
temp_time = length-1; /* stick at end */
|
||||
temp_time = length - (MY_FLOAT) 1; /* stick at end */
|
||||
else if (temp_time < 0.0) /* check for end of sound */
|
||||
temp_time = 0.0; /* stick at beg */
|
||||
temp_time = (MY_FLOAT) 0.0; /* stick at beg */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
48
RawWvIn.cpp
48
RawWvIn.cpp
@@ -14,6 +14,7 @@
|
||||
/*******************************************/
|
||||
|
||||
#include "RawWvIn.h"
|
||||
#include "swapstuf.h"
|
||||
|
||||
RawWvIn :: RawWvIn(char *fileName)
|
||||
{
|
||||
@@ -31,12 +32,12 @@ RawWvIn :: RawWvIn(char *fileName)
|
||||
while (fread(&data,2,1,myFile)) i++;
|
||||
length = i;
|
||||
fseek(myFile,0,0);
|
||||
time = 0.0;
|
||||
rate = 1.0;
|
||||
time = (MY_FLOAT) 0.0;
|
||||
rate = (MY_FLOAT) 1.0;
|
||||
lastTime = 0;
|
||||
finished = 0;
|
||||
gain = 1.0;
|
||||
lastOutput = 0.0;
|
||||
gain = (MY_FLOAT) 1.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
RawWvIn :: ~RawWvIn()
|
||||
@@ -51,30 +52,37 @@ void RawWvIn :: reset()
|
||||
}
|
||||
fseek(myFile,0,0);
|
||||
|
||||
#if defined(_debug_)
|
||||
printf("Resetting\n");
|
||||
time = 0.0;
|
||||
#endif
|
||||
|
||||
time = (MY_FLOAT) 0.0;
|
||||
lastTime = 0;
|
||||
finished = 0;
|
||||
lastOutput = 0.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void RawWvIn :: normalize()
|
||||
{
|
||||
this->normalize(1.0);
|
||||
this->normalize((MY_FLOAT) 1.0);
|
||||
}
|
||||
|
||||
void RawWvIn :: normalize(MY_FLOAT newPeak)
|
||||
{
|
||||
long i;
|
||||
FILE *fd;
|
||||
extern short SwapShort(short);
|
||||
|
||||
gain = 0.0;
|
||||
gain = (MY_FLOAT) 0.0;
|
||||
|
||||
fd = fopen(fileNm,"rb");
|
||||
for (i=0;i<length;i++) {
|
||||
fread(&data,2,1,fd);
|
||||
#ifdef __LITTLE_ENDIAN_
|
||||
data = SwapShort(data);
|
||||
#endif
|
||||
if (fabs(data) > gain)
|
||||
gain = fabs(data);
|
||||
gain = (MY_FLOAT) fabs((double) data);
|
||||
}
|
||||
if (gain > 0.0) {
|
||||
gain = newPeak / gain;
|
||||
@@ -90,7 +98,7 @@ void RawWvIn :: setRate(MY_FLOAT aRate)
|
||||
void RawWvIn :: finish()
|
||||
{
|
||||
finished = 1;
|
||||
lastOutput = 0.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
if (myFile) {
|
||||
fclose(myFile);
|
||||
myFile = 0;
|
||||
@@ -106,22 +114,29 @@ MY_FLOAT RawWvIn :: tick()
|
||||
int RawWvIn :: informTick()
|
||||
{
|
||||
long temp;
|
||||
extern short SwapShort(short);
|
||||
|
||||
if (!finished) {
|
||||
|
||||
if (!finished)
|
||||
{
|
||||
time += rate; /* Update current time */
|
||||
|
||||
if (time >= length) { /* Check for end of sound */
|
||||
time = length - 1; /* stick at end */
|
||||
if (time >= length) /* Check for end of sound */
|
||||
{
|
||||
time = (MY_FLOAT) length - 1; /* stick at end */
|
||||
finished = 1; /* Information for one-shot use */
|
||||
fclose(myFile);
|
||||
myFile = 0;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
temp = (long) time; /* Integer part of time address */
|
||||
if (temp > lastTime) { /* If we cross next sample time */
|
||||
if (temp > lastTime) /* If we cross next sample time */
|
||||
{
|
||||
lastTime = temp;
|
||||
fread(&data,2,1,myFile); /* Snarf next sample from file */
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
data = SwapShort(data);
|
||||
#endif
|
||||
lastOutput = data * gain; /* And save as non-interpolated data */
|
||||
}
|
||||
}
|
||||
@@ -160,4 +175,3 @@ void main()
|
||||
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