From 7c0ee03d602466f1742f47d5c78c9e0a8dc22ce0 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Wed, 25 Sep 2013 11:18:58 +0200 Subject: [PATCH] Version 2.02 --- AgogoBel.cpp | 2 +- DrumSynt.cpp | 126 +++++++-------- DrumSynt.h | 27 ++-- MD2SKINI.cpp | 15 +- MIDIIO.cpp | 1 + Makefile | 3 +- Makefile.NeXT | 2 +- Makefile.linux | 2 +- Makefile.sgi | 2 +- Mandolin.cpp | 173 ++++++++++---------- Mandolin.h | 4 +- Marimba.cpp | 4 +- Modal4.h | 4 +- Moog1.cpp | 2 +- Object.h | 11 +- Plucked.cpp | 73 +++++---- Plucked2.cpp | 82 +++++----- RTSoundIO.cpp | 38 ++++- RawInterp.cpp | 245 ++++++++++++++++++++++++++++ RawInterp.h | 52 ++++++ RawLoop.cpp | 133 ++++++++------- RawLoop.h | 3 +- RawWvIn.cpp => RawShot.cpp | 87 +++++----- RawWvIn.h => RawShot.h | 14 +- RawWave.cpp | 221 ++----------------------- RawWave.h | 55 ++----- ReleaseNotes.txt | 39 +++++ STK98v2.ncb | Bin 975872 -> 1033216 bytes STK98v2.opt | Bin 53760 -> 53760 bytes Sampler.h | 4 +- Vibraphn.cpp | 2 +- hierarch.txt | 32 ++-- mus151/Debug/.placeholder | 0 mus151/GUITwoOsc | 1 + mus151/MUS151.cpp | 312 ++++++++++++++++++++++++++++++++++++ mus151/MUS151.dsp | 177 ++++++++++++++++++++ mus151/MUS151.dsw | 29 ++++ mus151/MUS151.ncb | Bin 0 -> 58368 bytes mus151/Makefile | 65 ++++++++ mus151/README-mus151.txt | 16 ++ mus151/Release/.placeholder | 0 mus151/TwoOsc.cpp | 76 +++++++++ mus151/TwoOsc.h | 35 ++++ mus151/tcl/TwoWaves.tcl | 201 +++++++++++++++++++++++ syntmono.cpp | 39 ++--- syntmono.dsp | 24 ++- syntmono.plg | 151 ++++++++++++++++- 47 files changed, 1888 insertions(+), 696 deletions(-) create mode 100644 RawInterp.cpp create mode 100644 RawInterp.h rename RawWvIn.cpp => RawShot.cpp (65%) rename RawWvIn.h => RawShot.h (83%) create mode 100644 ReleaseNotes.txt create mode 100644 mus151/Debug/.placeholder create mode 100755 mus151/GUITwoOsc create mode 100644 mus151/MUS151.cpp create mode 100644 mus151/MUS151.dsp create mode 100644 mus151/MUS151.dsw create mode 100644 mus151/MUS151.ncb create mode 100644 mus151/Makefile create mode 100644 mus151/README-mus151.txt create mode 100644 mus151/Release/.placeholder create mode 100644 mus151/TwoOsc.cpp create mode 100644 mus151/TwoOsc.h create mode 100644 mus151/tcl/TwoWaves.tcl diff --git a/AgogoBel.cpp b/AgogoBel.cpp index b6dfbc0..8a89ee6 100644 --- a/AgogoBel.cpp +++ b/AgogoBel.cpp @@ -16,7 +16,7 @@ AgogoBel :: AgogoBel() : Modal4() { - wave = new RawWave("rawwaves/britestk.raw"); + wave = new RawInterp("rawwaves/britestk.raw"); wave->normalize(); wave->setRate((MY_FLOAT) 7.0); /* hardstick */ this->setRatioAndReson(0, (MY_FLOAT) 1.00,(MY_FLOAT) 0.999); /* Set our */ diff --git a/DrumSynt.cpp b/DrumSynt.cpp index 888a353..9be2d79 100644 --- a/DrumSynt.cpp +++ b/DrumSynt.cpp @@ -2,12 +2,19 @@ /* Master Class for Drum Synthesizer */ /* by Perry R. Cook, 1995-96 */ /* This instrument contains a bunch of */ -/* NI1sWave objects (Non-Interpolating, */ -/* 1 shot players), run through a bunch */ -/* of one-pole filters. You can specify */ -/* the maximum Polyphony (maximum number */ -/* of simultaneous voices) in a #define */ -/* in the .h file. */ +/* RawWave objects, run through a bunch */ +/* of one-pole filters. All the */ +/* corresponding rawwave files have been */ +/* sampled at 22050 Hz. Thus, if the */ +/* compile-time SRATE = 22050, then */ +/* RawShot objects are used. Otherwise, */ +/* RawInterp objects are used. You can */ +/* specify the maximum Polyphony (maximum */ +/* number of simultaneous voices) in a */ +/* #define in the .h file. */ +/* */ +/* Modified for RawWave abstract class */ +/* by Gary P. Scavone (11/11/98) */ /*******************************************/ #include "DrumSynt.h" @@ -48,25 +55,40 @@ char waveNames[DRUM_NUMWAVES][16] = { DrumSynt :: DrumSynt() : Instrmnt() { int i; - + for (i=0;iclear(); /* then */ tempWv = waves[0]; tempFilt = filters[0]; - for (i=0;inormalize((MY_FLOAT) 0.2); + if (SRATE == 22050) { + waves[numSounding-1] = new RawShot(tempString); + } else { + waves[numSounding-1] = new RawInterp(tempString); + waves[numSounding-1]->setRate((MY_FLOAT) (22050.0/SRATE)); + } + waves[numSounding-1]->normalize((MY_FLOAT) 0.4); 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 { + else { waves[notDone]->reset(); filters[notDone]->setPole((MY_FLOAT) 0.999 - ((MY_FLOAT) vel * NORM_7 * 0.6)); filters[notDone]->setGain(vel / (MY_FLOAT) 128.0); @@ -118,23 +144,13 @@ void DrumSynt :: noteOn(MY_FLOAT freq, MY_FLOAT amp) MY_FLOAT DrumSynt :: tick() { - int i, j, notDone; - MY_FLOAT output; + int j, i = 0; + MY_FLOAT output = 0.0; OnePole *tempFilt; - - i = 0; - notDone = 1; - output = (MY_FLOAT) 0.0; - - if (numSounding == 0) notDone = 0; - while (notDone && (i < numSounding)) { - + + while (i < numSounding) { 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 + if (waves[i]->informTick() == 1) { delete waves[i]; tempFilt = filters[i]; @@ -147,37 +163,9 @@ MY_FLOAT DrumSynt :: tick() filters[j]->clear(); sounding[j] = -1; numSounding -= 1; - if (numSounding == 0) notDone = 0; i -= 1; } i++; } - - return output * 2; + return output; } - -/************** Test Main Program *********************/ -/* -#include "miditabl.h" -#include "RawWvOut.h" -#include "Reverb.h" -#include "Noise.h" - -void main() -{ - long i,j; - DrumSynt instrument; - RawWvOut output("test.snd"); - Reverb reverb((MY_FLOAT) 2137); - Noise noise; - - for (j=0;j<100;j++) { - i = (int) (fabs(noise.tick()) * DRUM_NUMWAVES); - 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())); - -} -*/ diff --git a/DrumSynt.h b/DrumSynt.h index ac9298a..3d4ae0d 100644 --- a/DrumSynt.h +++ b/DrumSynt.h @@ -2,19 +2,28 @@ /* Master Class for Drum Synthesizer */ /* by Perry R. Cook, 1995-96 */ /* This instrument contains a bunch of */ -/* RawWvIn objects (Non-Interpolating, */ -/* 1 shot players), run through a bunch */ -/* of one-pole filters. You can specify */ -/* the maximum Polyphony (maximum number */ -/* of simultaneous voices) in a #define */ -/* in the .h file. */ +/* RawWave objects, run through a bunch */ +/* of one-pole filters. All the */ +/* corresponding rawwave files have been */ +/* sampled at 22050 Hz. Thus, if the */ +/* compile-time SRATE = 22050, then */ +/* RawShot objects are used. Otherwise, */ +/* RawInterp objects are used. You can */ +/* specify the maximum Polyphony (maximum */ +/* number of simultaneous voices) in a */ +/* #define in the .h file. */ +/* */ +/* Modified for RawWave abstract class */ +/* by Gary P. Scavone (11/11/98) */ /*******************************************/ #if !defined(__DrumSynt_h) #define __DrumSynt_h #include "Instrmnt.h" -#include "RawWvIn.h" +#include "RawWave.h" +#include "RawShot.h" +#include "RawInterp.h" #include "OnePole.h" #define DRUM_NUMWAVES 11 @@ -23,13 +32,13 @@ class DrumSynt : public Instrmnt { protected: - RawWvIn *waves[DRUM_POLYPHONY]; + RawWave *waves[DRUM_POLYPHONY]; OnePole *filters[DRUM_POLYPHONY]; int sounding[DRUM_POLYPHONY]; int numSounding; public: DrumSynt(); -/* ~DrumSynt(); */ + ~DrumSynt(); virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp); virtual MY_FLOAT tick(); }; diff --git a/MD2SKINI.cpp b/MD2SKINI.cpp index aadee39..e921d96 100644 --- a/MD2SKINI.cpp +++ b/MD2SKINI.cpp @@ -90,7 +90,6 @@ void errorf(void) { void main(int argc,char *argv[]) { long j; - int oneOn = 0; MY_FLOAT byte2, byte3; int channel; int firstMessage = 1; @@ -203,31 +202,23 @@ void main(int argc,char *argv[]) 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); - } + sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,64.0); + if (writeFileOut) { } - 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); - } + 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_: diff --git a/MIDIIO.cpp b/MIDIIO.cpp index 5aa2123..696e9a8 100644 --- a/MIDIIO.cpp +++ b/MIDIIO.cpp @@ -163,6 +163,7 @@ int MIDIIO :: nextMessage() #include #include #include +//#include int _seqfd; diff --git a/Makefile b/Makefile index 286e3a4..01578a2 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ OS = $(shell uname) O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \ - RawWave.o RawWvIn.o RawLoop.o \ + RawWave.o RawShot.o RawLoop.o RawInterp.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 \ @@ -43,6 +43,7 @@ ifeq ($(OS),Linux) # These are for Linux CC = gcc -O3 # -g -pg -O3 O_FILES += RTWvOut.o RTSoundIO.o MIDIIO.o LIBRARY = -lpthread -lm +# LIBRARY = /lib/libpthread.so.0 -lm endif .SUFFIXES: .cpp diff --git a/Makefile.NeXT b/Makefile.NeXT index 4c9a89c..e949ed7 100644 --- a/Makefile.NeXT +++ b/Makefile.NeXT @@ -1,7 +1,7 @@ # STK98 Makefile - NeXTStep solo version O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \ - RawWave.o RawWvIn.o RawLoop.o \ + RawWave.o RawShot.o RawLoop.o RawInterp.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 \ diff --git a/Makefile.linux b/Makefile.linux index abc97ea..387724f 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -1,7 +1,7 @@ # STK98 Makefile - Linux solo version O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \ - RawWave.o RawWvIn.o RawLoop.o \ + RawWave.o RawShot.o RawLoop.o RawInterp.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 \ diff --git a/Makefile.sgi b/Makefile.sgi index d519d27..ad5d647 100644 --- a/Makefile.sgi +++ b/Makefile.sgi @@ -1,7 +1,7 @@ # STK98 Makefile - SGI solo version O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \ - RawWave.o RawWvIn.o RawLoop.o \ + RawWave.o RawShot.o RawLoop.o RawInterp.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 \ diff --git a/Mandolin.cpp b/Mandolin.cpp index d69ec54..8def25e 100644 --- a/Mandolin.cpp +++ b/Mandolin.cpp @@ -21,28 +21,28 @@ Mandolin :: Mandolin(MY_FLOAT lowestFreq) : Plucked2(lowestFreq) { - int i; + 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; + soundfile[0] = new RawInterp("rawwaves/mand1.raw"); + soundfile[1] = new RawInterp("rawwaves/mand2.raw"); + soundfile[2] = new RawInterp("rawwaves/mand3.raw"); + soundfile[3] = new RawInterp("rawwaves/mand4.raw"); + soundfile[4] = new RawInterp("rawwaves/mand5.raw"); + soundfile[5] = new RawInterp("rawwaves/mand6.raw"); + soundfile[6] = new RawInterp("rawwaves/mand7.raw"); + soundfile[7] = new RawInterp("rawwaves/mand8.raw"); + soundfile[8] = new RawInterp("rawwaves/mand9.raw"); + soundfile[9] = new RawInterp("rawwaves/mand10.raw"); + soundfile[10] = new RawInterp("rawwaves/mand11.raw"); + soundfile[11] = new RawInterp("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() @@ -50,28 +50,29 @@ Mandolin :: ~Mandolin() } void Mandolin :: pluck(MY_FLOAT amplitude) -{ /* this function gets interesting here, */ - 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( - (MY_FLOAT) 0.5 * pluckPos * lastLength); /* Set Pick Position */ - /* which puts zeroes at pos*length */ - dampTime = (long) lastLength; /* See tick method below */ - waveDone = 0; +{ /* this function gets interesting here, */ + /* because pluck may be longer than */ + /* string length, so we just reset the */ + /* soundfile and add in the pluck in */ + /* the tick method. */ + soundfile[mic]->reset(); + pluckAmp = amplitude; + /* Set Pick Position which puts zeroes at pos*length */ + combDelay->setDelay((MY_FLOAT) 0.5 * pluckPos * lastLength); + dampTime = (long) lastLength; /* See tick method below */ + waveDone = 0; } void Mandolin :: pluck(MY_FLOAT amplitude, MY_FLOAT position) { - pluckPos = position; /* pluck position is zeroes at pos*length */ - this->pluck(amplitude); + pluckPos = position; /* pluck position is zeroes at pos*length */ + this->pluck(amplitude); } void Mandolin :: noteOn(MY_FLOAT freq, MY_FLOAT amp) { - this->setFreq(freq); - this->pluck(amp); + this->setFreq(freq); + this->pluck(amp); #if defined(_debug_) printf("Mandolin : NoteOn: Freq=%lf Amp=%lf\n",freq,amp); #endif @@ -79,66 +80,64 @@ void Mandolin :: noteOn(MY_FLOAT freq, MY_FLOAT amp) void Mandolin :: setBodySize(MY_FLOAT size) { - int i; - for (i=0;i<12;i++) { - soundfile[i]->setRate(size); - } + int i; + for (i=0;i<12;i++) { + soundfile[i]->setRate(size); + } } MY_FLOAT Mandolin :: tick() { - MY_FLOAT temp = (MY_FLOAT) 0; - if (!waveDone) { - 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 */ - dampTime -= 1; /* overflow on replucking */ - lastOutput = delayLine->tick( /* Calculate 1st delay */ - filter->tick( /* filterered reflection */ - temp + /* plus pluck excitation */ - (delayLine->lastOut() * (MY_FLOAT) 0.7))); - lastOutput += delayLine2->tick( /* and 2nd delay */ - filter2->tick( /* just like the 1st */ - temp + - (delayLine2->lastOut() * (MY_FLOAT) 0.7))); /* that's the whole thing!! */ - } - else { /* No damping hack after 1 period */ - lastOutput = delayLine->tick( /* Calculate 1st delay */ - filter->tick( /* filtered reflection */ - temp + /* plus pluck excitation */ - (delayLine->lastOut() - * loopGain))); - lastOutput += delayLine2->tick( /* and 2nd delay */ - filter2->tick( /* just like the 1st */ - temp + - (delayLine2->lastOut() - * loopGain))); - } - lastOutput *= (MY_FLOAT) 0.3 / 32768.0; - return lastOutput; + MY_FLOAT temp = (MY_FLOAT) 0; + if (!waveDone) { + 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 */ + dampTime -= 1; /* overflow on replucking */ + lastOutput = delayLine->tick( /* Calculate 1st delay */ + filter->tick( /* filterered reflection */ + temp + /* plus pluck excitation */ + (delayLine->lastOut() * (MY_FLOAT) 0.7))); + lastOutput += delayLine2->tick( /* and 2nd delay */ + filter2->tick( /* just like the 1st */ + temp + + (delayLine2->lastOut() * (MY_FLOAT) 0.7))); /* that's the whole thing!! */ + } + else { /* No damping hack after 1 period */ + lastOutput = delayLine->tick( /* Calculate 1st delay */ + filter->tick( /* filtered reflection */ + temp + /* plus pluck excitation */ + (delayLine->lastOut() * loopGain))); + lastOutput += delayLine2->tick( /* and 2nd delay */ + filter2->tick( /* just like the 1st */ + temp + + (delayLine2->lastOut() * loopGain))); + } + lastOutput *= (MY_FLOAT) 0.3 / 32768.0; + return lastOutput; } void Mandolin :: controlChange(int number, MY_FLOAT value) { #if defined(_debug_) - printf("Mandolin : ControlChange: Number=%i Value=%f\n",number,value); + printf("Mandolin : ControlChange: Number=%i Value=%f\n",number,value); #endif - 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!! %i\n",number); - } + 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!! %i\n",number); + } } diff --git a/Mandolin.h b/Mandolin.h index 86a46e6..58f3381 100644 --- a/Mandolin.h +++ b/Mandolin.h @@ -20,12 +20,12 @@ #define __Mandolin_h #include "Plucked2.h" -#include "RawWave.h" +#include "RawInterp.h" class Mandolin : public Plucked2 { protected: - RawWave *soundfile[12]; + RawInterp *soundfile[12]; MY_FLOAT directBody; int mic; long dampTime; diff --git a/Marimba.cpp b/Marimba.cpp index 7146fb6..eca6d5c 100644 --- a/Marimba.cpp +++ b/Marimba.cpp @@ -13,7 +13,7 @@ Marimba :: Marimba() : Modal4() { - wave = new RawWave("rawwaves/marmstk1.raw"); + wave = new RawInterp("rawwaves/marmstk1.raw"); wave->normalize(); wave->setRate((MY_FLOAT) 0.5); /* normal stick */ this->setRatioAndReson(0, (MY_FLOAT) 1.00,(MY_FLOAT) 0.9996); /* Set all 132.0 */ @@ -105,7 +105,7 @@ void Marimba :: controlChange(int number, MY_FLOAT value) MY_FLOAT Marimba :: tick() { if (multiStrike>0) - if (wave->isAllDone()) { + if (wave->isFinished()) { wave->reset(); multiStrike -= 1; } diff --git a/Modal4.h b/Modal4.h index c684759..1737757 100644 --- a/Modal4.h +++ b/Modal4.h @@ -11,7 +11,7 @@ #include "Instrmnt.h" #include "Envelope.h" -#include "RawWave.h" +#include "RawInterp.h" #include "RawLoop.h" #include "BiQuad.h" #include "OnePole.h" @@ -20,7 +20,7 @@ class Modal4 : public Instrmnt { protected: Envelope *envelope; - RawWave *wave; + RawInterp *wave; BiQuad *filters[4]; OnePole *onepole; RawLoop *vibr; diff --git a/Moog1.cpp b/Moog1.cpp index 01b9c9b..f8bac75 100644 --- a/Moog1.cpp +++ b/Moog1.cpp @@ -14,7 +14,7 @@ Moog1 :: Moog1() : SamplFlt() { - attacks[0] = new RawWave("rawwaves/mandpluk.raw"); + attacks[0] = new RawInterp("rawwaves/mandpluk.raw"); loops[0] = new RawLoop("rawwaves/impuls20.raw"); loops[1] = new RawLoop("rawwaves/sinewave.raw"); /* Steal one for vibrato */ attacks[0]->normalize(); diff --git a/Object.h b/Object.h index 68aa4fb..241984d 100644 --- a/Object.h +++ b/Object.h @@ -22,6 +22,8 @@ class Object virtual ~Object(); }; +/* Uncomment your OS type below! */ + /* #define __OS_NeXT_ */ #define __OS_IRIX_ /* #define __OS_Linux_ */ @@ -58,21 +60,21 @@ class Object #define MAX_IN_STRINGS 25 /* SRATE here is 44100, others are derived accordingly */ - +/* #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 (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 @@ -81,7 +83,6 @@ class Object #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 (MY_FLOAT) 8000.0 diff --git a/Plucked.cpp b/Plucked.cpp index 565f270..20f9e99 100644 --- a/Plucked.cpp +++ b/Plucked.cpp @@ -11,74 +11,73 @@ Plucked :: Plucked(MY_FLOAT lowestFreq) { - length = (long) (SRATE / lowestFreq + 1); - loopGain = (MY_FLOAT) 0.999; - delayLine = new DLineA(length); - loopFilt = new OneZero; - pickFilt = new OnePole; - noise = new Noise; - this->clear(); + length = (long) (SRATE / lowestFreq + 1); + loopGain = (MY_FLOAT) 0.999; + delayLine = new DLineA(length); + loopFilt = new OneZero; + pickFilt = new OnePole; + noise = new Noise; + this->clear(); } Plucked :: ~Plucked() { - delete delayLine; - delete loopFilt; - delete pickFilt; - delete noise; + delete delayLine; + delete loopFilt; + delete pickFilt; + delete noise; } void Plucked :: clear() { - delayLine->clear(); - loopFilt->clear(); - pickFilt->clear(); + delayLine->clear(); + loopFilt->clear(); + pickFilt->clear(); } void Plucked :: setFreq(MY_FLOAT frequency) { - MY_FLOAT delay; - delay = (SRATE / frequency) - (MY_FLOAT) 0.5; /* length - delays */ - delayLine->setDelay(delay); - loopGain = (MY_FLOAT) 0.995 + (frequency * (MY_FLOAT) 0.000005); - if (loopGain>1.0) loopGain = (MY_FLOAT) 0.99999; + MY_FLOAT delay; + delay = (SRATE / frequency) - (MY_FLOAT) 0.5; /* length - delays */ + delayLine->setDelay(delay); + 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((MY_FLOAT) 0.999 - (amplitude * (MY_FLOAT) 0.15)); - pickFilt->setGain(amplitude * (MY_FLOAT) 0.5); - for (i=0;itick(delayLine->lastOut() * (MY_FLOAT) 0.6 /* fill delay with noise */ - + pickFilt->tick(noise->tick())); /* additively with current */ - /* contents */ + long i; + pickFilt->setPole((MY_FLOAT) 0.999 - (amplitude * (MY_FLOAT) 0.15)); + pickFilt->setGain(amplitude * (MY_FLOAT) 0.5); + for (i=0;itick(delayLine->lastOut() * (MY_FLOAT) 0.6 /* fill delay with noise */ + + pickFilt->tick(noise->tick())); /* additively with current */ + /* contents */ } void Plucked :: noteOn(MY_FLOAT freq, MY_FLOAT amp) { - this->setFreq(freq); - this->pluck(amp); + this->setFreq(freq); + this->pluck(amp); #if defined(_debug_) - printf("Plucked : NoteOn: Freq=%lf Amp=%lf\n",freq,amp); + printf("Plucked : NoteOn: Freq=%lf Amp=%lf\n",freq,amp); #endif } void Plucked :: noteOff(MY_FLOAT amp) { - loopGain = (MY_FLOAT) 1.0 - amp; + loopGain = (MY_FLOAT) 1.0 - amp; #if defined(_debug_) - printf("Plucked : NoteOff: Amp=%lf\n",amp); + printf("Plucked : NoteOff: Amp=%lf\n",amp); #endif } MY_FLOAT Plucked :: tick() { - lastOutput = delayLine->tick( /* check this out, */ - loopFilt->tick( /* here's the whole inner */ - delayLine->lastOut() /* loop of the instrument!! */ - * loopGain)); - lastOutput *= (MY_FLOAT) 3.0; - return lastOutput; + /* check this out */ + /* here's the whole inner loop of the instrument!! */ + lastOutput = delayLine->tick(loopFilt->tick(delayLine->lastOut() * loopGain)); + lastOutput *= (MY_FLOAT) 3.0; + return lastOutput; } diff --git a/Plucked2.cpp b/Plucked2.cpp index f3658ac..5de2d8c 100644 --- a/Plucked2.cpp +++ b/Plucked2.cpp @@ -11,80 +11,80 @@ Plucked2 :: Plucked2(MY_FLOAT lowestFreq) { - length = (long) (SRATE / lowestFreq + 1); - 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 = (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; + length = (long) (SRATE / lowestFreq + 1); + 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 = (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() { - delete delayLine; - delete delayLine2; - delete combDelay; - delete filter; - delete filter2; + delete delayLine; + delete delayLine2; + delete combDelay; + delete filter; + delete filter2; } void Plucked2 :: clear() { - delayLine->clear(); - delayLine2->clear(); - combDelay->clear(); - filter->clear(); - filter2->clear(); + delayLine->clear(); + delayLine2->clear(); + combDelay->clear(); + filter->clear(); + filter2->clear(); } void Plucked2 :: setFreq(MY_FLOAT frequency) { - lastFreq = frequency; - lastLength = ((MY_FLOAT) SRATE / lastFreq); /* length - delays */ - delayLine->setDelay((lastLength / detuning) - (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; + lastFreq = frequency; + lastLength = ((MY_FLOAT) SRATE / lastFreq); /* length - delays */ + 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) - (MY_FLOAT) 0.5); - delayLine2->setDelay((lastLength * detuning) - (MY_FLOAT) 0.5); + detuning = detune; + 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) { - lastFreq = frequency; - detuning = detune; - this->setFreq(frequency); + lastFreq = frequency; + detuning = detune; + this->setFreq(frequency); } void Plucked2 :: setPluckPos(MY_FLOAT position) { - pluckPos = position; + pluckPos = position; } void Plucked2 :: setBaseLoopGain(MY_FLOAT aGain) { - baseLoopGain = aGain; - loopGain = baseLoopGain + (lastFreq * (MY_FLOAT) 0.000005); - if (loopGain>1.0) loopGain = (MY_FLOAT) 0.99999; + baseLoopGain = aGain; + loopGain = baseLoopGain + (lastFreq * (MY_FLOAT) 0.000005); + if (loopGain>1.0) loopGain = (MY_FLOAT) 0.99999; } void Plucked2 :: noteOff(MY_FLOAT amp) { - loopGain = ((MY_FLOAT) 1.0 - amp) * (MY_FLOAT) 0.5; + loopGain = ((MY_FLOAT) 1.0 - amp) * (MY_FLOAT) 0.5; #if defined(_debug_) - printf("Plucked2 : NoteOff: Amp=%lf\n",amp); + printf("Plucked2 : NoteOff: Amp=%lf\n",amp); #endif } diff --git a/RTSoundIO.cpp b/RTSoundIO.cpp index d7f273c..a8ca982 100644 --- a/RTSoundIO.cpp +++ b/RTSoundIO.cpp @@ -205,12 +205,17 @@ RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels) HWND hWnd; DWORD dwDataLen; WAVEFORMATEX wfFormat; - DSBUFFERDESC dsbdDesc; + DSBUFFERDESC dsbdDesc, primarydsbDesc; + LPDIRECTSOUNDBUFFER m_pDSPrimeBuffer; BYTE *pDSBuffData; + /* Number of buffers of size RT_BUFFER_SIZE to make secondary DS buffer */ + int nBufs = 16; + /* Initialize pointers to NULL */ m_pDirectSound = NULL; m_pDSBuffer = NULL; + m_pDSPrimeBuffer = NULL; /* Create the DS object */ if ((result = DirectSoundCreate(NULL, &m_pDirectSound, NULL)) != DS_OK) @@ -225,8 +230,6 @@ RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels) exit(0); } - /* Initialize the DS buffer */ - /* Define the wave format structure */ wfFormat.wFormatTag = WAVE_FORMAT_PCM; wfFormat.nChannels = channels; @@ -236,15 +239,38 @@ RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels) wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign; wfFormat.cbSize = 0; - /* Setup the DS buffer description */ - m_cbBufSize = RT_BUFFER_SIZE * sizeof(short) * 8; + /* Setup the primary DS buffer description */ + ZeroMemory(&primarydsbDesc, sizeof(DSBUFFERDESC)); + primarydsbDesc.dwSize = sizeof(DSBUFFERDESC); + primarydsbDesc.dwFlags = DSBCAPS_PRIMARYBUFFER; + primarydsbDesc.dwBufferBytes = 0; + primarydsbDesc.lpwfxFormat = NULL; + + /* Create the primary DS buffer */ + if ((result = m_pDirectSound->CreateSoundBuffer(&primarydsbDesc, + &m_pDSPrimeBuffer, NULL)) != DS_OK) + { + fprintf(stderr,"Cannot get the primary DS buffer address!\n"); + exit(0); + } + + /* Set the primary DS buffer sound format. We have to do this because + the default primary buffer is 8-bit, 22kHz! */ + if ((result = m_pDSPrimeBuffer->SetFormat(&wfFormat)) != DS_OK) + { + fprintf(stderr,"Cannot set the primary DS buffer to proper sound format!\n"); + exit(0); + } + + /* Setup the secondary DS buffer description */ + m_cbBufSize = RT_BUFFER_SIZE * sizeof(short) * nBufs; ZeroMemory(&dsbdDesc, sizeof(DSBUFFERDESC)); dsbdDesc.dwSize = sizeof(DSBUFFERDESC); dsbdDesc.dwFlags = DSBCAPS_GLOBALFOCUS; dsbdDesc.dwBufferBytes = m_cbBufSize; dsbdDesc.lpwfxFormat = &wfFormat; - /* Create the DS buffer */ + /* Create the secondary DS buffer */ if ((result = m_pDirectSound->CreateSoundBuffer(&dsbdDesc, &m_pDSBuffer, NULL)) != DS_OK) { diff --git a/RawInterp.cpp b/RawInterp.cpp new file mode 100644 index 0000000..4320f56 --- /dev/null +++ b/RawInterp.cpp @@ -0,0 +1,245 @@ +/*******************************************/ +/* Interpolating RawWave Class, */ +/* by Perry R. Cook, 1995-96 */ +/* This object can open a raw 16bit data */ +/* (signed integers) file, and play back */ +/* the data once or looping, with linear */ +/* interpolation on playback. */ +/* */ +/* Made inherited from RawWave */ +/* by Gary P. Scavone (11/11/98) */ +/*******************************************/ + +#include "RawInterp.h" + +#ifdef __LITTLE_ENDIAN__ + #include "swapstuf.h" +#endif + +RawInterp :: RawInterp(char *fileName) +{ + long i; + short temp; + FILE *fd; + fd = fopen(fileName,"rb"); + if (!fd) { + printf("Couldn't find soundfile %s !!!!!!!!\n",fileName); + exit(0); + } + i = 0; + while (fread(&temp,2,1,fd)) i++; + + length = i; + fseek(fd,0,0); + data = (MY_FLOAT *) malloc(MY_FLOAT_SIZE * (length + 1)); + myData = 1; + i = 0; + while (fread(&temp,2,1,fd)) { +#ifdef __LITTLE_ENDIAN__ + temp = SwapShort (temp); +#endif + data[i] = temp; + i++; + } + data[length] = data[length-1]; + fclose(fd); + looping = 0; + time = (MY_FLOAT) 0.0; + phaseOffset = (MY_FLOAT) 0.0; + rate = (MY_FLOAT) 1.0; + finished = 0; +} + +RawInterp :: RawInterp(MY_FLOAT *someData, long aLength) +{ + + length = aLength; + data = someData; + myData = 0; + looping = 0; + time = (MY_FLOAT) 0.0; + phaseOffset = (MY_FLOAT) 0.0; + rate = (MY_FLOAT) 1.0; +} + +RawInterp :: ~RawInterp() +{ + if (myData) { + free(data); + data = 0; + } +} + +void RawInterp :: reset() +{ + time = (MY_FLOAT) 0.0; + lastOutput = (MY_FLOAT) 0.0; + finished = 0; +} + +void RawInterp :: normalize() +{ + this->normalize((MY_FLOAT) 1.0); +} + +void RawInterp :: normalize(MY_FLOAT newPeak) +{ + long i; + MY_FLOAT max = (MY_FLOAT) 0.0; + for (i=0;i<=length;i++) + if (fabs(data[i]) > max) + max = (MY_FLOAT) fabs(data[i]); + if (max > 0.0) { + max = (MY_FLOAT) 1.0 / max; + max *= newPeak; + for (i=0;i<=length;i++) + data[i] *= max; + } +} + +void RawInterp :: setRate(MY_FLOAT aRate) +{ + rate = aRate; +} + +void RawInterp :: setFreq(MY_FLOAT aFreq) +{ + rate = length * (MY_FLOAT) ONE_OVER_SRATE * aFreq; +} + +void RawInterp :: addTime(MY_FLOAT aTime) /* Add an absolute time */ +{ /* in samples */ + time += aTime; +} + +void RawInterp :: addPhase(MY_FLOAT anAngle) /* Add a time in cycles */ +{ /* Cycles here means */ + time += length * anAngle; /* 1.0 = length */ +} + +void RawInterp :: addPhaseOffset(MY_FLOAT anAngle) +{ /* Add a phase offset */ + phaseOffset = length * anAngle; /* in cycles, where */ +} /* 1.0 = length */ + +void RawInterp :: setLooping(int aLoopStatus) +{ + time = (MY_FLOAT) 0; + looping = aLoopStatus; + if (looping) data[length] = data[0]; +} + +long RawInterp :: getLength() +{ + return length; +} + +MY_FLOAT* RawInterp :: getData() +{ + return data; +} + +MY_FLOAT RawInterp :: tick() +{ + this->informTick(); + return lastOutput; +} + +int RawInterp :: isFinished() +{ + return finished; +} + +int RawInterp :: informTick() +{ + long temp; + + MY_FLOAT temp_time, alpha; + + time += rate; /* Update current time */ + + if (looping) { + while (time >= length) /* Check for end of sound */ + time -= length; /* loop back to beginning */ + while (time < 0.0) /* Check for end of sound */ + time += length; /* loop back to beginning */ + } + else { + if (time >= length) { /* Check for end of sound */ + time = length-(MY_FLOAT) 1; /* stick at end */ + finished = 1; /* Information for one-shot use */ + } + else if (time < 0.0) /* Check for end of sound */ + time = (MY_FLOAT) 0.0; /* stick at beg */ + } + + temp_time = time; + + if (phaseOffset != 0.0) { + temp_time += phaseOffset; /* Add phase offset */ + if (looping) { + while (temp_time >= length) /* Check for end of sound */ + temp_time -= length; /* loop back to beginning */ + while (temp_time < 0.0) /* Check for end of sound */ + temp_time += length; /* loop back to beginning */ + } + else { + if (temp_time >= length) /* Check for end of sound */ + temp_time = length - (MY_FLOAT) 1; /* stick at end */ + else if (temp_time < 0.0) /* check for end of sound */ + temp_time = (MY_FLOAT) 0.0; /* stick at beg */ + } + } + + temp = (long) temp_time; /* Integer part of time address */ + alpha = temp_time - (MY_FLOAT) temp; /* fractional part of time address */ + lastOutput = data[temp]; /* Do linear interpolation */ + lastOutput = lastOutput + /* same as alpha*data[temp+1] */ + (alpha * (data[temp+1] - + lastOutput)); /* + (1-alpha)data[temp] */ + + return finished; +} + +MY_FLOAT RawInterp :: lastOut() +{ + return lastOutput; +} + +/************ Test Main Program *****************/ +/* +void main() +{ + RawInterp loopWave("rawwaves/sinewave.raw"); + RawInterp oneShot("rawwaves/mandpluk.raw"); + FILE *fd; + short data; + long i; + + loopWave.setLooping(1); + loopWave.setFreq(5500); + fd = fopen("test.raw","wb"); + for (i=0;i<4096;i++) { + data = loopWave.tick(); + fwrite(&data,2,1,fd); + } + loopWave.setFreq(2750); + for (i=0;i<4096;i++) { + data = loopWave.tick(); + fwrite(&data,2,1,fd); + } + + oneShot.setLooping(0); + for (i=0;i<8192;i++) { + data = oneShot.tick(); + fwrite(&data,2,1,fd); + } + oneShot.reset(); + oneShot.setRate(0.5); + for (i=0;i<16384;i++) { + data = oneShot.tick(); + fwrite(&data,2,1,fd); + } + fclose(fd); +} +*/ diff --git a/RawInterp.h b/RawInterp.h new file mode 100644 index 0000000..0860f0d --- /dev/null +++ b/RawInterp.h @@ -0,0 +1,52 @@ +/*******************************************/ +/* Interpolating RawWave Class, */ +/* by Perry R. Cook, 1995-96 */ +/* This object can open a raw 16bit data */ +/* (signed integers) file, and play back */ +/* the data once or looping, with linear */ +/* interpolation on playback. */ +/* */ +/* Made inherited from RawWave */ +/* by Gary P. Scavone (11/11/98) */ +/*******************************************/ + +#if !defined(__RawInterp_h) +#define __RawInterp_h + +#include "Object.h" +#include "RawWave.h" + +class RawInterp : public RawWave +{ + protected: + int looping; + int myData; + int finished; + long length; + MY_FLOAT *data; + MY_FLOAT rate; + MY_FLOAT time; + MY_FLOAT phaseOffset; + MY_FLOAT lastOutput; + public: + RawInterp(char *fileName); + RawInterp(MY_FLOAT *someData,long aLength); + ~RawInterp(); + void reset(); + void normalize(); + void normalize(MY_FLOAT newPeak); + void setRate(MY_FLOAT aRate); + void setFreq(MY_FLOAT aFreq); + void addTime(MY_FLOAT aTime); + void addPhase(MY_FLOAT anAngle); + void addPhaseOffset(MY_FLOAT anAngle); + void setLooping(int aLoopStatus); + int isFinished(); + long getLength(); + MY_FLOAT* getData(); + MY_FLOAT tick(); + int informTick(); + MY_FLOAT lastOut(); +}; + +#endif diff --git a/RawLoop.cpp b/RawLoop.cpp index 19c69d3..4d956fc 100644 --- a/RawLoop.cpp +++ b/RawLoop.cpp @@ -1,4 +1,3 @@ - /*******************************************/ /* Raw Looped Soundfile Class, */ /* by Perry R. Cook, 1995-96 */ @@ -14,121 +13,121 @@ RawLoop :: RawLoop(char *fileName) { - long i; - short temp; - FILE *fd; - fd = fopen(fileName,"rb"); - if (!fd) { - printf("Couldn't find soundfile %s !!!!!!!!\n",fileName); - exit(0); - } - i = 0; - while (fread(&temp,2,1,fd)) i++; - length = i; - fseek(fd,0,0); - data = (MY_FLOAT *) malloc(MY_FLOAT_SIZE * (length + 1)); - i = 0; - while (fread(&temp,2,1,fd)) { - #ifdef __LITTLE_ENDIAN__ - temp = SwapShort (temp); - #endif - data[i] = temp; - i++; - } - data[length] = data[0]; - fclose(fd); - time = (MY_FLOAT) 0.0; - phaseOffset = (MY_FLOAT) 0.0; - rate = (MY_FLOAT) 1.0; + 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)) { +#ifdef __LITTLE_ENDIAN__ + temp = SwapShort (temp); +#endif + data[i] = temp; + i++; + } + data[length] = data[0]; + fclose(fd); + time = (MY_FLOAT) 0.0; + phaseOffset = (MY_FLOAT) 0.0; + rate = (MY_FLOAT) 1.0; } RawLoop :: ~RawLoop() { - free(data); + free(data); } void RawLoop :: reset() { - time = (MY_FLOAT) 0.0; - lastOutput = (MY_FLOAT) 0.0; + time = (MY_FLOAT) 0.0; + lastOutput = (MY_FLOAT) 0.0; } void RawLoop :: normalize() { - this->normalize((MY_FLOAT) 1.0); + this->normalize((MY_FLOAT) 1.0); } void RawLoop :: normalize(MY_FLOAT newPeak) { - long i; - MY_FLOAT max = (MY_FLOAT) 0.0; - for (i=0;i<=length;i++) - if (fabs(data[i]) > max) + long i; + MY_FLOAT max = (MY_FLOAT) 0.0; + for (i=0;i<=length;i++) + if (fabs(data[i]) > max) max = (MY_FLOAT) fabs((double) data[i]); - if (max > 0.0) { - max = (MY_FLOAT) 1.0 / max; - max *= newPeak; - for (i=0;i<=length;i++) + if (max > 0.0) { + max = (MY_FLOAT) 1.0 / max; + max *= newPeak; + for (i=0;i<=length;i++) data[i] *= max; - } + } } void RawLoop :: setRate(MY_FLOAT aRate) { - rate = aRate; + rate = aRate; } void RawLoop :: setFreq(MY_FLOAT aFreq) { - rate = length * ONE_OVER_SRATE * aFreq; + rate = length * ONE_OVER_SRATE * aFreq; } void RawLoop :: addTime(MY_FLOAT aTime) /* Add an absolute time */ { /* in samples */ - time += aTime; + time += aTime; } void RawLoop :: addPhase(MY_FLOAT anAngle) /* Add a time in cycles */ { /* Cycles here means */ - time += length * anAngle; /* 1.0 = length */ + time += length * anAngle; /* 1.0 = length */ } void RawLoop :: addPhaseOffset(MY_FLOAT anAngle) -{ /* Add a phase offset */ - phaseOffset = length * anAngle; /* in cycles, where */ -} /* 1.0 = length */ +{ /* Add a phase offset */ + phaseOffset = length * anAngle; /* in cycles, where */ +} /* 1.0 = length */ MY_FLOAT RawLoop :: tick() { - long temp; + long temp; - MY_FLOAT temp_time, alpha; + MY_FLOAT temp_time, alpha; - time += rate; /* Update current time */ + time += rate; /* Update current time */ - while (time >= length) /* Check for end of sound */ - time -= length; /* loop back to beginning */ - while (time < 0.0) /* Check for end of sound */ - time += length; /* loop back to beginning */ + while (time >= length) /* Check for end of sound */ + time -= length; /* loop back to beginning */ + while (time < 0.0) /* Check for end of sound */ + time += length; /* loop back to beginning */ - temp_time = time; + temp_time = time; - if (phaseOffset != 0.0) { - temp_time += phaseOffset; /* Add phase offset */ - while (temp_time >= length) /* Check for end of sound */ + if (phaseOffset != 0.0) { + temp_time += phaseOffset; /* Add phase offset */ + while (temp_time >= length) /* Check for end of sound */ temp_time -= length; /* loop back to beginning */ - while (temp_time < 0.0) /* Check for end of sound */ + while (temp_time < 0.0) /* Check for end of sound */ temp_time += length; /* loop back to beginning */ - } + } - temp = (long) temp_time; /* Integer part of time address */ - alpha = temp_time - (MY_FLOAT) temp; /* fractional part of time address */ - lastOutput = data[temp]; /* Do linear interpolation */ - lastOutput = lastOutput + /* same as alpha*data[temp+1] */ - (alpha * (data[temp+1] - - lastOutput)); /* + (1-alpha)data[temp] */ + temp = (long) temp_time; /* Integer part of time address */ + alpha = temp_time - (MY_FLOAT) temp; /* fractional part of time address */ + lastOutput = data[temp]; /* Do linear interpolation */ + lastOutput = lastOutput + /* same as alpha*data[temp+1] */ + (alpha * (data[temp+1] + - lastOutput)); /* + (1-alpha)data[temp] */ - return lastOutput; + return lastOutput; } MY_FLOAT RawLoop :: lastOut() diff --git a/RawLoop.h b/RawLoop.h index 0cab42d..7eb2b9b 100644 --- a/RawLoop.h +++ b/RawLoop.h @@ -11,8 +11,9 @@ #define __RawLoop_h #include "Object.h" +#include "RawWave.h" -class RawLoop : public Object +class RawLoop : public RawWave { protected: long length; diff --git a/RawWvIn.cpp b/RawShot.cpp similarity index 65% rename from RawWvIn.cpp rename to RawShot.cpp index 8e02693..d16a946 100644 --- a/RawWvIn.cpp +++ b/RawShot.cpp @@ -1,5 +1,5 @@ /*******************************************/ -/* NonInterpolating One-Shot Raw Sound- */ +/* Non-Interpolating 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 */ @@ -13,15 +13,17 @@ /* applications). */ /*******************************************/ -#include "RawWvIn.h" -#include "swapstuf.h" +#include "RawShot.h" -RawWvIn :: RawWvIn(char *fileName) +#ifdef __LITTLE_ENDIAN__ + #include "swapstuf.h" +#endif + +RawShot :: RawShot(char *fileName) { long i; - + strcpy(fileNm,fileName); - myFile = fopen(fileNm,"rb"); if (!myFile) { printf("Couldn't find soundfile %s !!!!!!!!\n",fileName); @@ -32,6 +34,7 @@ RawWvIn :: RawWvIn(char *fileName) while (fread(&data,2,1,myFile)) i++; length = i; fseek(myFile,0,0); + time = (MY_FLOAT) 0.0; rate = (MY_FLOAT) 1.0; lastTime = 0; @@ -40,12 +43,12 @@ RawWvIn :: RawWvIn(char *fileName) lastOutput = (MY_FLOAT) 0.0; } -RawWvIn :: ~RawWvIn() +RawShot :: ~RawShot() { this->finish(); } -void RawWvIn :: reset() +void RawShot :: reset() { if (finished) { myFile = fopen(fileNm,"rb"); @@ -62,19 +65,17 @@ void RawWvIn :: reset() lastOutput = (MY_FLOAT) 0.0; } -void RawWvIn :: normalize() +void RawShot :: normalize() { this->normalize((MY_FLOAT) 1.0); } -void RawWvIn :: normalize(MY_FLOAT newPeak) +void RawShot :: normalize(MY_FLOAT newPeak) { long i; FILE *fd; - extern short SwapShort(short); gain = (MY_FLOAT) 0.0; - fd = fopen(fileNm,"rb"); for (i=0;i gain) gain = (MY_FLOAT) fabs((double) data); } - if (gain > 0.0) { + if (gain > 0.0) { gain = newPeak / gain; } fclose(fd); } -void RawWvIn :: setRate(MY_FLOAT aRate) +void RawShot :: setRate(MY_FLOAT aRate) { rate = aRate; } -void RawWvIn :: finish() +void RawShot :: finish() { finished = 1; lastOutput = (MY_FLOAT) 0.0; @@ -105,47 +106,47 @@ void RawWvIn :: finish() } } -MY_FLOAT RawWvIn :: tick() +int RawShot :: isFinished() +{ + return finished; +} + +MY_FLOAT RawShot :: tick() { this->informTick(); return lastOutput; } -int RawWvIn :: informTick() +int RawShot :: informTick() { long temp; - extern short SwapShort(short); - if (!finished) - { - time += rate; /* Update current time */ - - 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 - { - 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 */ + if (!finished) { + time += rate; /* Update current time */ + + 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 { + 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 */ #ifdef __LITTLE_ENDIAN__ - data = SwapShort(data); + data = SwapShort(data); #endif - lastOutput = data * gain; /* And save as non-interpolated data */ - } - } - } + lastOutput = data * gain; /* And save as non-interpolated data */ + } + } + } return finished; } -MY_FLOAT RawWvIn :: lastOut() +MY_FLOAT RawShot :: lastOut() { return lastOutput; } @@ -154,7 +155,7 @@ MY_FLOAT RawWvIn :: lastOut() /* void main() { - RawWvIn oneShot("rawwaves/mandpluk.raw"); + RawShot oneShot("rawwaves/mandpluk.raw"); FILE *fd; short data; long i; diff --git a/RawWvIn.h b/RawShot.h similarity index 83% rename from RawWvIn.h rename to RawShot.h index 49c59cd..f36d9d4 100644 --- a/RawWvIn.h +++ b/RawShot.h @@ -1,5 +1,5 @@ /*******************************************/ -/* NonInterpolating One-Shot Raw Sound- */ +/* Non-Interpolating 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 */ @@ -13,12 +13,13 @@ /* applications). */ /*******************************************/ -#if !defined(__RawWvIn_h) -#define __RawWvIn_h +#if !defined(__RawShot_h) +#define __RawShot_h #include "Object.h" +#include "RawWave.h" -class RawWvIn : public Object +class RawShot : public RawWave { protected: long length; @@ -32,13 +33,14 @@ class RawWvIn : public Object MY_FLOAT gain; MY_FLOAT lastOutput; public: - RawWvIn(char *fileName); - ~RawWvIn(); + RawShot(char *fileName); + ~RawShot(); void reset(); void normalize(); void normalize(MY_FLOAT newPeak); void setRate(MY_FLOAT aRate); void finish(); + int isFinished(); MY_FLOAT tick(); int informTick(); MY_FLOAT lastOut(); diff --git a/RawWave.cpp b/RawWave.cpp index 048cf4c..915f141 100644 --- a/RawWave.cpp +++ b/RawWave.cpp @@ -1,241 +1,42 @@ -/*******************************************/ -/* Raw Soundfile Class, */ -/* by Perry R. Cook, 1995-96 */ -/* This Object can open a raw 16bit data */ -/* (signed integers) file, and play back */ -/* the data once or looping, with linear */ -/* interpolation on playback. */ -/*******************************************/ +/********************************************/ +/* RawWave Abstract Class, */ +/* by Gary P. Scavone, 1998 */ +/********************************************/ #include "RawWave.h" -#include "swapstuf.h" - -RawWave :: RawWave(char *fileName) +RawWave :: RawWave() { - long i; - short temp; - FILE *fd; - fd = fopen(fileName,"rb"); - if (!fd) { - printf("Couldn't find soundfile %s !!!!!!!!\n",fileName); - exit(0); - } - i = 0; - while (fread(&temp,2,1,fd)) i++; - - length = i; - fseek(fd,0,0); - data = (MY_FLOAT *) malloc(MY_FLOAT_SIZE * (length + 1)); - myData = 1; - i = 0; - while (fread(&temp,2,1,fd)) { - #ifdef __LITTLE_ENDIAN__ - temp = SwapShort (temp); - #endif - data[i] = temp; - i++; - } - data[length] = data[length-1]; - fclose(fd); - looping = 0; - time = (MY_FLOAT) length; - phaseOffset = (MY_FLOAT) 0.0; - rate = (MY_FLOAT) 1.0; - allDone = 0; -} - -RawWave :: RawWave(MY_FLOAT *someData, long aLength) -{ - - length = aLength; - data = someData; - myData = 0; - looping = 0; - time = (MY_FLOAT) 0.0; - phaseOffset = (MY_FLOAT) 0.0; - rate = (MY_FLOAT) 1.0; } RawWave :: ~RawWave() { - if (myData) { - free(data); - data = 0; - } } void RawWave :: reset() { - time = (MY_FLOAT) 0.0; - lastOutput = (MY_FLOAT) 0.0; - allDone = 0; -} - -void RawWave :: normalize() -{ - this->normalize((MY_FLOAT) 1.0); } void RawWave :: normalize(MY_FLOAT newPeak) { - long i; - MY_FLOAT max = (MY_FLOAT) 0.0; - for (i=0;i<=length;i++) - if (fabs(data[i]) > max) - max = (MY_FLOAT) fabs(data[i]); - if (max > 0.0) { - max = (MY_FLOAT) 1.0 / max; - max *= newPeak; - for (i=0;i<=length;i++) - data[i] *= max; - } } void RawWave :: setRate(MY_FLOAT aRate) { - rate = aRate; -} - -void RawWave :: setFreq(MY_FLOAT aFreq) -{ - rate = length * (MY_FLOAT) ONE_OVER_SRATE * aFreq; -} - -void RawWave :: addTime(MY_FLOAT aTime) /* Add an absolute time */ -{ /* in samples */ - time += aTime; -} - -void RawWave :: addPhase(MY_FLOAT anAngle) /* Add a time in cycles */ -{ /* Cycles here means */ - time += length * anAngle; /* 1.0 = length */ -} - -void RawWave :: addPhaseOffset(MY_FLOAT anAngle) -{ /* Add a phase offset */ - phaseOffset = length * anAngle; /* in cycles, where */ -} /* 1.0 = length */ - -void RawWave :: setLooping(int aLoopStatus) -{ - time = (MY_FLOAT) 0; - looping = aLoopStatus; - if (looping) data[length] = data[0]; -} - -long RawWave :: getLength() -{ - return length; -} - -MY_FLOAT* RawWave :: getData() -{ - return data; -} - -MY_FLOAT RawWave :: tick() -{ - this->informTick(); - return lastOutput; -} - -int RawWave :: isAllDone() -{ - return allDone; } int RawWave :: informTick() { - long temp; - - MY_FLOAT temp_time, alpha; - - time += rate; /* Update current time */ - - if (looping) { - while (time >= length) /* Check for end of sound */ - time -= length; /* loop back to beginning */ - while (time < 0.0) /* Check for end of sound */ - time += length; /* loop back to beginning */ - } - else { - if (time >= length) { /* Check for end of sound */ - time = length-(MY_FLOAT) 1; /* stick at end */ - allDone = 1; /* Information for one-shot use */ - } - else if (time < 0.0) /* Check for end of sound */ - time = (MY_FLOAT) 0.0; /* stick at beg */ - } - - temp_time = time; - - if (phaseOffset != 0.0) { - temp_time += phaseOffset; /* Add phase offset */ - if (looping) { - while (temp_time >= length) /* Check for end of sound */ - temp_time -= length; /* loop back to beginning */ - while (temp_time < 0.0) /* Check for end of sound */ - temp_time += length; /* loop back to beginning */ - } - else { - if (temp_time >= length) /* Check for end of sound */ - temp_time = length - (MY_FLOAT) 1; /* stick at end */ - else if (temp_time < 0.0) /* check for end of sound */ - temp_time = (MY_FLOAT) 0.0; /* stick at beg */ - } - } + return 0; +} - temp = (long) temp_time; /* Integer part of time address */ - alpha = temp_time - (MY_FLOAT) temp; /* fractional part of time address */ - lastOutput = data[temp]; /* Do linear interpolation */ - lastOutput = lastOutput + /* same as alpha*data[temp+1] */ - (alpha * (data[temp+1] - - lastOutput)); /* + (1-alpha)data[temp] */ - - return allDone; +MY_FLOAT RawWave :: tick() +{ + return 0.0; } MY_FLOAT RawWave :: lastOut() { - return lastOutput; + return 0.0; } -/************ Test Main Program *****************/ -/* - -void main() -{ - RawWave loopWave("rawwaves/sinewave.raw"); - RawWave oneShot("rawwaves/mandpluk.raw"); - FILE *fd; - short data; - long i; - - loopWave.setLooping(1); - loopWave.setFreq(5500); - fd = fopen("test.raw","wb"); - for (i=0;i<4096;i++) { - data = loopWave.tick(); - fwrite(&data,2,1,fd); - } - loopWave.setFreq(2750); - for (i=0;i<4096;i++) { - data = loopWave.tick(); - fwrite(&data,2,1,fd); - } - - oneShot.setLooping(0); - for (i=0;i<8192;i++) { - data = oneShot.tick(); - fwrite(&data,2,1,fd); - } - oneShot.reset(); - oneShot.setRate(0.5); - for (i=0;i<16384;i++) { - data = oneShot.tick(); - fwrite(&data,2,1,fd); - } - fclose(fd); -} -*/ diff --git a/RawWave.h b/RawWave.h index 83cef3d..eef2a0e 100644 --- a/RawWave.h +++ b/RawWave.h @@ -1,48 +1,25 @@ -/*******************************************/ -/* Raw Soundfile Class, */ -/* by Perry R. Cook, 1995-96 */ -/* This Object can open a raw 16bit data */ -/* (signed integers) file, and play back */ -/* the data once or looping, with linear */ -/* interpolation on playback. */ -/*******************************************/ +/********************************************/ +/* RawWave Abstract Class, */ +/* by Gary P. Scavone, 1998 */ +/********************************************/ + +#include "Object.h" #if !defined(__RawWave_h) #define __RawWave_h -#include "Object.h" - class RawWave : public Object { - protected: - int looping; - int myData; - int allDone; - long length; - MY_FLOAT *data; - MY_FLOAT rate; - MY_FLOAT time; - MY_FLOAT phaseOffset; - MY_FLOAT lastOutput; public: - RawWave(char *fileName); - RawWave(MY_FLOAT *someData,long aLength); - ~RawWave(); - void reset(); - void normalize(); - void normalize(MY_FLOAT newPeak); - void setRate(MY_FLOAT aRate); - void setFreq(MY_FLOAT aFreq); - void addTime(MY_FLOAT aTime); - void addPhase(MY_FLOAT anAngle); - void addPhaseOffset(MY_FLOAT anAngle); - void setLooping(int aLoopStatus); - int isAllDone(); - long getLength(); - MY_FLOAT* getData(); - MY_FLOAT tick(); - int informTick(); - MY_FLOAT lastOut(); + RawWave(); + virtual ~RawWave(); + virtual void reset(); + virtual void normalize(MY_FLOAT newPeak); + virtual void setRate(MY_FLOAT aRate); + virtual int informTick(); + virtual MY_FLOAT tick(); + virtual MY_FLOAT lastOut(); }; -#endif + +#endif // defined(__RawWave_h) diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt new file mode 100644 index 0000000..26a7487 --- /dev/null +++ b/ReleaseNotes.txt @@ -0,0 +1,39 @@ +STK: A ToolKit of Audio Synthesis Classes and Instruments in C++ + +By Perry R. Cook, 1995-98 +and Gary P. Scavone, 1997-98 + +I'll call this latest release STK98v2.02. There was a v2.01 release shortly after the initial v2.0 release in July 1998, to correct a few SGI/Win return character incompatibilities. Since I am just creating this set of release notes with v2.02, I'll just gloss over the past changes. Hopefully, I'll be able to keep this document updated with future releases. + +--Gary Scavone + + +v2.02: +- 16 November 1998 +- created RawWave abstract class, with subclasses of RawLoop (looping rawwave oscillator), RawShot (non-looping, non-interpolating rawwave player ... used to be RawWvIn), and RawInterp (looping or non-looping, interpolating rawwave player ... used to be RawWave). +- modified DrumSynt to correctly handle sample rates different than 22050 Hz. +- modified syntmono parsing vs. tick routine so that some ticking occurs between each message. When multiple messages are waiting to be processed, the time between message updates is inversely proportional to the number of messages in the buffer. +- fixed DirectSound playback bug in Win distribution. Sound was being played at 8-bit, 22 kHz in all cases. Playback is now 16-bit and dependent on SRATE. +- fixed bug in MD2SKINI which prevented some NoteOff statements from being output. + + +v2.01: +- 27 July 1998 +- Corrected extraneous ^M line return characters that were incompatible with SGI. + + +v2.0: +- 20 July 1998 +- The first true release by Gary, with unified capabilities across SGI, Linux, and Win platforms. See WWW pages (http://www-ccrma.stanford.edu/CCRMA/Software/STK/) for more info. + + +v1.1: +- More linux support and other changes that happened so long ago that I can't remember anymore. Never officially released. + + +v1.0: +- Linux support added with the help of Tim Stilson. Never officially released. + + +v0.8: +- One of (if not THE) original distributions for SGI, NeXTStep, and basic Win support. I think this came out in 1996. \ No newline at end of file diff --git a/STK98v2.ncb b/STK98v2.ncb index d829cd6fc106d35df3513914f7fe918e84a3bf9c..08844988f414147cf946bf16efcb216e76bfb60e 100644 GIT binary patch delta 34080 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 literal 53760 zcmeHQ-I5!{86EB7jVv3-Hjd*M5(ekTkYELCAsB}^#F96WZFv<*Sp}kmjHI?!>}W=r zk+kt0FOXMAk>Ul&18@Vm4-b%3!5zgFm#GS5b3REek4KWxZn4I*b9(D&dV0R;ulsas zG<#~ko)7+c;={lF{p?3ZC|xm@jsNW&HdX@V3FHOCblkx4ogK;Rt>jU}6d?vaM_Wyd z+cNM7a0rkw{~C}44g)FR2q5G9D7MFduLGC@#tGmg@EC9k_y!<$-^BI|@Gamh@Hp@U z@NM8bz>|R3<*_{nd>8m0@O|J1z|Vk47r<2@3*>-nz#8yN;8%dy32q>N6DR<;fOVh<{2C|$ zWkBqHgY5=T1%3;>3cLpV4yXaY2gL4mZ2t&YKpkiRO+W#+ffgWk`<+ULi@%;>qUR2_ zo^c1B7f+`#V{{v3?%XeZ_@Bh%@4fSGLi(lcs_^a^TZV6R!9@f8H^F5O`QDHVZ8vXg z8cW0ZDsxxbG0!eoz9c&`S&^>7yK8L2zd~;J={Wo^<23o6Eb9NLxEcGuhEZ>$ufoD! z(lKKxA>UQ;EoqTDPK(jle*)ttd?Y)~jK9@(+E3&z*IJf$r&g}qcB{Icxz@JTMq6!@}o)3ucsvK^ML*@+oY}U1eb$61Z(Ciz*S{V1IKGJw6<7LobyeA6J}cYq zjM;+H8M9@hUH7c+W_YAF+;(Hl^*SMkQe3c{R;UUch*oF({ zbEfh<*L&K3=2_&oEzf}|_C$U${_)OWa$Wi$kpEX8|8XEcF%D%;EE#VZf7yf;nUOeo_Au z25Qv*wCGFyFDwgE|HJi%`rkfWgkxAG^}iSnI=f5;0t_Uf02Xdumq%OWHkA4w^}oRE zV3rJ!0WuJ82DCmCZx-15{bE4RFY15P|L%FfllmX^KR*ArUzgq3*Gv5`_EUfa#GHXy z@z+&EBs+*pmbmCIO6L%NEb9b}qK_AgKYmIo9mgN%5k;RjUPoMg4srZt;|BI_0gI-y z@IMR`#tDnYKmSN75Bc{I_b&189rW4(7ER(`_kB_SFU;`2sK2mX3bE9?_5bsL|7FB~ zPa?VxXKl;(@5VX@!=R7rXa%z&M(Tbs(oa=gZ_Dpm4P~AmhmoJZY-Y@^=SnCNVj4y@ zADh&98!^`78fO+RT4OTr+;(So;N-k8@3{vU{~exf+$RHMfDFWo0j zFY3S4f2sct=K$ls8UOvDF2Aw$L;W|lL(h(rfguC0zCU{K^Ne2Rak2*EI0)saJ}_GU zF==G6NTR5CbI+K2VAg_;Qug1;!l9?Nvq>xVv=Zc0E%#pua-J|q{f}P~GC&5%K)e~y z`b@l8VDI;f0X@H{|55*={zv_f>p$+-m6r7e8KC|bWP^D!5I+Vc`rqVHywFQqj_L!W zx4H!MKYd`L)s0oQxi4awrT+=zeE&=Q<{f)X2FL&zhynvzpNT?S*~aKGpywC$Kk9$f z|ET{_|BK!=Jc=!*{ujkjW1Gpqm&btC|CWuUerirCpM(StcjVn@qV{2Dc&{oSXLMm$ z{*yB#4%~6WN2vb^H%w%J43Ggb5ETZrJ`}J_^>-WgPi8t>NgsJ}qDP*1ukO4A41`a3#TAw?h-D9`DVg~g5qW(+$ zm-;XDU+TYK@dY_1?y3LAWT4qiGBAgM6yEv0Wv@a$Ut-%(E3btd%%`I%na!HMg5QZAN4=#f7JgT=BxF= zX&d#wgEN-w2^rW611rOm2Kc1@=b3o5O|#$V-S6Gjdm)+UkO4A42FO4p8PNJnBpc60 nKlBXf`9=MY`XBW_>VMS#9{Nl6foLH0zXLIh>;xIuGXwtzm+r;# diff --git a/Sampler.h b/Sampler.h index 6017b16..e6a7058 100644 --- a/Sampler.h +++ b/Sampler.h @@ -11,7 +11,7 @@ #include "Instrmnt.h" #include "ADSR.h" -#include "RawWave.h" +#include "RawInterp.h" #include "RawLoop.h" #include "OnePole.h" @@ -19,7 +19,7 @@ class Sampler : public Instrmnt { protected: ADSR *adsr; - RawWave *attacks[5]; + RawInterp *attacks[5]; RawLoop *loops[5]; OnePole *filter; MY_FLOAT baseFreq; diff --git a/Vibraphn.cpp b/Vibraphn.cpp index af57be6..0a15541 100644 --- a/Vibraphn.cpp +++ b/Vibraphn.cpp @@ -13,7 +13,7 @@ Vibraphn :: Vibraphn() : Modal4() { - wave = new RawWave("rawwaves/marmstk1.raw"); + wave = new RawInterp("rawwaves/marmstk1.raw"); wave->normalize(); wave->setRate((MY_FLOAT) 13.33); vibr->setFreq((MY_FLOAT) 4.0); diff --git a/hierarch.txt b/hierarch.txt index 9490643..d46a292 100644 --- a/hierarch.txt +++ b/hierarch.txt @@ -13,17 +13,17 @@ SourcSink Filters Reverb Non-Lin ModalSyn FM Physical Sampling Ph Object-----------------------------------Instrmnt----------. | | | | | | | Envelope| Filter Reverb BowTabl | .------------------|---------------------. - | | | | JetTabl | | | | | | | | | -ADSR | OneZero PRCRev ReedTabl| Modal4 | FM4Op---.| | | | Shakers - | OnePole JCRev | | | | || | | | | - ._____| TwoZero NRev .____| Marimba | FM4Alg3 || Plucked Sampler | Maraca - | | TwoPole | Vibraphn| | || Clarinet | | Sekere -Noise | DCBlock LipFilt AgogoBel| HeavyMtl|| Brass SamplFlt| Cabasa - | | BiQuad | || Flute | | Bamboo -SubNoise| DlineL .____| .____|| Bowed Moog1 | Water Drops - | DLineA | | || | Tambourine - ._____| DLineN VoicForm FM4Alg4 ||____. | SleighBells - | | FormSwep | | | | Guiro + | | | | JetTabl | | | | | | | | | +ADSR | OneZero PRCRev ReedTabl| Modal4 | FM4Op---.| | | | Shakers + | OnePole JCRev | | | | || | | | | + ._____| TwoZero NRev .____| Marimba | FM4Alg3 || Plucked Sampler | Maraca + | | TwoPole | Vibraphn| | || Clarinet | | Sekere +Noise | DCBlock LipFilt AgogoBel| HeavyMtl|| Brass SamplFlt| Cabasa + | | BiQuad | || Flute | | Bamboo +SubNoise| DlineL .____| .____|| Bowed Moog1 | Water Drops + | DLineA | | || | Tambourine + ._____| DLineN VoicForm FM4Alg4 ||____. | SleighBells + | | FormSwep | | | | Guiro RawWave | PercFlut| Plucked2 | | | | | ._____| .____| Mandolin .____| @@ -63,7 +63,7 @@ Bowed.cpp Not Hideous Bowed String DlineL,BowTabl,OnePole,BiQuad,RawWave, Brass.cpp Not So Bad Brass Inst. DLineA,LipFilt,DCBlock,ADSR,RawLoop Clarinet.cpp Pretty Good Clarinet DLineL,ReedTabl,OneZero,Envelope,Noise,RawLoop Flute.cpp Pretty Good Flute JetTabl,DLineL,OnePole,DCBlock,Noise,ADSR,RawLoop -Modal4.cpp 4 Resonances Envelope,RawWave,RawLoop,BiQuad,OnePole +Modal4.cpp 4 Resonances Envelope,RawWave,RawLoop,BiQuad,OnePole Marimba.cpp <> Vibraphn.cpp <> Agogobel.cpp <> @@ -78,12 +78,12 @@ PercFlut.cpp Perc. Flute <> Rhodey.cpp Rhodes-Like Elec. Piano <> Wurley.cpp Wurlitz. Elec. Piano <> TubeBell.cpp Classic FM Bell <> -FMVoices.cpp 3-Formant Voice Synth. <> -BeeThree.cpp Cheezy Organ for Paul <> +FMVoices.cpp 3-Formant Voice Synth. <> +BeeThree.cpp Cheezy Organ for Paul <> Sampler.cpp Sampling Synth. 4 each ADSR, RawWave (att), RawLoop (loop), OnePole SamplFlt.cpp Sampler with Swept Filter <> Moog1.cpp Swept filter flavor of <> -VoicForm.cpp Source/Filter Voice Envelope,Noise,SingWave,FormSwep,OnePole,OneZero +VoicForm.cpp Source/Filter Voice Envelope,Noise,SingWave,FormSwep,OnePole,OneZero DrumSynt.cpp Drum Synthesizer bunch of RawWvIn, and OnePole Shakers.cpp Stochastic Event Models @@ -122,7 +122,7 @@ Filters: Filter.cpp Filter Master Class Reverb: Reverb.cpp Reverb Master Class PRCRev.cpp 2 series allpass units, 2 parallel comb filters JCRev.cpp 3 series allpass units, 4 parallel comb filters - NReb.cpp 6 parallel comb filters, 3 series allpass units, ... + NRev.cpp 6 parallel comb filters, 3 series allpass units, ... NonLin&Lookup: JetTabl.cpp Cubic Jet NonLinearity BowTabl.cpp 1/x^3-like Bow NonLinearity diff --git a/mus151/Debug/.placeholder b/mus151/Debug/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/mus151/GUITwoOsc b/mus151/GUITwoOsc new file mode 100755 index 0000000..8d76b11 --- /dev/null +++ b/mus151/GUITwoOsc @@ -0,0 +1 @@ +wish < tcl/TwoWaves.tcl | MUS151 TwoOsc -r \ No newline at end of file diff --git a/mus151/MUS151.cpp b/mus151/MUS151.cpp new file mode 100644 index 0000000..5662fa9 --- /dev/null +++ b/mus151/MUS151.cpp @@ -0,0 +1,312 @@ +/******** Psychoacoustic Interface Program for MUS151 ************/ +/******** Center for Computer Research in Music & Acoustics ******/ +/******** Stanford University, by Gary P. Scavone, 1998 **********/ + +#include "../miditabl.h" +#include "../WvOut.h" +#include "../RTWvOut.h" +#include "../SKINI11.h" +#include "TwoOsc.h" + +#include "../SKINI11.msg" + +#define INSTR_LEN 60 + +int numStrings = 0; +int notDone = 1; + +#if defined(__SGI_REALTIME_) + +#include +#include +#include + +char inputString[MAX_IN_STRINGS][INSTR_LEN]; +pid_t string_thread; + +void newString(void *) +{ + int inOne = 0; + while (notDone) { + fgets(inputString[inOne],INSTR_LEN,stdin); + if (inputString[inOne][0] == 'E' && inputString[inOne][1] == 'x') { + notDone = 0; + } + else { + numStrings++; + if (numStrings > MAX_IN_STRINGS) { + fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n"); + numStrings--; + } + inOne++; + if (inOne == MAX_IN_STRINGS) inOne = 0; + } + } +} + +#elif defined(__USS_REALTIME_) + +#include +//#include + +char inputString[MAX_IN_STRINGS][INSTR_LEN]; +pthread_t string_thread; + +void *newString(void *) +{ + int inOne = 0; + while (notDone) { + fgets(inputString[inOne],INSTR_LEN,stdin); + if (inputString[inOne][0] == 'E' && inputString[inOne][1] == 'x') { + notDone = 0; + } + else { + numStrings++; + if (numStrings > MAX_IN_STRINGS) { + fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n"); + numStrings--; + } + inOne++; + if (inOne == MAX_IN_STRINGS) inOne = 0; + } + } +} + +#elif (defined(__WINDS_REALTIME_) || defined(__WINMM_REALTIME_) ) + +#include +#include + +char inputString[MAX_IN_STRINGS][INSTR_LEN]; +unsigned long string_thread; + +#define SERVICE_PORT 2001 + +void newString(void *) +{ + int inOne = 0, i=0, m=0, n; + SOCKET soc_id, accept_id; + WSADATA wsaData; + int nRet; + struct sockaddr_in sockname; + WORD wVersionRequested = MAKEWORD(1,1); + char socBuf[INSTR_LEN]; + + nRet = WSAStartup(wVersionRequested, &wsaData); + if (wsaData.wVersion != wVersionRequested) + { + fprintf(stderr,"\n Wrong version\n"); + exit(0); + } + + /* Create the server-side socket */ + soc_id = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); + if(soc_id == INVALID_SOCKET) { + fprintf(stderr,"Couldn't create socket!\n"); + exit(0); + } + + sockname.sin_family=AF_INET; + sockname.sin_addr.s_addr=INADDR_ANY; + sockname.sin_port=htons(SERVICE_PORT); + + /* Bind socket to the appropriate port and interface (INADDR_ANY) */ + if (bind(soc_id,(LPSOCKADDR)&sockname,sizeof(sockname))==SOCKET_ERROR) { + fprintf(stderr,"Couldn't bind socket!\n"); + exit(0); + } + + /* Listen for incoming connections */ + printf("Listening for socket on port %d\n", SERVICE_PORT); + if (listen(soc_id,1)==SOCKET_ERROR) { + fprintf(stderr,"Couldn't set up listen on socket!\n"); + exit(0); + } + + /* Accept and service one incoming connection request */ + accept_id=accept(soc_id,NULL,NULL); + if (accept_id==INVALID_SOCKET) { + fprintf(stderr,"Couldn't accept incoming connection on socket!\n"); + exit(0); + } + + memset(socBuf, 0, sizeof(socBuf)); + + printf("Socket connection made ... ready to receive SKINI messages.\n"); + while (notDone) { + i = recv(accept_id, socBuf, INSTR_LEN, 0); + if (i==0) notDone = 0; + n = 0; + while (n < i) { + inputString[inOne][m++] = socBuf[n]; + if (socBuf[n++] == '\n') { + if (inputString[inOne][0] == 'E' && inputString[inOne][1] == 'x') { + notDone = 0; + n = i; + } + else { + m = 0; + numStrings++; + if (numStrings > MAX_IN_STRINGS) { + fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n"); + numStrings--; + } + inOne++; + if (inOne == MAX_IN_STRINGS) inOne = 0; + } + memset(inputString[inOne], 0, INSTR_LEN); + } + } + } + closesocket(accept_id); + closesocket(soc_id); + WSACleanup(); + printf("Socket connection closed.\n"); +} + +#else +char inputString[1][INSTR_LEN]; +#endif + +/* Error function in case of incorrect command-line argument specifications */ +void errorf(char *func) { + printf("\nuseage: %s Instr \n",func); + printf(" where Instr = TwoOsc (only one available for now)\n\n"); + exit(0); +} + +void main(int argc,char *argv[]) +{ + long i, j, synlength; + int type, rtInput = 0; + int outOne = 0; + char *fin; + MY_FLOAT settleTime = 0.5; /* in seconds */ + MY_FLOAT temp, byte3, lastPitch; + WvOut *output; + TwoOsc *instrument; + SKINI11 *score; + + if (argc > 1) { + if (!strcmp(argv[1],"TwoOsc")) instrument = new TwoOsc; + else errorf(argv[0]); + } else errorf(argv[0]); + + output = new RTWvOut(); + score = new SKINI11(); + + rtInput = 1; /* We're going to always use realtime input */ + + /* If using realtime input, setup the input thread. */ +#if defined(__SGI_REALTIME_) + if (rtInput) { + string_thread = sproc(newString, PR_SALL); + if (string_thread == -1) { + fprintf(stderr, "unable to create input thread...aborting.\n"); + exit(-1); + } + instrument->noteOn(200.0, 0.2); + } +#elif defined(__USS_REALTIME_) + if (rtInput) { + if (pthread_create(&string_thread, NULL, newString, NULL)) + { + fprintf(stderr, "unable to create input thread...aborting.\n"); + exit(-1); + } + instrument->noteOn(200.0,0.2); + } +#elif (defined(__WINDS_REALTIME_) || defined(__WINMM_REALTIME_) ) + if (rtInput) { + string_thread = _beginthread(newString, 0, NULL); + if (string_thread == -1) { + fprintf(stderr, "Unable to create exit thread.\n"); + printf("Exiting MD2SKINI process.\n"); + exit(0); + } + instrument->noteOn(200.0,0.2); + } +#endif + + /* Finally ... the runtime loop begins! */ + notDone = 1; + synlength = RT_BUFFER_SIZE; + while(notDone || numStrings) { + if (rtInput) { + if (numStrings > 1) synlength = (long) RT_BUFFER_SIZE / numStrings; + else synlength = RT_BUFFER_SIZE; + for ( i=0; itick(instrument->tick()); + } + } + else { + fin = fgets(inputString[0],INSTR_LEN,stdin); + if (fin == NULL) notDone = 0; + else { + numStrings++; + } + } + if (numStrings) { + score->parseThis(inputString[outOne]); + type = score->getType(); + if (type > 0) { + if (temp = score->getDelta()) { /* SKINI score file */ + synlength = (long) (temp * SRATE); + for ( i=0; itick(instrument->tick()); + } + synlength = 0; + } + if (type == __SK_NoteOn_ ) { + if (( byte3 = score->getByteThree() ) == 0) + instrument->noteOff(byte3*NORM_7); + else { + j = (int) score->getByteTwo(); + temp = __MIDI_To_Pitch[j]; + lastPitch = temp; + instrument->noteOn(temp,byte3*NORM_7); + } + } + else if (type == __SK_NoteOff_) { + byte3 = score->getByteThree(); + instrument->noteOff(byte3*NORM_7); + } + else if (type == __SK_ControlChange_) { + j = (int) score->getByteTwo(); + byte3 = score->getByteThree(); + instrument->controlChange(j,byte3); + } + else if (type == __SK_AfterTouch_) { + j = (int) score->getByteTwo(); + instrument->controlChange(128,j); + } + else if (type == __SK_PitchBend_) { + temp = score->getByteTwo(); + j = (int) temp; + temp -= j; + lastPitch = __MIDI_To_Pitch[j] * pow(2.0,temp / 12.0) ; + instrument->setFreq(1, lastPitch); /* change osc1 pitch for now */ + } + else if (type == __SK_ProgramChange_) { + } + } + if (rtInput) { + outOne += 1; + if (outOne == MAX_IN_STRINGS) outOne = 0; + } + numStrings--; + } + } + for (i=0;itick(instrument->tick()); + } + + delete output; + delete score; + delete instrument; + +#if defined(__SGI_REALTIME_) + if (rtInput) kill(string_thread, SIGKILL); +#endif + printf("MUS151 finished.\n"); +} diff --git a/mus151/MUS151.dsp b/mus151/MUS151.dsp new file mode 100644 index 0000000..2bf5980 --- /dev/null +++ b/mus151/MUS151.dsp @@ -0,0 +1,177 @@ +# Microsoft Developer Studio Project File - Name="MUS151" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=MUS151 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "MUS151.MAK". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "MUS151.MAK" CFG="MUS151 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "MUS151 - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "MUS151 - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "MUS151 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "MUS151__" +# PROP BASE Intermediate_Dir "MUS151__" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib dsound.lib Wsock32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "MUS151 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib dsound.lib Wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "MUS151 - Win32 Release" +# Name "MUS151 - Win32 Debug" +# Begin Source File + +SOURCE=..\Envelope.cpp +# End Source File +# Begin Source File + +SOURCE=..\Envelope.h +# End Source File +# Begin Source File + +SOURCE=.\MUS151.cpp +# End Source File +# Begin Source File + +SOURCE=..\Object.cpp +# End Source File +# Begin Source File + +SOURCE=..\Object.h +# End Source File +# Begin Source File + +SOURCE=..\RawLoop.cpp +# End Source File +# Begin Source File + +SOURCE=..\RawLoop.h +# End Source File +# Begin Source File + +SOURCE=..\RawWave.cpp +# End Source File +# Begin Source File + +SOURCE=..\RawWave.h +# End Source File +# Begin Source File + +SOURCE=..\RTSoundIO.cpp +# End Source File +# Begin Source File + +SOURCE=..\RTSoundIO.h +# End Source File +# Begin Source File + +SOURCE=..\RTWvOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\RTWvOut.h +# End Source File +# Begin Source File + +SOURCE=..\SKINI11.cpp +# End Source File +# Begin Source File + +SOURCE=..\SKINI11.h +# End Source File +# Begin Source File + +SOURCE=..\SKINI11.msg +# End Source File +# Begin Source File + +SOURCE=..\SKINI11.tbl +# End Source File +# Begin Source File + +SOURCE=..\swapstuf.cpp +# End Source File +# Begin Source File + +SOURCE=..\swapstuf.h +# End Source File +# Begin Source File + +SOURCE=.\TwoOsc.cpp +# End Source File +# Begin Source File + +SOURCE=.\TwoOsc.h +# End Source File +# Begin Source File + +SOURCE=..\WvOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\WvOut.h +# End Source File +# End Target +# End Project diff --git a/mus151/MUS151.dsw b/mus151/MUS151.dsw new file mode 100644 index 0000000..5020f16 --- /dev/null +++ b/mus151/MUS151.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "MUS151"=.\MUS151.DSP - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/mus151/MUS151.ncb b/mus151/MUS151.ncb new file mode 100644 index 0000000000000000000000000000000000000000..dfe09388d4c06b22f748122efe7c8175f1d3b544 GIT binary patch literal 58368 zcmeHQdvILUdH;63l2^7~*7}8I!l8q!AW5`0`8f3=;OLim~2VziGtCh8|+EsT~ zR_vy(U^3t)nHD<9G)Xg)GA+}VqzP#rlbIxK+R)~K+tO+OXl59~@JEMq(&8jcNJyMj9oI1V@tI1V@tI1V@tI1V@tI1V@tI1V@tI1V@tI1V@tI1V@t zI1V@tI1V@tI1V@tI1V@tI1V@tI1XqI6!7tXlSp$Hh=u?%8hcIRNdwLYaI}bct7Wyq z_ZVC+^$NcT+$_Fq#IFI?LCylN5$RYb8-T;|5!ec8?)1Y~$Q8gfa>|6aNDR1Eo-}x^ ztOH&tvy3l(c#CWSu9LfoAMnGQWixQSeAL8`$y(qBx!J^Tl~$l;SxtP#4{wr9z%hB) zgkLU~1Fw}=k)Gwf48I0k6Tv9uN*t>toQg{LWQ~M#5#S~XH{cGo)=N0FO2Rwp;MXYO zXsx`0G~dI~io{Rg_!5o}0e{o@4FEGNjf3Zp8Gp}UhVgtm4yIv#jvNQx3=aI{(caMO z9fNzyuZ`Ezk>h~lz}tWWFzH3JUb6XIXLu{zwXo~O+umy2-Eh}X190Rx;5hJ>(f?$w*DUCI9(cybL2R1 zfgI>XYu}O-uNHNgbPKUpk_UstMe$b2DiwYuaYDQr^yNu0V$|=5(jr8ZJOPeMRE5{C zKzOHk2j!r`=S=)w=~eh4gV&)iPI@14O1!n`tCQ|C;W6~(NgJ6T@*hwm6C!s2hmilL z<#PxP%f}Hv@=@{rOg;^~LSuwqE4zUs8YBH7ISgE*@g3rA!1x8_*}cpU;h&f5;nd0Z zkst9MIe_rh0p27#fExllB7X|pB#-j?h~I?q56ZVu;=Fi`2%~&^ni$vHi17*DiNZ7D z9hMQ`n8rxITi7LAt7PF2%Crl|<49`{%D^Q2GB|2+`~YF}D|abNd3+CHTM_3Ma2+`g zlykt2|6$Bd(Wmg9G^NGk*ctl;9|3N;Q_Bb9$ALM1){I{SHRBt^o*!<(yBtA%`zsxe zKEoPd#$c^nfdk`ez_xuqi+DVD7AIl?N;lv8w-Qk653H zeFy>8e~z~|qjtAJ4Iti%Uo&d>EW@)tM%yn3ULnVci$1jbEx-}kW8!aUkMe}k=4*Mj25v15$~DXl zgfV}B@`X_*HFtoFIj>;bV7ARXz6l=k;Q1$TExOMc_p8PYql`>v-pY@&eb71KGsNWpV56fd1CM3Q~jsZvHDTD8o1aPf9LYxzC zM2-SS>){z8>YecS5dgC>mecsyV*b#$kHgSC#{k{oEm zv>!&Mq3>@)Z&##KV|MiwR{eu+-QF{N9l|Le*xnOs`JmU+#RB=D`|BJ*)bhbc@4OxH zjeHPaJp5vi5BrfH`|DiK7lV9I^5Qu?o)ANS`u9yZ`|mNxq@4zH{a_3_h?XBdRtIhd zZU`{P8)CS#Qzkz9_c2JWdkyA#!x*lt<&Ce#Gh(t^nsA9!!%wq=KoqTp2zn8dSbNS+oS_{h5X3G*W&{<@`Ay7{Ge7MjF0wv1L^|x zflgxN@2T|wb@GgfuU8kZ3dR@sKJr~HZG zjt_FapIFNWA1y6c=NtKe_4=Iu;|h5tAJTr9{r|c^KKNmdz1JZREg$@F6WYQ$=mSbV zAU)?7>a2XY%MY`4XP-pN2S3d5h&r^H5DB;n=M&j}vW;Z>$hMVjDN9h}WC(cV$Z=pf z9GF9UOnu(2x7mzJ-U5AKScX+{HU8&uy$aXInDIcw|CW5K0-p|@X4TZ=g$O^a*4KzM zGC$yV$-7kitB9iBI>$Hn9KH~~idA=Td(`MA*+TIFU0V?7UXSiC#sv%s}M z_;+L%u3x9|%i=v4`T}shJa5wPm)jA)N#ir(eOYP5Ev4|#Da2o=agBKY68Zt~M)@w& zBmVACAMj-wqkLZq{WI{U0Q=I1{982!|DKdD0&iBb=(EV<>o_>xxt#N#B5oLbV*KTt zGoC$g>d0|m*&I;q|A;i-aAFq+^yGth?>HW?RpMxIOYQ##^mU2vGxeGMYvSKF*b`6T z5rf(PW%#`Yvp-#q*6j~jtA_NUBD6fJkqc6q@xS#?HbXxe}ov} z9nu9{D}QO?bG=+6^nr~AcS{d&RQ4F$BRhfXSf} z&`dB}f;jLZ z-W|5jtgob(f!RObjQY&^{|%T1Anrl^WcyoVa69S?$N%{rvY+nO^MMhL90x8j4)miw zv%PPV?Pxtk)cRjlg7hsO#|K*#*7C#0=wJshz8^w3 z+v}_3YT&R;8N5xd0$w5SGI%TIA67!1XnEtKb?*YM)$%6oWA?EVm^pGi9@|ai7DwNI zCD#*hEI^NsbKLv4kmncH%IQITL<$s0(*Y0s6L+CM!SR91 zP55u9^$eTjbI1=%2E3i2YZ0wg_L%V7<#!O@Q~DBhCay`~90%o*F?R@8(S3~tAKUn}In6U0&JxB_*d74qPp zOn4jC2T+4}$lxuQZ)}A;_(S3e>9`!@2d$6?THg5Ry>|nzGV;d9*Mz;mtF^qT@zFcE z2DskH8y}+qJ-`iG-h_Q?+bR|*9!Td8Y6GC ze$on=IcUn;3Vo;*@*`>RX2{D{$d4Ng-UQSN9xC~S{Hf2hLY`>(r1hm%$djKjKKOGb zzNct~jMehW$7sZEmBZ7fyw_sdm-39~lwmxG8TSDV>tL6_P}Mka{#U*#{tKIOOFGp{%2Y9!zg@E|ILk<`aeqSxoBp-uU9M9wTfUNIr=KG&x@?K!`eLuq6(f?=tSKs#o z>-j?aeZP2Pl0tZm{+=J<9q4~^yia}4kMX&Z8G?54UmUNf;ww`fZKN3uE^tR`Kwz|bRwH0W+YoOt; zM9-fqZC7K&rvWt%HZ(Bi!|!d@zU{f?7~nYY*5ZJx|8K45>F&mH;6gaSQ9Zq~|3Xr^ zxQ+vk18)Tmu>HRVhuWtHy#Vfs6ObpKG)K9d1zwO87#M(KO@;YD2%E!?0T+)BUXJ}p zaJi>&(4H`syo0c+U@1CJx%{QlE;H=eExKGkLYZhMSg)9VW4$6>F0wQ?f`xcot=% z-AAq-piMjvG;tq9IZ^8s#^o9$6F)UC_;)GvzvfGSR*riU+#z;;3Z&)8z_a z<%xNgm7WVC%dZDfCfecRYF9lkr=q`s0xonpl*@~>EfiAi_rletKB7#t&!I;OgXdTs z{UYJLc(^_vFQy(t62WOTJ+g0`k`u3@OtcfiRWG!;@&BeJpJR~g{BlLsgral4H)o=} zeByRhu0KJU_&v0iU-+=%;*k-!c!15}Wj#Y)`fF?Tb3A}Dv0Pl)!;v16ul|?%Ti)xZ zE8>Nf>+ejt#*mobhjQeZ-%h>(@|RAF&)e`mHR~m>i$=Zs(c9E>ya8q6cV=8o#c#Yw zzWQJ4Z+ZNx%E4o~K#xRk4M)Rs;?2$Bq7PKYdfCXYvnUhS%j?&6c`t8ePH!Cb(ZH@D zTdr*=6W9Io{j&3jHqPR1`{F^1hIosH_|1{I4x^aZay^bRaXsAzm1^;{i)MO30l)jm zAM+C42cm6}wkXsnT{X(`(B-O;^$@6B_qPT7(souBSE!if8>2Hixh)qhFdUAC+WVq= zZN8RYYcMy&^&z@_gphr+=!_P3wp^KC({eqGa&bN#%_OK)FP3K8Tr@O4fQ7X^zv_Fl+;yrEPkl_;dDz57yQGsmSbe(ZQ6 zfAZMy$Q|#X@sO#R0@5BEnav$4B)cc2y}P?-U-m>QlbcR;Ps02s@K9p*U@kXJsN>0@ zvHMcVqCxR^$|Mk*vMUJ66_R4ocX{vec6s*%L77CMcxa|LJyVo{yGHjPJhT_qg;Y7> z@x;`0A@HqAXUdSymI`p%_}S!zRB?Yk^_y}cmmU{H^iYiK%v34I353q1vdNRd6_I4` z)O0BZN)Uu)bH&u5Y$=SXD+4Dc0$fZd?+-vSmo4UVncF54+2biy5)@-Bl`rLWB9WO% zo#(M6r>CV|-y0voBF|922Hh$$p4wD;JY7tTW$aTtdIHS0U}&TQ4&Tu~*uQh94YhEp zaJ*em;NfCEojqQVn+hijJ;jsLsY3VU%^FSTlSN#DD1AJeP^Vy5UoOkr#k19EB{`YM z<2erOefMbp;OOwkQ2*dNhrN5?)jtR{dT`$$UX6mf&}eZopGu6&bb5TWDB0Ak$%9W5 zUvS`bJaDD(T|>xF<)#1Q@d|Ld0;%`LRs^qr_b)U5 zy|5JwHPxO5C-Jy`mux^hUPL)l#j*(bL@`wc3&l!oQpY&-wZseYYrwy*IklGv1=%zw(Je||kqd1;PkC{_eCv`fNC{FUEItMFq zRb{q-;Wbfk@sFAyEl6r@ACwaq)rJ{gUW8tyi)B*TQwuUFdq_G?*()DJvdq*mmS83$ zfSL1(KQf$~$&U9Q(v8hf0P#}ZG?Pu^t>;S}_~YJelz_8dK{1q#Guno1HkB!qCpcY7 z5uC;2)0xD{TW2OF(0~>ubNQmz<&DiuDDe!p!1q_RQR$p*l_ru|+diS~DzMneL|zqd z@w-CBP0ZMei&kVjH>+Bd_H;IxnHf*@jH`@T2X7h}7(Q7jrlu-xxcp93PNUN(t?WIh zoU$9zffM8938qG;`_g&nSBlAU@Ni%M(7xM7h7TPX?5mD9Y`9So>DD9r_wR!xM$7Yf zd}=f~hM49JJ<>lovOwrC*;kfGmF+Ogec5$`FP3gZ0}s47 zRX*x%pZ~CR#*h@|1oE^xrFzQ!*u%nd65>F|F=9f$gzxc&?0t_8_usuw-Mh*)9#7(p zE8=ynzP?ql)Qwqy_sN{b$>meJI_L%<0c|rcd6vd6V!`^^WNd z=TMFFg$2{;+`GJdikj4TDsQeI+~{;7Ur3EirVFK8Wtj({#U-FK2l1fEj6n6Q@W72x za#Z;Br7{rU<;iY6iFa%^w~${yIuY}tLi?<|jLLw%)zOElZi+nas>smX21{-kfBz`N z#k4`{sl3PA*}H2u7#b91b}~^ckSXex*+6;JyBCOXo9~XN7E%w4q+B~ca z>2PvCGzQtc&^&(|rnyP{q~-xLOT?u+Tw39o>o3Rj3{8>H94DtVY5sP=q-Eaa#O*RkTvnpY zgJ9@_pB2$`F^MLH?$M{hr8+cCNVB_^p4am;%CtGRGp9*SZlk>z(J&BAa?}ki znOeoYY==L$UFB9JU&1*}4sptdW`Sr{gIkP~xV00v0k0-*H%j94JI%Xri&cL1RcqpM z3v^2#!U;dGDkqw7<+dl5xP?2nY3J6mmTVGk*HTV2H_xR(B$`&T#BJtC{EX{GxZGB* znjS-5oI2$eH08u?&R64tT;@P}0_QYaTTV1PQ%*EFQcW}^Yl+*wkhtuNTi(&EEls)j zC?8GWW)Q|D72ku)X=YC6a%+uhqPdxJqPaXvGwX@@ngf0uX)Mt^*+Rr^RhC0E0ZgLl-;cuOH10z5Bs^&v>|xv!KjF6I zqwF-RV~I;yXp)I$h52c>C7M|-rz!B0L~}?aZo5=YT=l^vqvb?X%OskR;b)wdxP=4F z6w#Ct&606TCYoVhjJVW>L{rS%9*QPtNHi_?aq#wo3#6slI-0U2(fngIaq$IB-Eny& zP1abV88&W7!6oodBmY~FKbIht6HQW)Xd1Jeep(JL)$^Y`+8cVk1M9*-PvHi8vKa3v zz)6nv=utoR`!$}*jn8CK)wrixE2*9dPZf)SQhCho4*E^t0LRrLWYWmaITGi0_nKcZa@4fL;n>AWi#ZhS|jyy zgmbm-F}VEd;2F3S#8=~BoM9YnC-);i-V^hpe((ptv_@Kw_`mE`$heFn$APyj2d==K zb>P^1t~2~?RQ|QEbfQ+FqiEdSaBo4ydl4?{;#-gZm=fvv7HxGsx$QNdL_1o#6xUf8My~;Jz35z%O)u?}pnAJZaoxNKYA; zfg8h~A=krhDEAuSejnGt=Jnormalize(); + osc[i]->setFreq((MY_FLOAT) 200.0); + amps[i] = 0.2; + } + lastOutput = 0; +} + +TwoOsc :: ~TwoOsc() +{ + int i; + for (i=0; i<2; i++) delete osc[i]; + delete envelope; +} + +void TwoOsc :: setFreq(int oscnum, MY_FLOAT frequency) +{ + if (oscnum == 1) osc[0]->setFreq(frequency); + else if (oscnum == 2) osc[1]->setFreq(frequency); +} + +void TwoOsc :: setAmp(int oscnum, MY_FLOAT amp) +{ + if (oscnum == 1) amps[0] = amp; + else if (oscnum == 2) amps[1] = amp; +} + +void TwoOsc :: noteOn(MY_FLOAT freq, MY_FLOAT amp) +{ + envelope->keyOn(); +} + +void TwoOsc :: noteOff(MY_FLOAT amp) +{ + envelope->keyOff(); +} + +MY_FLOAT TwoOsc :: tick() +{ + lastOutput = 0.5 * envelope->tick() * (amps[0]*osc[0]->tick() + amps[1]*osc[1]->tick()); + return lastOutput; +} + +void TwoOsc :: controlChange(int number, MY_FLOAT value) +{ + switch (number) { + case 20: + osc[0]->setFreq(value); + break; + case 21: + osc[1]->setFreq(value); + break; + case 22: + amps[0] = value * NORM_7; + break; + case 23: + amps[1] = value * NORM_7; + break; + } +} diff --git a/mus151/TwoOsc.h b/mus151/TwoOsc.h new file mode 100644 index 0000000..400c42b --- /dev/null +++ b/mus151/TwoOsc.h @@ -0,0 +1,35 @@ +/******************************************/ +/* Two oscillator instrument for use */ +/* with MUS151 Psychoacoustics course. */ +/* by Gary P. Scavone, 1998 */ +/* CCRMA, Stanford Unviversity */ +/******************************************/ + +#if !defined(__TwoOsc_h) +#define __TwoOsc_h + +//#include "../Instrmnt.h" +#include "../Envelope.h" +#include "../RawLoop.h" + + +class TwoOsc : public Object +{ + protected: + Envelope *envelope; + RawLoop *osc[2]; + MY_FLOAT lastOutput; + MY_FLOAT amps[2]; + + public: + TwoOsc(); + ~TwoOsc(); + virtual void setFreq(int oscnum, MY_FLOAT frequency); + virtual void setAmp(int oscnum, MY_FLOAT amp); + virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp); + virtual void noteOff(MY_FLOAT amp); + virtual MY_FLOAT tick(); + virtual void controlChange(int number, MY_FLOAT value); +}; + +#endif diff --git a/mus151/tcl/TwoWaves.tcl b/mus151/tcl/TwoWaves.tcl new file mode 100644 index 0000000..4312cef --- /dev/null +++ b/mus151/tcl/TwoWaves.tcl @@ -0,0 +1,201 @@ +set pitch 64.0 +set osc1on 1 +set osc2on 1 +set freq1 200.0 +set freq2 200.0 +set amp1 20 +set amp2 20 +set outID "stdout" +set commtype "stdout" + +# Configure main window +wm title . "MUS152 Two Oscillator Controller" +wm iconname . "TwoOsc" +. config -bg black + +# Configure "communications" menu +menu .menu -tearoff 0 +menu .menu.communication -tearoff 0 +.menu add cascade -label "Communication" -menu .menu.communication \ + -underline 0 +.menu.communication add radio -label "Console" -variable commtype \ + -value "stdout" -command { setComm } +.menu.communication add radio -label "Socket" -variable commtype \ + -value "socket" -command { setComm } +. configure -menu .menu + +# Configure title display +label .title -text "MUS151 Two Oscillator Controller" \ + -font {Times 14 bold} -background white \ + -foreground darkred -relief raised + +label .title2 -text "by Gary P. Scavone\n Center for Computer Research in Music & Acoustics (CCRMA) \n Stanford University" \ + -font {Times 12 bold} -background white \ + -foreground darkred -relief raised + +pack .title -padx 5 -pady 10 +pack .title2 -padx 5 -pady 10 + +# Configure "note-on" buttons +frame .noteOn -bg black + +button .noteOn.on -text NoteOn -bg grey66 -command { noteOn $pitch 64.0 } +button .noteOn.off -text NoteOff -bg grey66 -command { noteOff $pitch 127.0 } +button .noteOn.exit -text "Exit Program" -bg grey66 -command myExit +pack .noteOn.on -side left -padx 5 +pack .noteOn.off -side left -padx 5 -pady 10 +pack .noteOn.exit -side left -padx 5 -pady 10 + +pack .noteOn + +# Configure sliders +frame .left -bg black + +scale .left.freq1 -from 0 -to 10000 -length 400 \ +-command {changeParam 20 } \ +-orient horizontal -label "Frequency 1" \ +-tickinterval 2000 -showvalue true -bg grey66 \ +-variable freq1 + +scale .left.amp1 -from 0 -to 127 -length 400 \ +-command {changeParam 22 } \ +-orient horizontal -label "Amp 1" \ +-tickinterval 32 -showvalue true -bg grey66 \ +-variable amp1 + +scale .left.freq2 -from 0 -to 10000 -length 400 \ +-command {changeParam 21 } \ +-orient horizontal -label "Frequency 2" \ +-tickinterval 2000 -showvalue true -bg grey66 \ +-variable freq2 + +scale .left.amp2 -from 0 -to 127 -length 400 \ +-command {changeParam 23 } \ +-orient horizontal -label "Amp 2" \ +-tickinterval 32 -showvalue true -bg grey66 \ +-variable amp2 + +pack .left.freq1 -padx 10 -pady 3 +pack .left.amp1 -padx 10 -pady 3 +pack .left.freq2 -padx 10 -pady 3 +pack .left.amp2 -padx 10 -pady 3 + +pack .left -side left + +# Configure more buttons +frame .onOff -bg black + +checkbutton .onOff.1 -text "Play Osc 1" -variable osc1on -relief flat \ + -command {setPlayStatus 22 $osc1on} +checkbutton .onOff.2 -text "Play Osc 2" -variable osc2on -relief flat \ + -command {setPlayStatus 23 $osc2on} + +pack .onOff.1 .onOff.2 -padx 5 +pack .onOff -side right -padx 5 -pady 10 + +proc myExit {} { + global outID + puts $outID [format "NoteOff 0.0 1 64 127" ] + flush $outID + puts $outID [format "ExitProgram"] + flush $outID + close $outID + exit +} + +proc noteOn {pitchVal pressVal} { + global outID + puts $outID [format "NoteOn 0.0 1 %f %f" $pitchVal $pressVal] + flush $outID +} + +proc noteOff {pitchVal pressVal} { + global outID + puts $outID [format "NoteOff 0.0 1 %f %f" $pitchVal $pressVal] + flush $outID +} + +proc changeParam {controlNum value } { + global outID freq1 freq2 amp1 amp2 osc1on osc2on + if {$controlNum==20 || $controlNum==22} { + if {$osc1on==1} { + puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum $value ] + } + } elseif {$controlNum==21 || $controlNum==23} { + if {$osc2on==1} { + puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum $value ] + } + } + flush $outID +} + +proc setPlayStatus {controlNum value } { + global outID amp1 amp2 freq1 freq2 + if {$value==1} { + if {$controlNum==22} { + puts $outID [format "ControlChange 0.0 1 %d %f" 20 $freq1 ] + puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum $amp1 ] + } elseif {$controlNum==23} { + puts $outID [format "ControlChange 0.0 1 %d %f" 21 $freq2 ] + puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum $amp2 ] + } + } elseif {$value==0} { + puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum 0.0 ] + } + flush $outID +} + +# Socket connection procedure +set d .socketdialog + +proc setComm {} { + global outID commtype d + if {$commtype == "stdout"} { + if { [string compare "stdout" $outID] } { + set i [tk_dialog .dialog "Break Socket Connection?" {You are about to break an existing socket connection ... is this what you want to do?} "" 0 Cancel OK] + switch $i { + 0 {set commtype "socket"} + 1 {close $outID + set outID "stdout"} + } + } + } elseif { ![string compare "stdout" $outID] } { + set sockport 2001 + toplevel $d + wm title $d "STK Client Socket Connection" + wm resizable $d 0 0 + grab $d + label $d.message -text "Specify a socket port number below (if different than the STK default of 2001) and then click the \"Connect\" button to invoke a socket-client connection attempt to the STK socket server." \ + -background white -font {Helvetica 10 bold} \ + -wraplength 3i -justify left + frame $d.sockport + entry $d.sockport.entry -width 6 + label $d.sockport.text -text "Socket Port Number:" \ + -font {Helvetica 10 bold} + pack $d.message -side top -padx 5 -pady 10 + pack $d.sockport.text -side left -padx 1 -pady 10 + pack $d.sockport.entry -side right -padx 5 -pady 10 + pack $d.sockport -side top -padx 5 -pady 10 + $d.sockport.entry insert 0 $sockport + frame $d.buttons + button $d.buttons.cancel -text "Cancel" -bg grey66 \ + -command { set commtype "stdout" + set outID "stdout" + destroy $d } + button $d.buttons.connect -text "Connect" -bg grey66 \ + -command { + set sockport [$d.sockport.entry get] + set err [catch {socket localhost $sockport} outID] + if {$err == 0} { + destroy $d + } else { + tk_dialog $d.error "Socket Error" {Error: Unable to make socket connection. Make sure the STK socket server is first running and that the port number is correct.} "" 0 OK + } } + pack $d.buttons.cancel -side left -padx 5 -pady 10 + pack $d.buttons.connect -side right -padx 5 -pady 10 + pack $d.buttons -side bottom -padx 5 -pady 10 + } +} + + + diff --git a/syntmono.cpp b/syntmono.cpp index 1078d89..c616b2d 100644 --- a/syntmono.cpp +++ b/syntmono.cpp @@ -67,7 +67,7 @@ void newString(void *) { int inOne = 0; while (notDone) { - fgets(inputString[inOne],128,stdin); + fgets(inputString[inOne],INSTR_LEN,stdin); if (inputString[inOne][0] == 'E' && inputString[inOne][1] == 'x') { notDone = 0; } @@ -86,6 +86,7 @@ void newString(void *) #elif defined(__USS_REALTIME_) #include +//#include char inputString[MAX_IN_STRINGS][INSTR_LEN]; pthread_t string_thread; @@ -94,7 +95,7 @@ void *newString(void *) { int inOne = 0; while (notDone) { - fgets(inputString[inOne],128,stdin); + fgets(inputString[inOne],INSTR_LEN,stdin); if (inputString[inOne][0] == 'E' && inputString[inOne][1] == 'x') { notDone = 0; } @@ -434,12 +435,14 @@ void main(int argc,char *argv[]) instrument->noteOn(200.0,0.1); } #endif - + /* Finally ... the runtime loop begins! */ notDone = 1; + synlength = RT_BUFFER_SIZE; while(notDone || numStrings) { if (rtInput) { - synlength = RT_BUFFER_SIZE; + if (numStrings > 1) synlength = (long) RT_BUFFER_SIZE / numStrings; + else synlength = RT_BUFFER_SIZE; for ( i=0; i 1) { outSample = reverb->tick(instrument->tick()); @@ -455,22 +458,21 @@ void main(int argc,char *argv[]) numStrings++; } } - while (numStrings) { + if (numStrings) { score->parseThis(inputString[outOne]); type = score->getType(); - if (type > 0) { - synlength = (long) (score->getDelta() * SRATE); -#if defined(_debug_) - if (!rtInput) printf("Time = %f: ",output.getTime()); -#endif - for ( i=0; i 1) { - outSample = reverb->tick(instrument->tick()); - for ( j=0; jtick(outSample); + if (type > 0) { + if (temp = score->getDelta()) { /* SKINI score file */ + synlength = (long) (temp * SRATE); + for ( i=0; i 1) { + outSample = reverb->tick(instrument->tick()); + for ( j=0; jtick(outSample); + } + else output[0]->tick(reverb->tick(instrument->tick())); } - else output[0]->tick(reverb->tick(instrument->tick())); + synlength = 0; } - synlength = 0; if (type == __SK_NoteOn_ ) { if (( byte3 = score->getByteThree() ) == 0) instrument->noteOff(byte3*NORM_7); @@ -578,7 +580,8 @@ void main(int argc,char *argv[]) numStrings--; } } - for (i=0;i<2*reverbTime*SRATE;i++) { /* let the reverb settle a little */ + + for (i=0;i 1) { outSample = reverb->tick(instrument->tick()); for ( j=0; jtick(outSample); @@ -596,5 +599,5 @@ void main(int argc,char *argv[]) #if defined(__SGI_REALTIME_) if (rtInput) kill(string_thread, SIGKILL); #endif - printf("syntmono finished ... au revoir.\n"); + printf("syntmono finished ... goodbye.\n"); } diff --git a/syntmono.dsp b/syntmono.dsp index 20e5455..d1b8f2d 100644 --- a/syntmono.dsp +++ b/syntmono.dsp @@ -452,6 +452,14 @@ SOURCE=.\PRCRev.h # End Source File # Begin Source File +SOURCE=.\RawInterp.cpp +# End Source File +# Begin Source File + +SOURCE=.\RawInterp.h +# End Source File +# Begin Source File + SOURCE=.\RawLoop.cpp # End Source File # Begin Source File @@ -460,6 +468,14 @@ SOURCE=.\RawLoop.h # End Source File # Begin Source File +SOURCE=.\RawShot.cpp +# End Source File +# Begin Source File + +SOURCE=.\RawShot.h +# End Source File +# Begin Source File + SOURCE=.\RawWave.cpp # End Source File # Begin Source File @@ -468,14 +484,6 @@ SOURCE=.\RawWave.h # End Source File # Begin Source File -SOURCE=.\RawWvIn.cpp -# End Source File -# Begin Source File - -SOURCE=.\RawWvIn.h -# End Source File -# Begin Source File - SOURCE=.\ReedTabl.cpp # End Source File # Begin Source File diff --git a/syntmono.plg b/syntmono.plg index 885f5f9..7d264ba 100644 --- a/syntmono.plg +++ b/syntmono.plg @@ -10,15 +10,83 @@ Project's tools are: "Custom Build" with flags "" "" with flags "" -Creating temp file "c:\windows\TEMP\RSP8374.TMP" with contents -Creating command line "cl.exe @c:\windows\TEMP\RSP8374.TMP" -Creating temp file "c:\windows\TEMP\RSP8375.TMP" with contents -Creating command line "link.exe @c:\windows\TEMP\RSP8375.TMP" +.\Release\WvOut.obj> +Creating command line "link.exe @C:\WINDOWS\TEMP\RSPF2B1.TMP" Compiling... +ADSR.cpp +AgogoBel.cpp +BeeThree.cpp +BiQuad.cpp +Bowed.cpp +BowTabl.cpp +Brass.cpp +Clarinet.cpp +DCBlock.cpp +DLineA.cpp +DLineL.cpp +DLineN.cpp DrumSynt.cpp +Envelope.cpp +Filter.cpp +Flute.cpp +FM4Alg3.cpp +FM4Alg4.cpp +FM4Alg5.cpp +FM4Alg6.cpp +FM4Alg8.cpp +FM4Op.cpp FMVoices.cpp +FormSwep.cpp +HeavyMtl.cpp +Instrmnt.cpp +JCRev.cpp +JetTabl.cpp +LipFilt.cpp +Mandolin.cpp +Mandplyr.cpp +Marimba.cpp +MatWvOut.cpp +Modal4.cpp +Modulatr.cpp +Moog1.cpp Noise.cpp +NRev.cpp +Object.cpp +OnePole.cpp +OneZero.cpp +PercFlut.cpp +Plucked.cpp +Plucked2.cpp +PRCRev.cpp +RawInterp.cpp +RawLoop.cpp +RawShot.cpp +RawWave.cpp +ReedTabl.cpp +Reverb.cpp +Rhodey.cpp +RTSoundIO.cpp +RTWvOut.cpp +Sampler.cpp +SamplFlt.cpp Shakers.cpp +Simple.cpp +SingWave.cpp +SKINI11.cpp +SndWvOut.cpp +SubNoise.cpp +Swapstuf.cpp Syntmono.cpp +TubeBell.cpp +TwoPole.cpp +TwoZero.cpp +Vibraphn.cpp +VoicForm.cpp +VoicMang.cpp +WavWvOut.cpp +Wurley.cpp +WvOut.cpp Linking...