diff --git a/maximilian.cpp b/maximilian.cpp index 41ce498d..4b98bde4 100644 --- a/maximilian.cpp +++ b/maximilian.cpp @@ -16,11 +16,11 @@ * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: - * + * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -34,7 +34,7 @@ #include "maximilian.h" #include "math.h" -/* Maximilian can be configured to load ogg vorbis format files using the +/* Maximilian can be configured to load ogg vorbis format files using the * loadOgg() method. * Uncomment the following to include Sean Barrett's Ogg Vorbis decoder. * If you're on windows, make sure to add the files std_vorbis.c and std_vorbis.h to your project*/ @@ -55,7 +55,7 @@ int maxiSettings::channels = 2; int maxiSettings::bufferSize = 1024; -//this is a 514-point sinewave table that has many uses. +//this is a 514-point sinewave table that has many uses. 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 }; @@ -200,7 +200,7 @@ double mtofarray[129]={0, 8.661957, 9.177024, 9.722718, 10.3, 10.913383, 11.5623 void setup();//use this to do any initialisation if you want. -void play(double *channels);//run dac! +void play(double *channels);//run dac! maxiOsc::maxiOsc(){ //When you create an oscillator, the constructor sets the phase of the oscillator to 0. @@ -218,7 +218,7 @@ double maxiOsc::noise() { void maxiOsc::phaseReset(double phaseIn) { //This allows you to set the phase of the oscillator to anything you like. phase=phaseIn; - + } double maxiOsc::sinewave(double frequency) { @@ -227,7 +227,7 @@ double maxiOsc::sinewave(double frequency) { if ( phase >= 1.0 ) phase -= 1.0; phase += (1./(maxiSettings::sampleRate/(frequency))); return(output); - + } double maxiOsc::sinebuf4(double frequency) { @@ -237,21 +237,21 @@ double maxiOsc::sinebuf4(double frequency) { phase += 512./(maxiSettings::sampleRate/(frequency)); if ( phase >= 511 ) phase -=512; remainder = phase - floor(phase); - + if (phase==0) { a=sineBuffer[(long) 512]; b=sineBuffer[(long) phase]; c=sineBuffer[(long) phase+1]; d=sineBuffer[(long) phase+2]; - + } else { a=sineBuffer[(long) phase-1]; b=sineBuffer[(long) phase]; c=sineBuffer[(long) phase+1]; d=sineBuffer[(long) phase+2]; - + } - + a1 = 0.5f * (c - a); a2 = a - 2.5 * b + 2.f * c - 0.5f * d; a3 = 0.5f * (d - a) + 1.5f * (b - c); @@ -275,16 +275,16 @@ double maxiOsc::coswave(double frequency) { if ( phase >= 1.0 ) phase -= 1.0; phase += (1./(maxiSettings::sampleRate/(frequency))); return(output); - + } double maxiOsc::phasor(double frequency) { - //This produces a floating point linear ramp between 0 and 1 at the desired frequency + //This produces a floating point linear ramp between 0 and 1 at the desired frequency output=phase; if ( phase >= 1.0 ) phase -= 1.0; phase += (1./(maxiSettings::sampleRate/(frequency))); return(output); -} +} double maxiOsc::square(double frequency) { //This is a square wave @@ -307,7 +307,7 @@ double maxiOsc::pulse(double frequency, double duty) { } double maxiOsc::phasor(double frequency, double startphase, double endphase) { - //This is a phasor that takes a value for the start and end of the ramp. + //This is a phasor that takes a value for the start and end of the ramp. output=phase; if (phase= 1.0 ) phase -= 2.0; phase += (1./(maxiSettings::sampleRate/(frequency))); return(output); - + } double maxiOsc::sawn(double frequency) { @@ -343,7 +343,7 @@ double maxiOsc::sawn(double frequency) { double remainder = temp - floor(temp); output = (double) ((1.0f-remainder) * transition[(long)temp] + remainder * transition[1+(long)temp]) - phase; return(output); - + } double maxiOsc::rect(double frequency, double duty) { @@ -361,8 +361,8 @@ double maxiOsc::triangle(double frequency) { output =((1.0-phase) - 0.25) * 4; } return(output); - -} + +} // don't use this nonsense. Use ramps instead. // ..er... I mean "This method is deprecated" @@ -384,11 +384,11 @@ double maxiEnvelope::line(int numberofsegments,double segments[1000]) { startVal=currentval; } output=amplitude; - + } else { output=0; - + } return(output); } @@ -398,11 +398,11 @@ void maxiEnvelope::trigger(int index, double amp) { isPlaying=1;//ok the envelope is being used now. valindex=index; amplitude=amp; - + } void maxiEnvelope::trigger(bool noteOn) { - + if (noteOn) trig=1; if (noteOn==false) trig=0; @@ -417,39 +417,39 @@ double maxiEnvelope::ramp(double startVal, double endVal, double duration){ } if (isPlaying) { - + if (startVal= endVal ) phase = endVal; } - + if (startVal > endVal) { phase += ((endVal-startVal)/(maxiSettings::sampleRate/(1./duration))); if ( phase <= endVal ) phase = endVal; } return(phase); } else { - + return(0); - + } - + } double maxiEnvelope::ramps(std::vector rampsArray){ - + if (trig!=0) { valindex=0; endVal=rampsArray[valindex+1]; isPlaying=true; trig=0; - + } - + if (isPlaying) { - + if (valindex>0 && rampsArray[valindex-1]==rampsArray[valindex+1]) { period += (1/(maxiSettings::sampleRate/(1./rampsArray[valindex]))); if (period>=1) { @@ -462,7 +462,7 @@ double maxiEnvelope::ramps(std::vector rampsArray){ } } output=phase; } - + if (valindex==0 && output==endVal) { period += (1/(maxiSettings::sampleRate/(1./rampsArray[valindex]))); if (period>=1) { @@ -475,7 +475,7 @@ double maxiEnvelope::ramps(std::vector rampsArray){ } } output=phase; } - + if (phase= endVal ) { @@ -489,7 +489,7 @@ double maxiEnvelope::ramps(std::vector rampsArray){ } output=phase; } - + if (phase > endVal) { phase += ((endVal-startVal)/(maxiSettings::sampleRate/(1./rampsArray[valindex]))); if ( phase <= endVal ) { @@ -502,17 +502,17 @@ double maxiEnvelope::ramps(std::vector rampsArray){ } } output=phase; } - + return(output); - + } else { - + return(0); } } double maxiEnvelope::ar(double attack, double release) { - + if (trig!=0) { //phase=0; releaseMode=false; @@ -526,18 +526,18 @@ double maxiEnvelope::ar(double attack, double release) { releaseMode=true; }; } - + if (releaseMode==true) { phase += ((-1)/(maxiSettings::sampleRate/(1./release))); if ( phase <= 0 ) phase = 0; } - + return phase; } double maxiEnvelope::adsr(double attack, double decay, double sustain, double release) { - + if (trig!=0 && !attackMode) { // phase=0.; releaseMode=false; @@ -546,7 +546,7 @@ double maxiEnvelope::adsr(double attack, double decay, double sustain, double re attackMode=true; trig=0; } - + if (attackMode) { phase += ((1)/(maxiSettings::sampleRate/(1./attack))); @@ -556,7 +556,7 @@ double maxiEnvelope::adsr(double attack, double decay, double sustain, double re decayMode=true; }; } - + if (decayMode) { phase += ((-1)/(maxiSettings::sampleRate/(1./decay))); if ( phase <= sustain ) { @@ -565,19 +565,19 @@ double maxiEnvelope::adsr(double attack, double decay, double sustain, double re sustainMode=true; }; } - + if (sustainMode) { if (noteOn) { phase=sustain; } - + if (!noteOn) { sustainMode=false; releaseMode=true; } } - + if (releaseMode) { phase += ((-sustain)/(maxiSettings::sampleRate/(1./release))); if ( phase <= 0 ) { @@ -585,14 +585,14 @@ double maxiEnvelope::adsr(double attack, double decay, double sustain, double re releaseMode=false; } } - + return phase; } //Delay with feedback maxiDelayline::maxiDelayline() { - memset( memory, 0, 88200*sizeof (double) ); + memset( memory, 0, 88200*sizeof (double) ); } @@ -604,7 +604,7 @@ double maxiDelayline::dl(double input, int size, double feedback) { memory[phase]=(memory[phase]*feedback)+(input*feedback)*0.5; phase+=1; return(output); - + } double maxiDelayline::dl(double input, int size, double feedback, int position) { @@ -614,7 +614,7 @@ double maxiDelayline::dl(double input, int size, double feedback, int position) memory[phase]=(memory[phase]*feedback)+(input*feedback)*chandiv; phase+=1; return(output); - + } maxiFractionalDelay::maxiFractionalDelay ( void ) { @@ -628,27 +628,27 @@ double maxiFractionalDelay::dl ( double sig, double delayTime, double feedback ) int32_t delay = delayTime; // Truncated double fractAmount = delayTime - delay; // Fractional remainder double truncAmount = 1.0f - fractAmount; // Inverse fractional remainder - + // Update read pointer readPointer = writePointer - delay; if (readPointer < 0) readPointer += delaySize; - + int readPointerFractPart = readPointer-1; if (readPointerFractPart < 0) readPointerFractPart += delaySize; - + // Get interpolated sample double y = memory[readPointer] * truncAmount + memory[readPointerFractPart] * fractAmount; - + // Write new sample memory[writePointer] = y * feedback + sig; - + // Increment write pointer if (++writePointer >= delaySize) writePointer -= delaySize; return y; - + } @@ -706,7 +706,7 @@ double maxiFilter::bandpass(double input,double cutoff1, double resonance) { inputs[0] = (1-resonance)*(sqrt(resonance*(resonance-4.0*pow(z,2.0)+2.0)+1)); inputs[1] = 2*z*resonance; inputs[2] = pow((resonance*-1),2); - + output=inputs[0]*input+inputs[1]*outputs[1]+inputs[2]*outputs[2]; outputs[2]=outputs[1]; outputs[1]=output; @@ -720,7 +720,7 @@ double *maxiMix::stereo(double input,double two[2],double x) { two[0]=input*sqrt(1.0-x); two[1]=input*sqrt(x); return(two); -} +} //quad bus double *maxiMix::quad(double input,double four[4],double x,double y) { @@ -776,7 +776,7 @@ bool maxiSample::loadOgg(string fileName, int channel) { myChannels=(short)channelx; length=myDataSize; mySampleRate=44100; - + if (myChannels>1) { int position=0; int channel=readChannel; @@ -808,28 +808,28 @@ bool maxiSample::read() bool datafound = false; inFile.seekg(4, ios::beg); inFile.read( (char*) &myChunkSize, 4 ); // read the ChunkSize - + inFile.seekg(16, ios::beg); inFile.read( (char*) &mySubChunk1Size, 4 ); // read the SubChunk1Size - + //inFile.seekg(20, ios::beg); inFile.read( (char*) &myFormat, sizeof(short) ); // read the file format. This should be 1 for PCM - + //inFile.seekg(22, ios::beg); inFile.read( (char*) &myChannels, sizeof(short) ); // read the # of channels (1 or 2) - + //inFile.seekg(24, ios::beg); inFile.read( (char*) &mySampleRate, sizeof(int) ); // read the samplerate - + //inFile.seekg(28, ios::beg); inFile.read( (char*) &myByteRate, sizeof(int) ); // read the byterate - + //inFile.seekg(32, ios::beg); inFile.read( (char*) &myBlockAlign, sizeof(short) ); // read the blockalign - + //inFile.seekg(34, ios::beg); inFile.read( (char*) &myBitsPerSample, sizeof(short) ); // read the bitspersample - + //ignore any extra chunks char chunkID[5]=""; chunkID[4] = 0; @@ -846,14 +846,14 @@ bool maxiSample::read() filePos += myDataSize; } } - + // read the data chunk char * myData = (char*) malloc(myDataSize * sizeof(char)); inFile.seekg(filePos, ios::beg); inFile.read(myData, myDataSize); length=myDataSize*(0.5/myChannels); inFile.close(); // close the input file - + cout << "Ch: " << myChannels << ", len: " << length << endl; if (myChannels>1) { int position=0; @@ -867,16 +867,16 @@ bool maxiSample::read() free(temp); temp = (short*) malloc(myDataSize * sizeof(char)); memcpy(temp, myData, myDataSize * sizeof(char)); - + free(myData); - + }else { -// cout << "ERROR: Could not load sample: " <=0) { - + if ((long) position>=length-1) position=1; remainder = position - floor(position); if (position+1=0) { a=position-1; - + } else { a=0; @@ -977,7 +977,7 @@ double maxiSample::play(double speed) { b=0; } output = (double) ((-1-remainder) * temp[a] + remainder * temp[b])/32767;//linear interpolation - } + } return(output); } @@ -996,14 +996,14 @@ double maxiSample::play(double frequency, double start, double end, double &pos) if (pos= end ) pos = start; pos += ((end-start)/((maxiSettings::sampleRate)/(frequency*chandiv))); remainder = pos - floor(pos); long posl = floor(pos); if (posl+1start && position < end-1) { a=temp[(long) position+1]; - + } else { a=temp[0]; - + } - + b=temp[(long) position]; if (position>start) { c=temp[(long) position-1]; - + } else { c=temp[0]; - + } if (position>start+1) { d=temp[(long) position-2]; - + } else { d=temp[0]; } @@ -1113,9 +1113,9 @@ double maxiSample::play4(double frequency, double start, double end) { a2 = a - 2.5 * b + 2.f * c - 0.5f * d; a3 = 0.5f * (d - a) + 1.5f * (b - c); output = (double) (((a3 * remainder + a2) * -remainder + a1) * -remainder + b) / 32767; - + } - + return(output); } @@ -1137,12 +1137,12 @@ double maxiSample::bufferPlay(unsigned char &bufferin,double speed,long length) short* buffer = (short *)&bufferin; position=position+((speed*chandiv)/(maxiSettings::sampleRate/mySampleRate)); if (speed >=0) { - + if ((long) position>=length-1) position=1; remainder = position - floor(position); if (position+1=0) { a=position-1; - + } else { a=0; @@ -1173,7 +1173,7 @@ double maxiSample::bufferPlay(unsigned char &bufferin,double speed,long length) b=0; } output = (double) ((-1-remainder) * buffer[a] + remainder * buffer[b])/32767;//linear interpolation - } + } return(output); } @@ -1186,14 +1186,14 @@ double maxiSample::bufferPlay(unsigned char &bufferin,double frequency, double s if (position= end ) position = start; position += ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv))); remainder = position - floor(position); long pos = floor(position); if (pos+10) { a=buffer[(int)(floor(position))-1]; - + } else { a=buffer[0]; - + } - + b=buffer[(long) position]; if (positionstart && position < end-1) { a=buffer[(long) position+1]; - + } else { a=buffer[0]; - + } - + b=buffer[(long) position]; if (position>start) { c=buffer[(long) position-1]; - + } else { c=buffer[0]; - + } if (position>start+1) { d=buffer[(long) position-2]; - + } else { d=buffer[0]; } @@ -1303,9 +1303,9 @@ double maxiSample::bufferPlay4(unsigned char &bufferin,double frequency, double a2 = a - 2.5 * b + 2.f * c - 0.5f * d; a3 = 0.5f * (d - a) + 1.5f * (b - c); output = (double) (((a3 * remainder + a2) * -remainder + a1) * -remainder + b) / 32767; - + } - + return(output); } @@ -1350,7 +1350,7 @@ void maxiSample::normalise(float maxLevel) { } void maxiSample::autoTrim(float alpha, float threshold, bool trimStart, bool trimEnd) { - + int startMarker=0; if(trimStart) { maxiLagExp startLag(alpha, 0); @@ -1362,7 +1362,7 @@ void maxiSample::autoTrim(float alpha, float threshold, bool trimStart, bool tri startMarker++; } } - + int endMarker = int(length-1); if(trimEnd) { maxiLagExp endLag(alpha, 0); @@ -1374,9 +1374,9 @@ void maxiSample::autoTrim(float alpha, float threshold, bool trimStart, bool tri endMarker--; } } - + cout << "Autotrim: start: " << startMarker << ", end: " << endMarker << endl; - + int newLength = endMarker - startMarker; if (newLength > 0) { short *newData = (short*) malloc(sizeof(short) * newLength); @@ -1403,107 +1403,107 @@ void maxiSample::autoTrim(float alpha, float threshold, bool trimStart, bool tri -/* OK this compressor and gate are now ready to use. The envelopes, like all the envelopes in this recent update, use stupid algorithms for +/* 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){ + + 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 (holdcount0.) { 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){ + + if (fabs(input)>threshold && attackphase!=1){ holdcount=0; releasephase=0; attackphase=1; if(currentRatio==0) currentRatio=ratio; } - + if (attackphase==1 && currentRatio=ratio-1) { attackphase=0; releasephase=1; } - + if (releasephase==1 && currentRatio>0.) { - currentRatio*=release; + currentRatio*=release; } - + if (input>0.) { output = input/(1.+currentRatio); } else { output = input/(1.+currentRatio); } - + return output*(1+log(ratio)); } double maxiDyn::compress(double input) { - + if (fabs(input)>threshold && attackphase!=1){ holdcount=0; releasephase=0; attackphase=1; if(currentRatio==0) currentRatio=ratio; } - + if (attackphase==1 && 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)); } @@ -1512,50 +1512,50 @@ double maxiDyn::compress(double input) { 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){ + + 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 (holdcount0.) { output=input*(amplitude*=release); - + } - + return output; } /* 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; @@ -1563,52 +1563,59 @@ double maxiEnv::adsr(double input, double attack, double decay, double sustain, releasephase=0; attackphase=1; } - + if (attackphase==1) { releasephase=0; 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 (trigger != 1) + { + holdcount = holdtime; + decayphase = 0; + holdphase = 1; + } + else if (amplitude <= sustain) + { + decayphase = 0; + holdphase = 1; + } } - + 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 maxiEnv::adsr(double input, int trigger) { - + if (trigger==1 && attackphase!=1 && holdphase!=1 && decayphase!=1){ holdcount=0; decayphase=0; @@ -1616,47 +1623,54 @@ double maxiEnv::adsr(double input, int trigger) { releasephase=0; attackphase=1; } - + if (attackphase==1) { releasephase=0; 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 (trigger != 1) + { + holdcount = holdtime; + decayphase = 0; + holdphase = 1; + } + else if (amplitude <= sustain) + { + decayphase = 0; + holdphase = 1; + } } - + 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; } @@ -1715,13 +1729,13 @@ template<> void maxiEnvelopeFollower::setAttack(double attackMS) { } template<> void maxiEnvelopeFollower::setRelease(double releaseMS) { - release = pow( 0.01, 1.0 / ( releaseMS * maxiSettings::sampleRate * 0.001 ) ); + release = pow( 0.01, 1.0 / ( releaseMS * maxiSettings::sampleRate * 0.001 ) ); } double pitchRatios[256]= {0.0006517771980725,0.0006905338959768,0.0007315951515920, 0.0007750981021672, 0.0008211878011934, 0.0008700182079338, 0.0009217521874234, 0.0009765623835847, 0.0010346318595111, 0.0010961542138830, 0.0011613349197432, 0.0012303915573284, 0.0013035543961450, 0.0013810677919537, 0.0014631903031841, 0.0015501962043345, 0.0016423756023869, 0.0017400364158675, 0.0018435043748468, 0.0019531247671694, 0.0020692637190223, 0.0021923084277660, 0.0023226698394865, 0.0024607831146568, 0.0026071087922901, 0.0027621355839074, 0.0029263808391988, 0.0031003924086690, 0.0032847514376044, 0.0034800728317350, 0.0036870087496936, 0.0039062497671694, 0.0041385274380445, 0.0043846168555319, 0.0046453396789730, 0.0049215662293136, 0.0052142175845802, 0.0055242711678147, 0.0058527616783977, 0.0062007848173380, 0.0065695028752089, 0.0069601456634700, 0.0073740174993873, 0.0078124995343387, 0.0082770548760891, 0.0087692337110639, 0.0092906802892685, 0.0098431324586272, 0.0104284351691604, 0.0110485423356295, 0.0117055233567953, 0.0124015696346760, 0.0131390057504177, 0.0139202913269401, 0.0147480349987745, 0.0156249990686774, 0.0165541097521782, 0.0175384692847729, 0.0185813605785370, 0.0196862649172544, 0.0208568722009659, 0.0220970865339041, 0.0234110467135906, 0.0248031392693520, 0.0262780115008354, 0.0278405826538801, 0.0294960699975491, 0.0312499981373549, 0.0331082195043564, 0.0350769385695457, 0.0371627211570740, 0.0393725298345089, 0.0417137444019318, 0.0441941730678082, 0.0468220934271812, 0.0496062822639942, 0.0525560230016708, 0.0556811690330505, 0.0589921437203884, 0.0624999962747097, 0.0662164390087128, 0.0701538771390915, 0.0743254423141479, 0.0787450596690178, 0.0834274888038635, 0.0883883461356163, 0.0936441868543625, 0.0992125645279884, 0.1051120460033417, 0.1113623380661011, 0.1179842874407768, 0.1249999925494194, 0.1324328780174255, 0.1403077542781830, 0.1486508846282959, 0.1574901193380356, 0.1668549776077271, 0.1767766922712326, 0.1872883737087250, 0.1984251290559769, 0.2102240920066833, 0.2227246761322021, 0.2359685748815536, 0.2500000000000000, 0.2648657560348511, 0.2806155085563660, 0.2973017692565918, 0.3149802684783936, 0.3337099552154541, 0.3535533845424652, 0.3745767772197723, 0.3968502581119537, 0.4204482138156891, 0.4454493522644043, 0.4719371497631073, 0.5000000000000000, 0.5297315716743469, 0.5612310171127319, 0.5946035385131836, 0.6299605369567871, 0.6674199104309082, 0.7071067690849304, 0.7491535544395447, 0.7937005162239075, 0.8408964276313782, 0.8908987045288086, 0.9438742995262146, 1.0000000000000000, 1.0594631433486938, 1.1224620342254639, 1.1892070770263672, 1.2599210739135742, 1.3348398208618164, 1.4142135381698608, 1.4983071088790894, 1.5874010324478149, 1.6817928552627563, 1.7817974090576172, 1.8877485990524292, 2.0000000000000000, 2.1189262866973877, 2.2449240684509277, 2.3784141540527344, 2.5198421478271484, 2.6696796417236328, 2.8284270763397217, 2.9966142177581787, 3.1748020648956299, 3.3635857105255127, 3.5635950565338135, 3.7754974365234375, 4.0000000000000000, 4.2378525733947754, 4.4898481369018555, 4.7568287849426270, 5.0396842956542969, 5.3393597602844238, 5.6568546295166016, 5.9932284355163574, 6.3496046066284180, 6.7271714210510254, 7.1271901130676270, 7.5509948730468750, 8.0000000000000000, 8.4757051467895508, 8.9796962738037109, 9.5136575698852539, 10.0793685913085938, 10.6787195205688477, 11.3137092590332031, 11.9864568710327148, 12.6992092132568359, 13.4543428421020508, 14.2543802261352539, 15.1019897460937500, 16.0000000000000000, 16.9514102935791016, 17.9593944549560547, 19.0273151397705078, 20.1587371826171875, 21.3574390411376953, 22.6274185180664062, 23.9729137420654297, 25.3984184265136719, 26.9086875915527344, 28.5087604522705078, 30.2039794921875000, 32.0000000000000000, 33.9028205871582031, 35.9187889099121094, 38.0546302795410156, 40.3174743652343750, 42.7148780822753906, 45.2548370361328125, 47.9458274841308594, 50.7968368530273438, 53.8173751831054688, 57.0175209045410156, 60.4079589843750000, 64.0000076293945312, 67.8056411743164062, 71.8375778198242188, 76.1092605590820312, 80.6349563598632812, 85.4297561645507812, 90.5096740722656250, 95.8916625976562500, 101.5936737060546875, 107.6347503662109375, 114.0350418090820312, 120.8159179687500000, 128.0000152587890625, 135.6112823486328125, 143.6751556396484375, 152.2185211181640625, 161.2699127197265625, 170.8595123291015625, 181.0193481445312500, 191.7833251953125000, 203.1873474121093750, 215.2695007324218750, 228.0700836181640625, 241.6318511962890625, 256.0000305175781250, 271.2225646972656250, 287.3503112792968750, 304.4370422363281250, 322.5398254394531250, 341.7190246582031250, 362.0386962890625000, 383.5666503906250000, 406.3746948242187500, 430.5390014648437500, 456.1401977539062500, 483.2637023925781250, 512.0000610351562500, 542.4451293945312500, 574.7006225585937500, 608.8740844726562500, 645.0796508789062500, 683.4380493164062500, 724.0773925781250000, 767.1333007812500000, 812.7494506835937500, 861.0780029296875000, 912.2803955078125000, 966.5274047851562500, 1024.0001220703125000, 1084.8903808593750000, 1149.4012451171875000, 1217.7481689453125000, 1290.1593017578125000, 1366.8762207031250000, 1448.1549072265625000, 1534.2666015625000000, 1625.4989013671875000}; maxiKick::maxiKick(){ - + maxiKick::envelope.setAttack(0); maxiKick::setPitch(200); maxiKick::envelope.setDecay(1); @@ -1729,81 +1743,81 @@ maxiKick::maxiKick(){ maxiKick::envelope.setRelease(500); maxiKick::envelope.holdtime=1; maxiKick::envelope.trigger=0; - + }; double maxiKick::play(){ - + envOut=envelope.adsr(1.,envelope.trigger); - + if (inverse) { - + envOut=fabs(1-envOut); - + } - + output=kick.sinewave(pitch*envOut)*envOut; - + if (envelope.trigger==1) { envelope.trigger=0; } - + if (useDistortion) { - + output=distort.fastAtanDist(output, distortion); } - + if (useFilter) { - + output=filter.lores(output, cutoff, resonance); - + } - + if (useLimiter) { - + if (output*gain > 1) { - + return 1.; - + } else if (output*gain < -1) { - + return -1.; - + } else { - + return output*gain; - + } - - - + + + } else { - + return output*gain; - + } }; void maxiKick::setRelease(double release) { - + envelope.setRelease(release); - + } void maxiKick::setPitch(double newPitch) { - + pitch=newPitch; - + } void maxiKick::trigger() { - + envelope.trigger=1; - + } maxiSnare::maxiSnare(){ - + maxiSnare::envelope.setAttack(0); maxiSnare::setPitch(800); maxiSnare::envelope.setDecay(20); @@ -1811,82 +1825,82 @@ maxiSnare::maxiSnare(){ maxiSnare::envelope.setRelease(300); maxiSnare::envelope.holdtime=1; maxiSnare::envelope.trigger=0; - + }; double maxiSnare::play(){ - + envOut=envelope.adsr(1.,envelope.trigger); - + if (inverse) { - + envOut=fabs(1-envOut); - + } - + output=(tone.triangle(pitch*(0.1+(envOut*0.85)))+noise.noise())*envOut; - + if (envelope.trigger==1) { envelope.trigger=0; } - + if (useDistortion) { - + output=distort.fastAtanDist(output, distortion); } - + if (useFilter) { - + output=filter.lores(output, cutoff, resonance); - + } - + if (useLimiter) { - + if (output*gain > 1) { - + return 1.; - + } else if (output*gain < -1) { - + return -1.; - + } else { - + return output*gain; - + } - - - + + + } else { - + return output*gain; - + } - + }; void maxiSnare::setRelease(double release) { - + envelope.setRelease(release); - + } void maxiSnare::setPitch(double newPitch) { - + pitch=newPitch; - + } void maxiSnare::trigger() { - + envelope.trigger=1; - + } maxiHats::maxiHats(){ - + maxiHats::envelope.setAttack(0); maxiHats::setPitch(12000); maxiHats::envelope.setDecay(20); @@ -1896,131 +1910,131 @@ maxiHats::maxiHats(){ maxiHats::envelope.trigger=0; maxiHats::filter.setCutoff(8000); maxiHats::filter.setResonance(1); - + }; double maxiHats::play(){ - + envOut=envelope.adsr(1.,envelope.trigger); - + if (inverse) { - + envOut=fabs(1-envOut); - + } - + output=(tone.sinebuf(pitch)+noise.noise())*envOut; - + if (envelope.trigger==1) { envelope.trigger=0; } - + if (useDistortion) { - + output=distort.fastAtanDist(output, distortion); } - + if (useFilter) { - + output=filter.play(output, 0., 0., 1., 0.); - + } - + if (useLimiter) { - + if (output*gain > 1) { - + return 1.; - + } else if (output*gain < -1) { - + return -1.; - + } else { - + return output*gain; - + } - - - + + + } else { - + return output*gain; - + } - + }; void maxiHats::setRelease(double release) { - + envelope.setRelease(release); - + } void maxiHats::setPitch(double newPitch) { - + pitch=newPitch; - + } void maxiHats::trigger() { - + envelope.trigger=1; - + } maxiClock::maxiClock() { - + playHead=0; currentCount=0; lastCount=0; bpm=120; ticks=1; maxiClock::setTempo(bpm); - + } void maxiClock::ticker() { - + tick=false; currentCount=floor(timer.phasor(bps));//this sets up a metronome that ticks n times a second - + if (lastCount!=currentCount) {//if we have a new timer int this sample, - + tick=true; playHead++;//iterate the playhead - + } - + } void maxiClock::setTempo(double bpmIn) { - + bpm=bpmIn; bps=(bpm/60.)*ticks; } void maxiClock::setTicksPerBeat(int ticksPerBeat) { - + ticks=ticksPerBeat; maxiClock::setTempo(bpm); - + } maxiSampler::maxiSampler() { - + maxiSampler::voices=32; maxiSampler::currentVoice=0; - - + + for (int i=0;i0.) { outputs[i]=samples[i].play(pitchRatios[(int)pitch[i]+originalPitch]*((1./samples[i].length)*maxiSettings::sampleRate),0,samples[i].length)*envOut[i]; output+=outputs[i]/voices; - + if (envelopes[i].trigger==1 && !sustain) { envelopes[i].trigger=0; - + } - + } - + } return output; - + } void maxiSampler::load(string inFile, bool setall) { - + if (setall) { for (int i=0;i