diff options
| -rwxr-xr-x | main.cpp | 76 | ||||
| -rwxr-xr-x | maximilian.h | 7 | ||||
| -rw-r--r-- | ofxMaxim/ofxMaxim/libs/maximilian.cpp | 328 | ||||
| -rwxr-xr-x | ofxMaxim/ofxMaxim/libs/maximilian.h | 69 |
4 files changed, 379 insertions, 101 deletions
@@ -1,55 +1,61 @@ #include "maximilian.h" -//this tutorial explains how to use the maxiEnv +//Bizarelly, this sounds a little bit like Kraftwerk's 'Metropolis', although it isn't. Funny that. -maxiSample sound1; +maxiOsc sound,bass,timer,mod,lead,lead2,leadmod;//here are the synth bits +maxiEnv envelope, leadenvelope;//some envelopes +maxiFilter filter, filter2;//some filters +maxiDelayline delay;//a delay +convert mtof;//a method for converting midi notes to frequency +double bassout,leadout, delayout;//some variables to hold the data and pass it around +int trigger, trigger2, newnote;//some control variables +int currentCount,lastCount,playHead=0, currentChord=0;//some other control variables +int pitch[8]={57,57,59,60};//the bassline for the arpeggio +int chord[8]={0,0,7,2,5,5,0,0};//the root chords for the arpeggio +float currentPitch,leadPitch;//the final pitch variables -maxiOsc timer,snarePhase; //and a timer +//here's the lead line trigger array, followed by the pitches +int leadLineTrigger[256]={1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +int leadLinePitch[15]={69,67,65,64,67,66,64,62,65,64,62,57,55,60,57}; -maxiEnv envelope;//this is going to be an envelope -int currentCount,lastCount,playHead, - -sequence[16]={1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0}; //This is the sequence for the kick - -int sampleTrigger; - -double sampleOut; void setup() {//some inits - //YOU HAVE TO PROVIDE THE SAMPLES.... - - sound1.load("/Users/mickgrierson/Documents/audio/68373__juskiddink__Cello_open_string_bowed.wav");//load in your samples. Provide the full path to a wav file. - - - printf("Summary:\n%s", sound1.getSummary());//get info on samples if you like. - //beats.getLength(); } void play(double *output) {//this is where the magic happens. Very slow magic. - currentCount=(int)timer.phasor(8);//this sets up a metronome that ticks 8 times a second - + currentCount=(int)timer.phasor(9);//this sets up a metronome that ticks every so often if (lastCount!=currentCount) {//if we have a new timer int this sample, play the sound - - sampleTrigger=sequence[playHead%16]; + trigger=1;//play the arpeggiator line + trigger2=leadLineTrigger[playHead%256];//play the lead line + if (trigger2==1) {//if we are going to play a note + leadPitch=mtof.mtof(leadLinePitch[newnote]);//get the next pitch val + newnote++;//and iterate + if (newnote>14) { + newnote=0;//make sure we don't go over the edge of the array + } + } + currentPitch=mtof.mtof(pitch[(playHead%4)]+chord[currentChord%8]);//write the frequency val into currentPitch playHead++;//iterate the playhead - lastCount=0;//reset the metrotest - + if (playHead%32==0) {//wrap every 4 bars + currentChord++;//change the chord + } + //cout << "tick\n";//the clock ticks + lastCount=0;//set lastCount to 0 } - //the envelope we're using here is an AR envelope. - //It has an input (which in this case is a sound) - //It has an attack coefficient, a hold val (in samples) - //and a release coefficient. Finally, it has a trigger input. - //If you stick a 1 in the trigger input, it retriggers the envelope - sampleOut=envelope.ar(sound1.play(1.), 0.1, 0.9999, 1, sampleTrigger); // - - output[0]=sampleOut;//left channel - output[1]=sampleOut;//right channel + bassout=filter2.lores(envelope.adsr(bass.saw(currentPitch*0.5)+sound.pulse(currentPitch*0.5,mod.phasor(1)),1,0.9995, 0.25, 0.9995, 1, trigger),9250,2);//new, simple ADSR. + leadout=filter.lores(leadenvelope.ar(lead2.saw(leadPitch*4)+lead.pulse(leadPitch+(leadmod.sinebuf(1.9)*1.5), 0.6), 0.00005, 0.999975, 50000, trigger2),5900,10);//leadline + + delayout=(leadout+(delay.dl(leadout, 14000, 0.8)*0.5))/2;//add some delay + + if(trigger!=0)trigger=0;//set the trigger to off if you want it to trigger immediately next time. + + + output[0]=(bassout+delayout)/2;//sum output + output[1]=(bassout+delayout)/2; - sampleTrigger = 0;//set trigger to 0 at the end of each sample to guarantee retriggering. - }
\ No newline at end of file diff --git a/maximilian.h b/maximilian.h index 5062ba5..4ec75d1 100755 --- a/maximilian.h +++ b/maximilian.h @@ -137,6 +137,7 @@ class maxiFilter { double z;//pole double c;//filter coefficient public: + maxiFilter():x(0.0), y(0.0), z(0.0), c(0.0){}; double cutoff; double resonance; double lores(double input,double cutoff1, double resonance); @@ -173,12 +174,12 @@ private: int myByteRate; short myBlockAlign; short myBitsPerSample; - int myDataSize; double position; double speed; double output; public: + int myDataSize; short myChannels; int mySampleRate; long length; @@ -191,7 +192,7 @@ public: ~maxiSample() { - delete myData; + if (myData) delete[] myData; myChunkSize = NULL; mySubChunk1Size = NULL; myFormat = NULL; @@ -203,7 +204,7 @@ public: myDataSize = NULL; } -// maxiSample(); + maxiSample():myData(NULL){}; bool load(string fileName, int channel=0); diff --git a/ofxMaxim/ofxMaxim/libs/maximilian.cpp b/ofxMaxim/ofxMaxim/libs/maximilian.cpp index 10c13ca..3741173 100644 --- a/ofxMaxim/ofxMaxim/libs/maximilian.cpp +++ b/ofxMaxim/ofxMaxim/libs/maximilian.cpp @@ -47,14 +47,16 @@ int maxiSettings::bufferSize = 1024; double sineBuffer[514]={0,0.012268,0.024536,0.036804,0.049042,0.06131,0.073547,0.085785,0.097992,0.1102,0.12241,0.13455,0.1467,0.15884,0.17093,0.18301,0.19507,0.20709,0.21909,0.23105,0.24295,0.25485,0.26669,0.2785,0.29025,0.30197,0.31366,0.32529,0.33685,0.34839,0.35986,0.37128,0.38266,0.39395,0.40521,0.41641,0.42752,0.4386,0.44958,0.46051,0.47137,0.48215,0.49286,0.50351,0.51407,0.52457,0.53497,0.54529,0.55554,0.5657,0.57578,0.58575,0.59567,0.60547,0.6152,0.62482,0.63437,0.6438,0.65314,0.66238,0.67151,0.68057,0.68951,0.69833,0.70706,0.7157,0.72421,0.7326,0.74091,0.74908,0.75717,0.76514,0.77298,0.7807,0.7883,0.79581,0.80316,0.81042,0.81754,0.82455,0.83142,0.8382,0.84482,0.85132,0.8577,0.86392,0.87006,0.87604,0.88187,0.8876,0.89319,0.89862,0.90396,0.90912,0.91415,0.91907,0.92383,0.92847,0.93295,0.93729,0.9415,0.94556,0.94949,0.95325,0.95691,0.96039,0.96375,0.96692,0.97,0.9729,0.97565,0.97827,0.98074,0.98306,0.98523,0.98724,0.98914,0.99084,0.99243,0.99387,0.99515,0.99628,0.99725,0.99808,0.99875,0.99927,0.99966,0.99988,0.99997,0.99988,0.99966,0.99927,0.99875,0.99808,0.99725,0.99628,0.99515,0.99387,0.99243,0.99084,0.98914,0.98724,0.98523,0.98306,0.98074,0.97827,0.97565,0.9729,0.97,0.96692,0.96375,0.96039,0.95691,0.95325,0.94949,0.94556,0.9415,0.93729,0.93295,0.92847,0.92383,0.91907,0.91415,0.90912,0.90396,0.89862,0.89319,0.8876,0.88187,0.87604,0.87006,0.86392,0.8577,0.85132,0.84482,0.8382,0.83142,0.82455,0.81754,0.81042,0.80316,0.79581,0.7883,0.7807,0.77298,0.76514,0.75717,0.74908,0.74091,0.7326,0.72421,0.7157,0.70706,0.69833,0.68951,0.68057,0.67151,0.66238,0.65314,0.6438,0.63437,0.62482,0.6152,0.60547,0.59567,0.58575,0.57578,0.5657,0.55554,0.54529,0.53497,0.52457,0.51407,0.50351,0.49286,0.48215,0.47137,0.46051,0.44958,0.4386,0.42752,0.41641,0.40521,0.39395,0.38266,0.37128,0.35986,0.34839,0.33685,0.32529,0.31366,0.30197,0.29025,0.2785,0.26669,0.25485,0.24295,0.23105,0.21909,0.20709,0.19507,0.18301,0.17093,0.15884,0.1467,0.13455,0.12241,0.1102,0.097992,0.085785,0.073547,0.06131,0.049042,0.036804,0.024536,0.012268,0,-0.012268,-0.024536,-0.036804,-0.049042,-0.06131,-0.073547,-0.085785,-0.097992,-0.1102,-0.12241,-0.13455,-0.1467,-0.15884,-0.17093,-0.18301,-0.19507,-0.20709,-0.21909,-0.23105,-0.24295,-0.25485,-0.26669,-0.2785,-0.29025,-0.30197,-0.31366,-0.32529,-0.33685,-0.34839,-0.35986,-0.37128,-0.38266,-0.39395,-0.40521,-0.41641,-0.42752,-0.4386,-0.44958,-0.46051,-0.47137,-0.48215,-0.49286,-0.50351,-0.51407,-0.52457,-0.53497,-0.54529,-0.55554,-0.5657,-0.57578,-0.58575,-0.59567,-0.60547,-0.6152,-0.62482,-0.63437,-0.6438,-0.65314,-0.66238,-0.67151,-0.68057,-0.68951,-0.69833,-0.70706,-0.7157,-0.72421,-0.7326,-0.74091,-0.74908,-0.75717,-0.76514,-0.77298,-0.7807,-0.7883,-0.79581,-0.80316,-0.81042,-0.81754,-0.82455,-0.83142,-0.8382,-0.84482,-0.85132,-0.8577,-0.86392,-0.87006,-0.87604,-0.88187,-0.8876,-0.89319,-0.89862,-0.90396,-0.90912,-0.91415,-0.91907,-0.92383,-0.92847,-0.93295,-0.93729,-0.9415,-0.94556,-0.94949,-0.95325,-0.95691,-0.96039,-0.96375,-0.96692,-0.97,-0.9729,-0.97565,-0.97827,-0.98074,-0.98306,-0.98523,-0.98724,-0.98914,-0.99084,-0.99243,-0.99387,-0.99515,-0.99628,-0.99725,-0.99808,-0.99875,-0.99927,-0.99966,-0.99988,-0.99997,-0.99988,-0.99966,-0.99927,-0.99875,-0.99808,-0.99725,-0.99628,-0.99515,-0.99387,-0.99243,-0.99084,-0.98914,-0.98724,-0.98523,-0.98306,-0.98074,-0.97827,-0.97565,-0.9729,-0.97,-0.96692,-0.96375,-0.96039,-0.95691,-0.95325,-0.94949,-0.94556,-0.9415,-0.93729,-0.93295,-0.92847,-0.92383,-0.91907,-0.91415,-0.90912,-0.90396,-0.89862,-0.89319,-0.8876,-0.88187,-0.87604,-0.87006,-0.86392,-0.8577,-0.85132,-0.84482,-0.8382,-0.83142,-0.82455,-0.81754,-0.81042,-0.80316,-0.79581,-0.7883,-0.7807,-0.77298,-0.76514,-0.75717,-0.74908,-0.74091,-0.7326,-0.72421,-0.7157,-0.70706,-0.69833,-0.68951,-0.68057,-0.67151,-0.66238,-0.65314,-0.6438,-0.63437,-0.62482,-0.6152,-0.60547,-0.59567,-0.58575,-0.57578,-0.5657,-0.55554,-0.54529,-0.53497,-0.52457,-0.51407,-0.50351,-0.49286,-0.48215,-0.47137,-0.46051,-0.44958,-0.4386,-0.42752,-0.41641,-0.40521,-0.39395,-0.38266,-0.37128,-0.35986,-0.34839,-0.33685,-0.32529,-0.31366,-0.30197,-0.29025,-0.2785,-0.26669,-0.25485,-0.24295,-0.23105,-0.21909,-0.20709,-0.19507,-0.18301,-0.17093,-0.15884,-0.1467,-0.13455,-0.12241,-0.1102,-0.097992,-0.085785,-0.073547,-0.06131,-0.049042,-0.036804,-0.024536,-0.012268,0,0.012268 }; +int mtofarray[129]={0, 8.661957, 9.177024, 9.722718, 10.3, 10.913383, 11.562325, 12.25, 12.978271, 13.75, 14.567617, 15.433853, 16.351599, 17.323914, 18.354048, 19.445436, 20.601723, 21.826765, 23.124651, 24.5, 25.956543, 27.5, 29.135235, 30.867706, 32.703197, 34.647827, 36.708096, 38.890873, 41.203445, 43.65353, 46.249302, 49., 51.913086, 55., 58.27047, 61.735413, 65.406395, 69.295654, 73.416191, 77.781746, 82.406891, 87.30706, 92.498604, 97.998856, 103.826172, 110., 116.540939, 123.470825, 130.81279, 138.591309, 146.832382, 155.563492, 164.813782, 174.61412, 184.997208, 195.997711, 207.652344, 220., 233.081879, 246.94165, 261.62558, 277.182617,293.664764, 311.126984, 329.627563, 349.228241, 369.994415, 391.995422, 415.304688, 440., 466.163757, 493.883301, 523.25116, 554.365234, 587.329529, 622.253967, 659.255127, 698.456482, 739.988831, 783.990845, 830.609375, 880., 932.327515, 987.766602, 1046.502319, 1108.730469, 1174.659058, 1244.507935, 1318.510254, 1396.912964, 1479.977661, 1567.981689, 1661.21875, 1760., 1864.655029, 1975.533203, 2093.004639, 2217.460938, 2349.318115, 2489.015869, 2637.020508, 2793.825928, 2959.955322, 3135.963379, 3322.4375, 3520., 3729.31, 3951.066406, 4186.009277, 4434.921875, 4698.63623, 4978.031738, 5274.041016, 5587.651855, 5919.910645, 6271.926758, 6644.875, 7040., 7458.620117, 7902.132812, 8372.018555, 8869.84375, 9397.272461, 9956.063477, 10548.082031, 11175.303711, 11839.821289, 12543.853516, 13289.75}; + void setup();//use this to do any initialisation if you want. void play(double *channels);//run dac! maxiOsc::maxiOsc(){ phase = 0.0; -// memset(phases,0,500); -// memset(freqs,0,500); + // memset(phases,0,500); + // memset(freqs,0,500); } double maxiOsc::noise() { @@ -64,6 +66,11 @@ double maxiOsc::noise() { return(output); } +void maxiOsc::phaseReset(double phaseIn) { + phase=phaseIn; + +} + double maxiOsc::sinewave(double frequency) { output=sin (phase*(TWOPI)); if ( phase >= 1.0 ) phase -= 1.0; @@ -162,14 +169,13 @@ double maxiOsc::saw(double frequency) { } -double maxiOsc::triangle(double frequency, double phase) { - output=tri*2; +double maxiOsc::triangle(double frequency) { if ( phase >= 1.0 ) phase -= 1.0; - phase += (1./(maxiSettings::sampleRate/(frequency*chandiv))); + phase += (1./(maxiSettings::sampleRate/(frequency))); if (phase <= 0.5 ) { - tri = phase; - } else { - tri =(1-phase); + output =((phase)*4)-1; + } else { + output =((0.5-phase)*4)-1; } return(output); @@ -177,36 +183,54 @@ double maxiOsc::triangle(double frequency, double phase) { //I like this. double maxiEnvelope::line(int numberofsegments,double segments[1000]) { - period=2./(segments[valindex+1]*0.004); - nextval=segments[valindex+2]; - currentval=segments[valindex]; - if (currentval-amplitude > 0.0000001 && valindex < numberofsegments) { - amplitude += ((currentval-startval)/(maxiSettings::sampleRate/period)); - } else if (currentval-amplitude < -0.0000001 && valindex < numberofsegments) { - amplitude -= (((currentval-startval)*(-1))/(maxiSettings::sampleRate/period)); - } else if (valindex >numberofsegments-1) { - valindex=numberofsegments-2; - } else { - valindex=valindex+2; - startval=currentval; + if (isPlaying==1) {//only make a sound once you've been triggered + + period=2./(segments[valindex+1]*0.004); + nextval=segments[valindex+2]; + currentval=segments[valindex]; + if (currentval-amplitude > 0.0000001 && valindex < numberofsegments) { + amplitude += ((currentval-startval)/(maxiSettings::sampleRate/period)); + } else if (currentval-amplitude < -0.0000001 && valindex < numberofsegments) { + amplitude -= (((currentval-startval)*(-1))/(maxiSettings::sampleRate/period)); + } else if (valindex >numberofsegments-1) { + valindex=numberofsegments-2; + } else { + valindex=valindex+2; + startval=currentval; + } + output=amplitude; + + } + else { + output=0; + } - output=amplitude; - return(output); + return(output); } //and this void maxiEnvelope::trigger(int index, double amp) { + isPlaying=1;//ok the envelope is being used now. valindex=index; amplitude=amp; } //and this + +maxiDelayline::maxiDelayline() { + memory[88200]=NULL; + +} + + double maxiDelayline::dl(double input, int size, double feedback) { - if ( phase >=size ) phase = 0; + if ( phase >=size ) { + phase = 0; + } memory[phase]=(memory[phase]*feedback)+(input*feedback)*0.5; phase+=1; - output=memory[phase+1]; + output=memory[phase]; return(output); } @@ -237,7 +261,7 @@ double maxiFilter::hipass(double input, double cutoff) { double maxiFilter::lores(double input,double cutoff1, double resonance) { cutoff=cutoff1*0.5; if (cutoff<10) cutoff=10; - if (cutoff>(maxiSettings::sampleRate*0.25)) cutoff=(maxiSettings::sampleRate*0.25); + if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5); if (resonance<1.) resonance = 1.; z=cos(TWOPI*cutoff/maxiSettings::sampleRate); c=2-2*z; @@ -253,7 +277,7 @@ double maxiFilter::lores(double input,double cutoff1, double resonance) { double maxiFilter::hires(double input,double cutoff1, double resonance) { cutoff=cutoff1*0.5; if (cutoff<10) cutoff=10; - if (cutoff>(maxiSettings::sampleRate*0.25)) cutoff=(maxiSettings::sampleRate*0.25); + if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5); if (resonance<1.) resonance = 1.; z=cos(TWOPI*cutoff/maxiSettings::sampleRate); c=2-2*z; @@ -323,8 +347,9 @@ double *maxiMix::ambisonic(double input,double eight[8],double x,double y,double } -bool maxiSample::load(string fileName) { +bool maxiSample::load(string fileName, int channel) { myPath = fileName; + readChannel=channel; return read(); } @@ -337,10 +362,8 @@ bool maxiSample::read() bool result; ifstream inFile( myPath.c_str(), ios::in | ios::binary); result = inFile; - if (inFile) { bool datafound = false; - inFile.seekg(4, ios::beg); inFile.read( (char*) &myChunkSize, 4 ); // read the ChunkSize @@ -389,6 +412,16 @@ bool maxiSample::read() length=myDataSize*(0.5/myChannels); inFile.close(); // close the input file + if (myChannels>1) { + int position=0; + int channel=readChannel*2; + for (int i=channel;i<myDataSize+6;i+=(myChannels*2)) { + myData[position]=myData[i]; + myData[position+1]=myData[i+1]; + position+=2; + } + } + }else { cout << "ERROR: Could not load sample: " <<myPath << endl; } @@ -399,18 +432,19 @@ bool maxiSample::read() double maxiSample::play() { -// long length=myDataSize*(1./myChannels); + // long length=myDataSize*(1./myChannels); double remainder; short* buffer = (short *)myData; position=(position+1); remainder = position - (long) position; if ((long) position>length) position=0; - output = (double) ((1-remainder) * buffer[1+ (long) position] + remainder * buffer[2+(long) position])/32767;//linear interpolation + output = + (double) ((1-remainder) * buffer[1+ (long) position] + remainder * buffer[2+(long) position])/32767;//linear interpolation return(output); } double maxiSample::playOnce() { -// long length=myDataSize*(0.5/myChannels); + // long length=myDataSize*(0.5/myChannels); double remainder; short* buffer = (short *)myData; position=(position+1); @@ -419,14 +453,27 @@ double maxiSample::playOnce() { output = (double) ((1-remainder) * buffer[1+ (long) position] + remainder * buffer[2+(long) position])/32767;//linear interpolation else output=0; + + return(output); +} +double maxiSample::playOnce(double speed) { + double remainder; + //long a,b; + // long length=myDataSize*0.5; + short* buffer = (short *)myData; + position=position+((speed*chandiv*myChannels)/(maxiSettings::sampleRate/mySampleRate)); + if ((long) position<length) + output = (double) ((1-remainder) * buffer[1+ (long) position] + remainder * buffer[2+(long) position])/32767;//linear interpolation + else + output=0; return(output); } double maxiSample::play(double speed) { double remainder; long a,b; -// long length=myDataSize*0.5; + // long length=myDataSize*0.5; short* buffer = (short *)myData; position=position+((speed*chandiv*myChannels)/(maxiSettings::sampleRate/mySampleRate)); if (speed >=0) { @@ -442,29 +489,29 @@ double maxiSample::play(double speed) { } if (position+2<length) { - b=position+2; + b=position+2; } else { - b=length-1; + b=length-1; } output = (double) ((1-remainder) * buffer[a] + remainder * buffer[b])/32767;//linear interpolation -} else { + } else { if ((long) position<0) position=length; remainder = position - floor(position); if (position-1>=0) { a=position-1; - - } - else { - a=0; - } - if (position-2>=0) { - b=position-2; - } - else { - b=0; - } + + } + else { + a=0; + } + if (position-2>=0) { + b=position-2; + } + else { + b=0; + } output = (double) ((-1-remainder) * buffer[a] + remainder * buffer[b])/32767;//linear interpolation } return(output); @@ -477,7 +524,7 @@ double maxiSample::play(double frequency, double start, double end) { double maxiSample::play(double frequency, double start, double end, double &pos) { double remainder; // long length=myDataSize; - + if (end>=length) end=length-1; long a,b; short* buffer = (short *)myData; @@ -503,7 +550,7 @@ double maxiSample::play(double frequency, double start, double end, double &pos) else { b=length-1; } - + output = (double) ((1-remainder) * buffer[a] + remainder * buffer[b])/32767;//linear interpolation } else { @@ -547,7 +594,7 @@ double maxiSample::play4(double frequency, double start, double end) { remainder = position - floor(position); if (position>0) { a=buffer[(int)(floor(position))-1]; - + } else { a=buffer[0]; @@ -556,14 +603,14 @@ double maxiSample::play4(double frequency, double start, double end) { b=buffer[(long) position]; if (position<end-2) { c=buffer[(long) position+1]; - + } else { c=buffer[0]; - + } if (position<end-3) { d=buffer[(long) position+2]; - + } else { d=buffer[0]; } @@ -803,3 +850,178 @@ void maxiSample::getLength() { } +/* OK this compressor and gate are now ready to use. The envelopes, like all the envelopes in this recent update, use stupid algorithms for + incrementing - consequently a long attack is something like 0.0001 and a long release is like 0.9999. + Annoyingly, a short attack is 0.1, and a short release is 0.99. I'll sort this out laters */ + +double maxiDyn::gate(double input, double threshold, long holdtime, double attack, double release) { + + if (fabs(input)>threshold && attackphase!=1){ + holdcount=0; + releasephase=0; + attackphase=1; + if(amplitude==0) amplitude=0.01; + } + + if (attackphase==1 && amplitude<1) { + amplitude*=(1+attack); + output=input*amplitude; + } + + if (amplitude>=1) { + attackphase=0; + holdphase=1; + } + + if (holdcount<holdtime && holdphase==1) { + output=input; + holdcount++; + } + + if (holdcount==holdtime) { + holdphase=0; + releasephase=1; + } + + if (releasephase==1 && amplitude>0.) { + output=input*(amplitude*=release); + + } + + return output; +} + + +double maxiDyn::compressor(double input, double ratio, double threshold, double attack, double release) { + + if (fabs(input)>threshold && attackphase!=1){ + holdcount=0; + releasephase=0; + attackphase=1; + if(currentRatio==0) currentRatio=ratio; + } + + if (attackphase==1 && currentRatio<ratio-1) { + currentRatio*=(1+attack); + } + + if (currentRatio>=ratio-1) { + attackphase=0; + releasephase=1; + } + + if (releasephase==1 && currentRatio>0.) { + currentRatio*=release; + } + + if (input>0.) { + output = input/(1.+currentRatio); + } else { + output = input/(1.+currentRatio); + } + + return output*(1+log(ratio)); +} + + +/* Lots of people struggle with the envelope generators so here's a new easy one. + It takes mental numbers for attack and release tho. Basically, they're exponentials. + I'll map them out later so that it's a bit more intuitive */ +double maxiEnv::ar(double input, double attack, double release, long holdtime, int trigger) { + + if (trigger==1 && attackphase!=1 && holdphase!=1){ + holdcount=0; + releasephase=0; + attackphase=1; + } + + if (attackphase==1) { + amplitude+=(1*attack); + output=input*amplitude; + } + + if (amplitude>=1) { + amplitude=1; + attackphase=0; + holdphase=1; + } + + if (holdcount<holdtime && holdphase==1) { + output=input; + holdcount++; + } + + if (holdcount==holdtime && trigger==1) { + output=input; + } + + if (holdcount==holdtime && trigger!=1) { + holdphase=0; + releasephase=1; + } + + if (releasephase==1 && amplitude>0.) { + output=input*(amplitude*=release); + + } + + return output; +} + +/* and here's a new adsr. It's not bad, very simple to use*/ + +double maxiEnv::adsr(double input, double attack, double decay, double sustain, double release, long holdtime, int trigger) { + + if (trigger==1 && attackphase!=1 && holdphase!=1 && decayphase!=1){ + holdcount=0; + decayphase=0; + sustainphase=0; + releasephase=0; + attackphase=1; + } + + if (attackphase==1) { + amplitude+=(1*attack); + output=input*amplitude; + } + + if (amplitude>=1) { + amplitude=1; + attackphase=0; + decayphase=1; + } + + if (decayphase==1) { + output=input*(amplitude*=decay); + if (amplitude<=sustain) { + decayphase=0; + holdphase=1; + } + } + + if (holdcount<holdtime && holdphase==1) { + output=input*amplitude; + holdcount++; + } + + if (holdcount==holdtime && trigger==1) { + output=input*amplitude; + } + + if (holdcount==holdtime && trigger!=1) { + holdphase=0; + releasephase=1; + } + + if (releasephase==1 && amplitude>0.) { + output=input*(amplitude*=release); + + } + + return output; +} + +double convert::mtof(int midinote) { + + return mtofarray[midinote]; +}
\ No newline at end of file diff --git a/ofxMaxim/ofxMaxim/libs/maximilian.h b/ofxMaxim/ofxMaxim/libs/maximilian.h index 2031940..102d552 100755 --- a/ofxMaxim/ofxMaxim/libs/maximilian.h +++ b/ofxMaxim/ofxMaxim/libs/maximilian.h @@ -70,7 +70,7 @@ class maxiOsc { double endphase; double output; double tri; - + public: maxiOsc(); @@ -79,12 +79,13 @@ public: double phasor(double frequency); double phasor(double frequency, double startphase, double endphase); double saw(double frequency); - double triangle(double frequency,double phase); + double triangle(double frequency); double square(double frequency); double pulse(double frequency, double duty); double noise(); double sinebuf(double frequency); double sinebuf4(double frequency); + void phaseReset(double phaseIn); }; @@ -96,6 +97,7 @@ class maxiEnvelope { double startval; double currentval; double nextval; + int isPlaying; public: double line(int numberofsegments,double segments[100]); @@ -115,9 +117,10 @@ class maxiDelayline { double memory[88200]; public: + maxiDelayline(); double dl(double input, int size, double feedback); double dl(double input, int size, double feedback, int position); - + }; @@ -160,13 +163,13 @@ public: }; - class maxiSample { private: string myPath; int myChunkSize; int mySubChunk1Size; + int readChannel; short myFormat; int myByteRate; short myBlockAlign; @@ -181,11 +184,12 @@ public: int mySampleRate; long length; void getLength(); - + + char* myData; // get/set for the Path property - + ~maxiSample() { if (myData) delete[] myData; @@ -201,8 +205,8 @@ public: } maxiSample():myData(NULL){}; - - bool load(string fileName); + + bool load(string fileName, int channel=0); void trigger(); @@ -213,12 +217,14 @@ public: double playOnce(); + double playOnce(double speed); + double play(double speed); double play(double frequency, double start, double end, double &pos); double play(double frequency, double start, double end); - + double play4(double frequency, double start, double end); double bufferPlay(unsigned char &bufferin,long length); @@ -304,7 +310,7 @@ public: val = max(min(val, inMax), inMin); return pow((outMax / outMin), (val - inMin) / (inMax - inMin)) * outMin; } - + static double inline explin(double val, double inMin, double inMax, double outMin, double outMax) { //clipping val = max(min(val, inMax), inMin); @@ -314,4 +320,47 @@ public: }; +class maxiDyn { + + +public: + double gate(double input, double threshold=0.9, long holdtime=1, double attack=1, double release=0.9995); + double compressor(double input, double ratio, double threshold=0.9, double attack=1, double release=0.9995); + double input; + double ratio; + double currentRatio; + double threshold; + double output; + double attack; + double release; + double amplitude; + long holdtime; + long holdcount; + int attackphase,holdphase,releasephase; +}; + +class maxiEnv { + + +public: + double ar(double input, double attack=1, double release=0.9, long holdtime=1, int trigger=0); + double adsr(double input, double attack=1, double decay=0.99, double sustain=0.125, double release=0.9, long holdtime=1, int trigger=0); + double input; + double output; + double attack; + double decay; + double sustain; + double release; + double amplitude; + int trigger; + long holdtime; + long holdcount; + int attackphase,decayphase,sustainphase,holdphase,releasephase; +}; + +class convert { +public: + double mtof(int midinote); +}; + #endif |
