diff options
Diffstat (limited to 'ofxMaxim/openFrameworksExamples/OSX')
4 files changed, 681 insertions, 375 deletions
diff --git a/ofxMaxim/openFrameworksExamples/OSX/OF0.8.4MaximExtractorExample/ofxMaxim/libs/maximilian.cpp b/ofxMaxim/openFrameworksExamples/OSX/OF0.8.4MaximExtractorExample/ofxMaxim/libs/maximilian.cpp index 18b2af2..7ba4978 100755..100644 --- a/ofxMaxim/openFrameworksExamples/OSX/OF0.8.4MaximExtractorExample/ofxMaxim/libs/maximilian.cpp +++ b/ofxMaxim/openFrameworksExamples/OSX/OF0.8.4MaximExtractorExample/ofxMaxim/libs/maximilian.cpp @@ -325,19 +325,6 @@ double maxiOsc::saw(double frequency) { phase += (1./(maxiSettings::sampleRate/(frequency))); return(output); -} - -double maxiOsc::triangle(double frequency) { - //This is a triangle wave. - if ( phase >= 1.0 ) phase -= 1.0; - phase += (1./(maxiSettings::sampleRate/(frequency))); - if (phase <= 0.5 ) { - output =(phase - 0.25) * 4; - } else { - output =((1.0-phase) - 0.25) * 4; - } - return(output); - } double maxiOsc::sawn(double frequency) { @@ -359,12 +346,29 @@ double maxiOsc::sawn(double frequency) { } +double maxiOsc::rect(double frequency, double duty) { + + return (output); +} + +double maxiOsc::triangle(double frequency) { + //This is a triangle wave. + if ( phase >= 1.0 ) phase -= 1.0; + phase += (1./(maxiSettings::sampleRate/(frequency))); + if (phase <= 0.5 ) { + output =(phase - 0.25) * 4; + } else { + output =((1.0-phase) - 0.25) * 4; + } + return(output); + +} double maxiEnvelope::line(int numberofsegments,double segments[1000]) { //This is a basic multi-segment ramp generator that you can use for more or less anything. //However, it's not that intuitive. if (isPlaying==1) {//only make a sound once you've been triggered - period=2./(segments[valindex+1]*0.004); + period=4./(segments[valindex+1]*0.0044); nextval=segments[valindex+2]; currentval=segments[valindex]; if (currentval-amplitude > 0.0000001 && valindex < numberofsegments) { @@ -397,8 +401,7 @@ void maxiEnvelope::trigger(int index, double amp) { //Delay with feedback maxiDelayline::maxiDelayline() { - memset( memory, 0, 88200*sizeof (double) ); - phase=0; + memset( memory, 0, 88200*sizeof (double) ); } @@ -437,9 +440,9 @@ double maxiFilter::hipass(double input, double cutoff) { } //awesome. cuttof is freq in hz. res is between 1 and whatever. Watch out! double maxiFilter::lores(double input,double cutoff1, double resonance) { - cutoff=cutoff1*0.5; + cutoff=cutoff1; if (cutoff<10) cutoff=10; - if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5); + if (cutoff>(maxiSettings::sampleRate)) cutoff=(maxiSettings::sampleRate); if (resonance<1.) resonance = 1.; z=cos(TWOPI*cutoff/maxiSettings::sampleRate); c=2-2*z; @@ -453,9 +456,9 @@ double maxiFilter::lores(double input,double cutoff1, double resonance) { //working hires filter double maxiFilter::hires(double input,double cutoff1, double resonance) { - cutoff=cutoff1*0.5; + cutoff=cutoff1; if (cutoff<10) cutoff=10; - if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5); + if (cutoff>(maxiSettings::sampleRate)) cutoff=(maxiSettings::sampleRate); if (resonance<1.) resonance = 1.; z=cos(TWOPI*cutoff/maxiSettings::sampleRate); c=2-2*z; @@ -524,18 +527,20 @@ double *maxiMix::ambisonic(double input,double eight[8],double x,double y,double return(eight); } - +//This is the maxiSample load function. It just calls read. bool maxiSample::load(string fileName, int channel) { myPath = fileName; readChannel=channel; return read(); } +// This is for OGG loading bool maxiSample::loadOgg(string fileName, int channel) { #ifdef VORBIS bool result; readChannel=channel; int channelx; +// cout << fileName << endl; free(temp); myDataSize = stb_vorbis_decode_filename(const_cast<char*>(fileName.c_str()), &channelx, &temp); result = myDataSize > 0; @@ -558,11 +563,13 @@ bool maxiSample::loadOgg(string fileName, int channel) { return 0; } +//This sets the playback position to the start of a sample void maxiSample::trigger() { position = 0; recordPosition = 0; } +//This is the main read function. bool maxiSample::read() { bool result; @@ -612,7 +619,7 @@ bool maxiSample::read() } // read the data chunk - char *myData = (char*) malloc(myDataSize * sizeof(char)); + char * myData = (char*) malloc(myDataSize * sizeof(char)); inFile.seekg(filePos, ios::beg); inFile.read(myData, myDataSize); length=myDataSize*(0.5/myChannels); @@ -644,6 +651,7 @@ bool maxiSample::read() return result; // this should probably be something more descriptive } +//This plays back at the correct speed. Always loops. double maxiSample::play() { position++; if ((long) position >= length) position=0; @@ -651,40 +659,43 @@ double maxiSample::play() { return output; } +void maxiSample::setPosition(double newPos) { + position = maxiMap::clamp<double>(newPos, 0.0, 1.0) * length; +} + //start end and points are between 0 and 1 double maxiSample::playLoop(double start, double end) { - position++; + position++; if (position < length * start) position = length * start; - if ((long) position >= length * end) position = length * start; - output = (double) temp[(long)position]/32767.0; - return output; + if ((long) position >= length * end) position = length * start; + output = (double) temp[(long)position]/32767.0; + return output; } -double maxiSample::playOnce() { - position++; - if ((long) position<length) +double maxiSample::playUntil(double end) { + position++; + if ((long) position<length * end) output = (double) temp[(long)position]/32767.0; else { output=0; } - return output; - + return output; } -void maxiSample::setPosition(double newPos) { - position = maxiMap::clamp<double>(newPos, 0.0, 1.0) * length; -} -double maxiSample::playUntil(double end) { +//This plays back at the correct speed. Only plays once. To retrigger, you have to manually reset the position +double maxiSample::playOnce() { position++; - if ((long) position<length * end) + if ((long) position<length) output = (double) temp[(long)position]/32767.0; else { output=0; } return output; + } +//Same as above but takes a speed value specified as a ratio, with 1.0 as original speed double maxiSample::playOnce(double speed) { position=position+((speed*chandiv)/(maxiSettings::sampleRate/mySampleRate)); double remainder = position - (long) position; @@ -695,6 +706,7 @@ double maxiSample::playOnce(double speed) { return(output); } +//As above but looping double maxiSample::play(double speed) { double remainder; long a,b; @@ -740,10 +752,12 @@ double maxiSample::play(double speed) { return(output); } +//placeholder double maxiSample::play(double frequency, double start, double end) { return play(frequency, start, end, position); } +//This allows you to say how often a second you want a specific chunk of audio to play double maxiSample::play(double frequency, double start, double end, double &pos) { double remainder; if (end>=length) end=length-1; @@ -755,7 +769,7 @@ double maxiSample::play(double frequency, double start, double end, double &pos) } if ( pos >= end ) pos = start; - pos += ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv))); + pos += ((end-start)/((maxiSettings::sampleRate)/(frequency*chandiv))); remainder = pos - floor(pos); long posl = floor(pos); if (posl+1<length) { @@ -775,7 +789,7 @@ double maxiSample::play(double frequency, double start, double end, double &pos) output = (double) ((1-remainder) * temp[a] + remainder * temp[b])/32767;//linear interpolation } else { - frequency=frequency-(frequency+frequency); + frequency*=-1.; if ( pos <= start ) pos = end; pos -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv))); remainder = pos - floor(pos); @@ -801,7 +815,7 @@ double maxiSample::play(double frequency, double start, double end, double &pos) } -//better cubic inerpolation. Cobbled together from various (pd externals, yehar, other places). +//Same as above. better cubic inerpolation. Cobbled together from various (pd externals, yehar, other places). double maxiSample::play4(double frequency, double start, double end) { double remainder; double a,b,c,d,a1,a2,a3; @@ -840,7 +854,7 @@ double maxiSample::play4(double frequency, double start, double end) { output = (double) (((a3 * remainder + a2) * remainder + a1) * remainder + b) / 32767; } else { - frequency=frequency-(frequency+frequency); + frequency*=-1.; if ( position <= start ) position = end; position -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv))); remainder = position - floor(position); @@ -876,6 +890,8 @@ double maxiSample::play4(double frequency, double start, double end) { return(output); } + +//You don't need to worry about this stuff. double maxiSample::bufferPlay(unsigned char &bufferin,long length) { double remainder; short* buffer = (short *)&bufferin; @@ -963,7 +979,7 @@ double maxiSample::bufferPlay(unsigned char &bufferin,double frequency, double s output = (double) ((1-remainder) * buffer[a] + remainder * buffer[b])/32767;//linear interpolation } else { - frequency=frequency-(frequency+frequency); + frequency*=-1.; if ( position <= start ) position = end; position -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv))); remainder = position - floor(position); @@ -1028,7 +1044,7 @@ double maxiSample::bufferPlay4(unsigned char &bufferin,double frequency, double output = (double) (((a3 * remainder + a2) * remainder + a1) * remainder + b) / 32767; } else { - frequency=frequency-(frequency+frequency); + frequency*=-1.; if ( position <= start ) position = end; position -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv))); remainder = position - floor(position); @@ -1066,18 +1082,17 @@ double maxiSample::bufferPlay4(unsigned char &bufferin,double frequency, double void maxiSample::getLength() { - length=myDataSize*0.5; + length=myDataSize*0.5; } void maxiSample::setLength(unsigned long numSamples) { - temp = (short*) realloc(temp, sizeof(short) * numSamples); -// short *newData = (short*) malloc(sizeof(short) * numSamples); -// if (NULL!=temp) { -// unsigned long copyLength = min((unsigned long)length, numSamples); -// memcpy(newData, temp, sizeof(short) * copyLength); -// free(temp); -// } -// temp = newData; + cout << "Length: " << numSamples << endl; + short *newData = (short*) malloc(sizeof(short) * numSamples); + if (NULL!=temp) { + unsigned long copyLength = min((unsigned long)length, numSamples); + memcpy(newData, temp, sizeof(short) * copyLength); + } + temp = newData; myDataSize = numSamples * 2; length=numSamples; position=0; @@ -1092,7 +1107,6 @@ void maxiSample::reset() { position=0; } - void maxiSample::normalise(float maxLevel) { short maxValue = 0; for(int i=0; i < length; i++) { @@ -1160,10 +1174,6 @@ 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 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 */ @@ -1237,6 +1247,37 @@ double maxiDyn::compressor(double input, double ratio, double threshold, double 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) { + 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. @@ -1282,61 +1323,159 @@ double maxiEnv::ar(double input, double attack, double release, long holdtime, i return output; } -/* and here's a new adsr. It's not bad, very simple to use*/ +/* 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; + + if (trigger==1 && attackphase!=1 && holdphase!=1 && decayphase!=1){ + holdcount=0; + decayphase=0; + sustainphase=0; + 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 (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 maxiEnv::adsr(double input, int trigger) { + + if (trigger==1 && attackphase!=1 && holdphase!=1 && decayphase!=1){ + holdcount=0; + decayphase=0; + sustainphase=0; + 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 (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; +} + + +void maxiEnv::setAttack(double attackMS) { + attack = 1-pow( 0.01, 1.0 / ( attackMS * maxiSettings::sampleRate * 0.001 ) ); +} + +void maxiEnv::setRelease(double releaseMS) { + release = pow( 0.01, 1.0 / ( releaseMS * maxiSettings::sampleRate * 0.001 ) ); +} + +void maxiEnv::setSustain(double sustainL) { + sustain = sustainL; +} + +void maxiEnv::setDecay(double decayMS) { + decay = pow( 0.01, 1.0 / ( decayMS * maxiSettings::sampleRate * 0.001 ) ); +} + +void maxiDyn::setAttack(double attackMS) { + attack = pow( 0.01, 1.0 / ( attackMS * maxiSettings::sampleRate * 0.001 ) ); +} + +void maxiDyn::setRelease(double releaseMS) { + release = pow( 0.01, 1.0 / ( releaseMS * maxiSettings::sampleRate * 0.001 ) ); +} + +void maxiDyn::setThreshold(double thresholdI) { + threshold = thresholdI; +} + +void maxiDyn::setRatio(double ratioF) { + ratio = ratioF; +} + + double convert::mtof(int midinote) { return mtofarray[midinote]; } + +template<> void maxiEnvelopeFollower::setAttack(double attackMS) { + attack = pow( 0.01, 1.0 / ( attackMS * maxiSettings::sampleRate * 0.001 ) ); +} + +template<> void maxiEnvelopeFollower::setRelease(double releaseMS) { + release = pow( 0.01, 1.0 / ( releaseMS * maxiSettings::sampleRate * 0.001 ) ); +} + diff --git a/ofxMaxim/openFrameworksExamples/OSX/OF0.8.4MaximExtractorExample/ofxMaxim/libs/maximilian.h b/ofxMaxim/openFrameworksExamples/OSX/OF0.8.4MaximExtractorExample/ofxMaxim/libs/maximilian.h index 03dfea5..8a78c26 100755 --- a/ofxMaxim/openFrameworksExamples/OSX/OF0.8.4MaximExtractorExample/ofxMaxim/libs/maximilian.h +++ b/ofxMaxim/openFrameworksExamples/OSX/OF0.8.4MaximExtractorExample/ofxMaxim/libs/maximilian.h @@ -30,12 +30,6 @@ * */ -/* - Feature request: - maxiNANINFAlarm - maxiLimiter - */ - #ifndef MAXIMILIAN_H #define MAXIMILIAN_H @@ -49,6 +43,10 @@ #include <cstdlib> #include "math.h" +#ifdef _WIN32 //|| _WIN64 +#include <algorithm> +#endif + using namespace std; #ifndef PI #define PI 3.1415926535897932384626433832795 @@ -91,8 +89,9 @@ public: double noise(); double sinebuf(double frequency); double sinebuf4(double frequency); + double sawn(double frequency); + double rect(double frequency, double duty=0.5); void phaseReset(double phaseIn); - double sawn(double frequency); }; @@ -214,12 +213,12 @@ private: int myByteRate; short myBlockAlign; short myBitsPerSample; + double position, recordPosition; double speed; double output; maxiLagExp<double> loopRecordLag; public: - double position, recordPosition; int myDataSize; short myChannels; int mySampleRate; @@ -237,9 +236,11 @@ public: { // if (myData) free(myData); if (temp) free(temp); + printf("freeing SampleData"); + } - maxiSample():temp(NULL),position(0), recordPosition(0), myChannels(1), mySampleRate(maxiSettings::sampleRate) {}; + maxiSample():temp(NULL),position(0), recordPosition(0), myChannels(1), mySampleRate(maxiSettings::sampleRate) {}; maxiSample& operator=(const maxiSample &source) { if (this == &source) @@ -285,60 +286,60 @@ public: void clear(); void reset(); - - double play(); - + + double play(); + double playLoop(double start, double end); // start and end are between 0.0 and 1.0 - - double playOnce(); - - double playOnce(double speed); - + + double playOnce(); + + double playOnce(double speed); + void setPosition(double newPos); // between 0.0 and 1.0 double playUntil(double end); - - 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); - - double bufferPlay(unsigned char &bufferin,double speed,long length); - - double bufferPlay(unsigned char &bufferin,double frequency, double start, double end); - - double bufferPlay4(unsigned char &bufferin,double frequency, double start, double end); + + 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); + + double bufferPlay(unsigned char &bufferin,double speed,long length); + + double bufferPlay(unsigned char &bufferin,double frequency, double start, double end); + + double bufferPlay4(unsigned char &bufferin,double frequency, double start, double end); bool save() { return save(myPath); } bool save(string filename) { - fstream myFile (filename.c_str(), ios::out | ios::binary); - - // write the wav file per the wav file format - myFile.seekp (0, ios::beg); - myFile.write ("RIFF", 4); - myFile.write ((char*) &myChunkSize, 4); - myFile.write ("WAVE", 4); - myFile.write ("fmt ", 4); - myFile.write ((char*) &mySubChunk1Size, 4); - myFile.write ((char*) &myFormat, 2); - myFile.write ((char*) &myChannels, 2); - myFile.write ((char*) &mySampleRate, 4); - myFile.write ((char*) &myByteRate, 4); - myFile.write ((char*) &myBlockAlign, 2); - myFile.write ((char*) &myBitsPerSample, 2); - myFile.write ("data", 4); - myFile.write ((char*) &myDataSize, 4); - myFile.write ((char*) temp, myDataSize); - - return true; + fstream myFile (filename.c_str(), ios::out | ios::binary); + + // write the wav file per the wav file format + myFile.seekp (0, ios::beg); + myFile.write ("RIFF", 4); + myFile.write ((char*) &myChunkSize, 4); + myFile.write ("WAVE", 4); + myFile.write ("fmt ", 4); + myFile.write ((char*) &mySubChunk1Size, 4); + myFile.write ((char*) &myFormat, 2); + myFile.write ((char*) &myChannels, 2); + myFile.write ((char*) &mySampleRate, 4); + myFile.write ((char*) &myByteRate, 4); + myFile.write ((char*) &myBlockAlign, 2); + myFile.write ((char*) &myBitsPerSample, 2); + myFile.write ("data", 4); + myFile.write ((char*) &myDataSize, 4); + myFile.write ((char*) temp, myDataSize); + + return true; } // return a printable summary of the wav file @@ -346,6 +347,7 @@ public: { char *summary = new char[250]; sprintf(summary, " Format: %d\n Channels: %d\n SampleRate: %d\n ByteRate: %d\n BlockAlign: %d\n BitsPerSample: %d\n DataSize: %d\n", myFormat, myChannels, mySampleRate, myByteRate, myBlockAlign, myBitsPerSample, myDataSize); + std::cout << myDataSize; return summary; } @@ -356,43 +358,47 @@ public: class maxiMap { public: - static double inline linlin(double val, double inMin, double inMax, double outMin, double outMax) { - val = max(min(val, inMax), inMin); - return ((val - inMin) / (inMax - inMin) * (outMax - outMin)) + outMin; - } - - static double inline linexp(double val, double inMin, double inMax, double outMin, double outMax) { - //clipping - 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); - return (log(val/inMin) / log(inMax/inMin) * (outMax - outMin)) + outMin; - } - + static double inline linlin(double val, double inMin, double inMax, double outMin, double outMax) { + val = max(min(val, inMax), inMin); + return ((val - inMin) / (inMax - inMin) * (outMax - outMin)) + outMin; + } + + static double inline linexp(double val, double inMin, double inMax, double outMin, double outMax) { + //clipping + 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); + return (log(val/inMin) / log(inMax/inMin) * (outMax - outMin)) + outMin; + } + //changed to templated function, e.g. maxiMap::maxiClamp<int>(v, l, h); template<typename T> - static T inline clamp(T v, const T low, const T high) { + static T inline clamp(T v, const T low, const T high) { if (v > high) v = high; else if (v < low) { v = low; } - return v; - } + return v; + } }; + 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 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 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 compress(double input); + double input; double ratio; double currentRatio; double threshold; @@ -400,6 +406,10 @@ public: double attack; double release; double amplitude; + void setAttack(double attackMS); + void setRelease(double releaseMS); + void setThreshold(double thresholdI); + void setRatio(double ratioF); long holdtime; long holdcount; int attackphase,holdphase,releasephase; @@ -411,6 +421,7 @@ 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 adsr(double input,int trigger); double input; double output; double attack; @@ -418,8 +429,12 @@ public: double sustain; double release; double amplitude; + void setAttack(double attackMS); + void setRelease(double releaseMS); + void setDecay(double decayMS); + void setSustain(double sustainL); int trigger; - long holdtime; + long holdtime=1; long holdcount; int attackphase,decayphase,sustainphase,holdphase,releasephase; }; @@ -516,20 +531,20 @@ public: env = 0; } void setAttack(T attackMS) { - attack = pow( 0.01, 1.0 / (attackMS * maxiSettings::sampleRate * 0.001 ) ); + attack = pow( 0.01, 1.0 / (attackMS * maxiSettings::sampleRate * 0.001 ) ); } void setRelease(T releaseMS) { - release = pow( 0.01, 1.0 / (releaseMS * maxiSettings::sampleRate * 0.001 ) ); + release = pow( 0.01, 1.0 / (releaseMS * maxiSettings::sampleRate * 0.001 ) ); } inline T play(T input) { input = fabs(input); if (input>env) env = attack * (env - input) + input; else - env = release * (env - input) + input; + env = release * (env - input) + input; return env; } - void reset() {env=0;} + void reset() {env=0;} inline T getEnv(){return env;} inline void setEnv(T val){env = val;} private: @@ -539,7 +554,6 @@ private: typedef maxiEnvelopeFollowerType<double> maxiEnvelopeFollower; typedef maxiEnvelopeFollowerType<float> maxiEnvelopeFollowerF; -//from https://ccrma.stanford.edu/~jos/filters/DC_Blocker_Software_Implementations.html class maxiDCBlocker { public: double xm1, ym1; diff --git a/ofxMaxim/openFrameworksExamples/OSX/ofxMaximExample_0.8.4_OSX_Granular/ofxMaxim/libs/maximilian.cpp b/ofxMaxim/openFrameworksExamples/OSX/ofxMaximExample_0.8.4_OSX_Granular/ofxMaxim/libs/maximilian.cpp index 0b8ba86..7ba4978 100755..100644 --- a/ofxMaxim/openFrameworksExamples/OSX/ofxMaximExample_0.8.4_OSX_Granular/ofxMaxim/libs/maximilian.cpp +++ b/ofxMaxim/openFrameworksExamples/OSX/ofxMaximExample_0.8.4_OSX_Granular/ofxMaxim/libs/maximilian.cpp @@ -325,19 +325,6 @@ double maxiOsc::saw(double frequency) { phase += (1./(maxiSettings::sampleRate/(frequency))); return(output); -} - -double maxiOsc::triangle(double frequency) { - //This is a triangle wave. - if ( phase >= 1.0 ) phase -= 1.0; - phase += (1./(maxiSettings::sampleRate/(frequency))); - if (phase <= 0.5 ) { - output =(phase - 0.25) * 4; - } else { - output =((1.0-phase) - 0.25) * 4; - } - return(output); - } double maxiOsc::sawn(double frequency) { @@ -359,12 +346,29 @@ double maxiOsc::sawn(double frequency) { } +double maxiOsc::rect(double frequency, double duty) { + + return (output); +} + +double maxiOsc::triangle(double frequency) { + //This is a triangle wave. + if ( phase >= 1.0 ) phase -= 1.0; + phase += (1./(maxiSettings::sampleRate/(frequency))); + if (phase <= 0.5 ) { + output =(phase - 0.25) * 4; + } else { + output =((1.0-phase) - 0.25) * 4; + } + return(output); + +} double maxiEnvelope::line(int numberofsegments,double segments[1000]) { //This is a basic multi-segment ramp generator that you can use for more or less anything. //However, it's not that intuitive. if (isPlaying==1) {//only make a sound once you've been triggered - period=2./(segments[valindex+1]*0.004); + period=4./(segments[valindex+1]*0.0044); nextval=segments[valindex+2]; currentval=segments[valindex]; if (currentval-amplitude > 0.0000001 && valindex < numberofsegments) { @@ -397,8 +401,7 @@ void maxiEnvelope::trigger(int index, double amp) { //Delay with feedback maxiDelayline::maxiDelayline() { - memset( memory, 0, 88200*sizeof (double) ); - phase=0; + memset( memory, 0, 88200*sizeof (double) ); } @@ -437,9 +440,9 @@ double maxiFilter::hipass(double input, double cutoff) { } //awesome. cuttof is freq in hz. res is between 1 and whatever. Watch out! double maxiFilter::lores(double input,double cutoff1, double resonance) { - cutoff=cutoff1*0.5; + cutoff=cutoff1; if (cutoff<10) cutoff=10; - if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5); + if (cutoff>(maxiSettings::sampleRate)) cutoff=(maxiSettings::sampleRate); if (resonance<1.) resonance = 1.; z=cos(TWOPI*cutoff/maxiSettings::sampleRate); c=2-2*z; @@ -453,9 +456,9 @@ double maxiFilter::lores(double input,double cutoff1, double resonance) { //working hires filter double maxiFilter::hires(double input,double cutoff1, double resonance) { - cutoff=cutoff1*0.5; + cutoff=cutoff1; if (cutoff<10) cutoff=10; - if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5); + if (cutoff>(maxiSettings::sampleRate)) cutoff=(maxiSettings::sampleRate); if (resonance<1.) resonance = 1.; z=cos(TWOPI*cutoff/maxiSettings::sampleRate); c=2-2*z; @@ -524,18 +527,20 @@ double *maxiMix::ambisonic(double input,double eight[8],double x,double y,double return(eight); } - +//This is the maxiSample load function. It just calls read. bool maxiSample::load(string fileName, int channel) { myPath = fileName; readChannel=channel; return read(); } +// This is for OGG loading bool maxiSample::loadOgg(string fileName, int channel) { #ifdef VORBIS bool result; readChannel=channel; int channelx; +// cout << fileName << endl; free(temp); myDataSize = stb_vorbis_decode_filename(const_cast<char*>(fileName.c_str()), &channelx, &temp); result = myDataSize > 0; @@ -558,11 +563,13 @@ bool maxiSample::loadOgg(string fileName, int channel) { return 0; } +//This sets the playback position to the start of a sample void maxiSample::trigger() { position = 0; recordPosition = 0; } +//This is the main read function. bool maxiSample::read() { bool result; @@ -597,7 +604,7 @@ bool maxiSample::read() //ignore any extra chunks char chunkID[5]=""; chunkID[4] = 0; - int filePos = 36; + int filePos = 20 + mySubChunk1Size; while(!datafound && !inFile.eof()) { inFile.seekg(filePos, ios::beg); inFile.read((char*) &chunkID, sizeof(char) * 4); @@ -612,7 +619,7 @@ bool maxiSample::read() } // read the data chunk - char *myData = (char*) malloc(myDataSize * sizeof(char)); + char * myData = (char*) malloc(myDataSize * sizeof(char)); inFile.seekg(filePos, ios::beg); inFile.read(myData, myDataSize); length=myDataSize*(0.5/myChannels); @@ -644,6 +651,7 @@ bool maxiSample::read() return result; // this should probably be something more descriptive } +//This plays back at the correct speed. Always loops. double maxiSample::play() { position++; if ((long) position >= length) position=0; @@ -651,40 +659,43 @@ double maxiSample::play() { return output; } +void maxiSample::setPosition(double newPos) { + position = maxiMap::clamp<double>(newPos, 0.0, 1.0) * length; +} + //start end and points are between 0 and 1 double maxiSample::playLoop(double start, double end) { - position++; + position++; if (position < length * start) position = length * start; - if ((long) position >= length * end) position = length * start; - output = (double) temp[(long)position]/32767.0; - return output; + if ((long) position >= length * end) position = length * start; + output = (double) temp[(long)position]/32767.0; + return output; } -double maxiSample::playOnce() { - position++; - if ((long) position<length) +double maxiSample::playUntil(double end) { + position++; + if ((long) position<length * end) output = (double) temp[(long)position]/32767.0; else { output=0; } - return output; - + return output; } -void maxiSample::setPosition(double newPos) { - position = maxiMap::clamp<double>(newPos, 0.0, 1.0) * length; -} -double maxiSample::playUntil(double end) { +//This plays back at the correct speed. Only plays once. To retrigger, you have to manually reset the position +double maxiSample::playOnce() { position++; - if ((long) position<length * end) + if ((long) position<length) output = (double) temp[(long)position]/32767.0; else { output=0; } return output; + } +//Same as above but takes a speed value specified as a ratio, with 1.0 as original speed double maxiSample::playOnce(double speed) { position=position+((speed*chandiv)/(maxiSettings::sampleRate/mySampleRate)); double remainder = position - (long) position; @@ -695,6 +706,7 @@ double maxiSample::playOnce(double speed) { return(output); } +//As above but looping double maxiSample::play(double speed) { double remainder; long a,b; @@ -740,10 +752,12 @@ double maxiSample::play(double speed) { return(output); } +//placeholder double maxiSample::play(double frequency, double start, double end) { return play(frequency, start, end, position); } +//This allows you to say how often a second you want a specific chunk of audio to play double maxiSample::play(double frequency, double start, double end, double &pos) { double remainder; if (end>=length) end=length-1; @@ -755,7 +769,7 @@ double maxiSample::play(double frequency, double start, double end, double &pos) } if ( pos >= end ) pos = start; - pos += ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv))); + pos += ((end-start)/((maxiSettings::sampleRate)/(frequency*chandiv))); remainder = pos - floor(pos); long posl = floor(pos); if (posl+1<length) { @@ -775,7 +789,7 @@ double maxiSample::play(double frequency, double start, double end, double &pos) output = (double) ((1-remainder) * temp[a] + remainder * temp[b])/32767;//linear interpolation } else { - frequency=frequency-(frequency+frequency); + frequency*=-1.; if ( pos <= start ) pos = end; pos -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv))); remainder = pos - floor(pos); @@ -801,7 +815,7 @@ double maxiSample::play(double frequency, double start, double end, double &pos) } -//better cubic inerpolation. Cobbled together from various (pd externals, yehar, other places). +//Same as above. better cubic inerpolation. Cobbled together from various (pd externals, yehar, other places). double maxiSample::play4(double frequency, double start, double end) { double remainder; double a,b,c,d,a1,a2,a3; @@ -840,7 +854,7 @@ double maxiSample::play4(double frequency, double start, double end) { output = (double) (((a3 * remainder + a2) * remainder + a1) * remainder + b) / 32767; } else { - frequency=frequency-(frequency+frequency); + frequency*=-1.; if ( position <= start ) position = end; position -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv))); remainder = position - floor(position); @@ -876,6 +890,8 @@ double maxiSample::play4(double frequency, double start, double end) { return(output); } + +//You don't need to worry about this stuff. double maxiSample::bufferPlay(unsigned char &bufferin,long length) { double remainder; short* buffer = (short *)&bufferin; @@ -963,7 +979,7 @@ double maxiSample::bufferPlay(unsigned char &bufferin,double frequency, double s output = (double) ((1-remainder) * buffer[a] + remainder * buffer[b])/32767;//linear interpolation } else { - frequency=frequency-(frequency+frequency); + frequency*=-1.; if ( position <= start ) position = end; position -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv))); remainder = position - floor(position); @@ -1028,7 +1044,7 @@ double maxiSample::bufferPlay4(unsigned char &bufferin,double frequency, double output = (double) (((a3 * remainder + a2) * remainder + a1) * remainder + b) / 32767; } else { - frequency=frequency-(frequency+frequency); + frequency*=-1.; if ( position <= start ) position = end; position -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv))); remainder = position - floor(position); @@ -1066,18 +1082,17 @@ double maxiSample::bufferPlay4(unsigned char &bufferin,double frequency, double void maxiSample::getLength() { - length=myDataSize*0.5; + length=myDataSize*0.5; } void maxiSample::setLength(unsigned long numSamples) { - temp = (short*) realloc(temp, sizeof(short) * numSamples); -// short *newData = (short*) malloc(sizeof(short) * numSamples); -// if (NULL!=temp) { -// unsigned long copyLength = min((unsigned long)length, numSamples); -// memcpy(newData, temp, sizeof(short) * copyLength); -// free(temp); -// } -// temp = newData; + cout << "Length: " << numSamples << endl; + short *newData = (short*) malloc(sizeof(short) * numSamples); + if (NULL!=temp) { + unsigned long copyLength = min((unsigned long)length, numSamples); + memcpy(newData, temp, sizeof(short) * copyLength); + } + temp = newData; myDataSize = numSamples * 2; length=numSamples; position=0; @@ -1092,7 +1107,6 @@ void maxiSample::reset() { position=0; } - void maxiSample::normalise(float maxLevel) { short maxValue = 0; for(int i=0; i < length; i++) { @@ -1160,10 +1174,6 @@ 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 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 */ @@ -1237,6 +1247,37 @@ double maxiDyn::compressor(double input, double ratio, double threshold, double 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) { + 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. @@ -1282,61 +1323,159 @@ double maxiEnv::ar(double input, double attack, double release, long holdtime, i return output; } -/* and here's a new adsr. It's not bad, very simple to use*/ +/* 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; + + if (trigger==1 && attackphase!=1 && holdphase!=1 && decayphase!=1){ + holdcount=0; + decayphase=0; + sustainphase=0; + 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 (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 maxiEnv::adsr(double input, int trigger) { + + if (trigger==1 && attackphase!=1 && holdphase!=1 && decayphase!=1){ + holdcount=0; + decayphase=0; + sustainphase=0; + 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 (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; +} + + +void maxiEnv::setAttack(double attackMS) { + attack = 1-pow( 0.01, 1.0 / ( attackMS * maxiSettings::sampleRate * 0.001 ) ); +} + +void maxiEnv::setRelease(double releaseMS) { + release = pow( 0.01, 1.0 / ( releaseMS * maxiSettings::sampleRate * 0.001 ) ); +} + +void maxiEnv::setSustain(double sustainL) { + sustain = sustainL; +} + +void maxiEnv::setDecay(double decayMS) { + decay = pow( 0.01, 1.0 / ( decayMS * maxiSettings::sampleRate * 0.001 ) ); +} + +void maxiDyn::setAttack(double attackMS) { + attack = pow( 0.01, 1.0 / ( attackMS * maxiSettings::sampleRate * 0.001 ) ); +} + +void maxiDyn::setRelease(double releaseMS) { + release = pow( 0.01, 1.0 / ( releaseMS * maxiSettings::sampleRate * 0.001 ) ); +} + +void maxiDyn::setThreshold(double thresholdI) { + threshold = thresholdI; +} + +void maxiDyn::setRatio(double ratioF) { + ratio = ratioF; +} + + double convert::mtof(int midinote) { return mtofarray[midinote]; } + +template<> void maxiEnvelopeFollower::setAttack(double attackMS) { + attack = pow( 0.01, 1.0 / ( attackMS * maxiSettings::sampleRate * 0.001 ) ); +} + +template<> void maxiEnvelopeFollower::setRelease(double releaseMS) { + release = pow( 0.01, 1.0 / ( releaseMS * maxiSettings::sampleRate * 0.001 ) ); +} + diff --git a/ofxMaxim/openFrameworksExamples/OSX/ofxMaximExample_0.8.4_OSX_Granular/ofxMaxim/libs/maximilian.h b/ofxMaxim/openFrameworksExamples/OSX/ofxMaximExample_0.8.4_OSX_Granular/ofxMaxim/libs/maximilian.h index 03dfea5..8a78c26 100755 --- a/ofxMaxim/openFrameworksExamples/OSX/ofxMaximExample_0.8.4_OSX_Granular/ofxMaxim/libs/maximilian.h +++ b/ofxMaxim/openFrameworksExamples/OSX/ofxMaximExample_0.8.4_OSX_Granular/ofxMaxim/libs/maximilian.h @@ -30,12 +30,6 @@ * */ -/* - Feature request: - maxiNANINFAlarm - maxiLimiter - */ - #ifndef MAXIMILIAN_H #define MAXIMILIAN_H @@ -49,6 +43,10 @@ #include <cstdlib> #include "math.h" +#ifdef _WIN32 //|| _WIN64 +#include <algorithm> +#endif + using namespace std; #ifndef PI #define PI 3.1415926535897932384626433832795 @@ -91,8 +89,9 @@ public: double noise(); double sinebuf(double frequency); double sinebuf4(double frequency); + double sawn(double frequency); + double rect(double frequency, double duty=0.5); void phaseReset(double phaseIn); - double sawn(double frequency); }; @@ -214,12 +213,12 @@ private: int myByteRate; short myBlockAlign; short myBitsPerSample; + double position, recordPosition; double speed; double output; maxiLagExp<double> loopRecordLag; public: - double position, recordPosition; int myDataSize; short myChannels; int mySampleRate; @@ -237,9 +236,11 @@ public: { // if (myData) free(myData); if (temp) free(temp); + printf("freeing SampleData"); + } - maxiSample():temp(NULL),position(0), recordPosition(0), myChannels(1), mySampleRate(maxiSettings::sampleRate) {}; + maxiSample():temp(NULL),position(0), recordPosition(0), myChannels(1), mySampleRate(maxiSettings::sampleRate) {}; maxiSample& operator=(const maxiSample &source) { if (this == &source) @@ -285,60 +286,60 @@ public: void clear(); void reset(); - - double play(); - + + double play(); + double playLoop(double start, double end); // start and end are between 0.0 and 1.0 - - double playOnce(); - - double playOnce(double speed); - + + double playOnce(); + + double playOnce(double speed); + void setPosition(double newPos); // between 0.0 and 1.0 double playUntil(double end); - - 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); - - double bufferPlay(unsigned char &bufferin,double speed,long length); - - double bufferPlay(unsigned char &bufferin,double frequency, double start, double end); - - double bufferPlay4(unsigned char &bufferin,double frequency, double start, double end); + + 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); + + double bufferPlay(unsigned char &bufferin,double speed,long length); + + double bufferPlay(unsigned char &bufferin,double frequency, double start, double end); + + double bufferPlay4(unsigned char &bufferin,double frequency, double start, double end); bool save() { return save(myPath); } bool save(string filename) { - fstream myFile (filename.c_str(), ios::out | ios::binary); - - // write the wav file per the wav file format - myFile.seekp (0, ios::beg); - myFile.write ("RIFF", 4); - myFile.write ((char*) &myChunkSize, 4); - myFile.write ("WAVE", 4); - myFile.write ("fmt ", 4); - myFile.write ((char*) &mySubChunk1Size, 4); - myFile.write ((char*) &myFormat, 2); - myFile.write ((char*) &myChannels, 2); - myFile.write ((char*) &mySampleRate, 4); - myFile.write ((char*) &myByteRate, 4); - myFile.write ((char*) &myBlockAlign, 2); - myFile.write ((char*) &myBitsPerSample, 2); - myFile.write ("data", 4); - myFile.write ((char*) &myDataSize, 4); - myFile.write ((char*) temp, myDataSize); - - return true; + fstream myFile (filename.c_str(), ios::out | ios::binary); + + // write the wav file per the wav file format + myFile.seekp (0, ios::beg); + myFile.write ("RIFF", 4); + myFile.write ((char*) &myChunkSize, 4); + myFile.write ("WAVE", 4); + myFile.write ("fmt ", 4); + myFile.write ((char*) &mySubChunk1Size, 4); + myFile.write ((char*) &myFormat, 2); + myFile.write ((char*) &myChannels, 2); + myFile.write ((char*) &mySampleRate, 4); + myFile.write ((char*) &myByteRate, 4); + myFile.write ((char*) &myBlockAlign, 2); + myFile.write ((char*) &myBitsPerSample, 2); + myFile.write ("data", 4); + myFile.write ((char*) &myDataSize, 4); + myFile.write ((char*) temp, myDataSize); + + return true; } // return a printable summary of the wav file @@ -346,6 +347,7 @@ public: { char *summary = new char[250]; sprintf(summary, " Format: %d\n Channels: %d\n SampleRate: %d\n ByteRate: %d\n BlockAlign: %d\n BitsPerSample: %d\n DataSize: %d\n", myFormat, myChannels, mySampleRate, myByteRate, myBlockAlign, myBitsPerSample, myDataSize); + std::cout << myDataSize; return summary; } @@ -356,43 +358,47 @@ public: class maxiMap { public: - static double inline linlin(double val, double inMin, double inMax, double outMin, double outMax) { - val = max(min(val, inMax), inMin); - return ((val - inMin) / (inMax - inMin) * (outMax - outMin)) + outMin; - } - - static double inline linexp(double val, double inMin, double inMax, double outMin, double outMax) { - //clipping - 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); - return (log(val/inMin) / log(inMax/inMin) * (outMax - outMin)) + outMin; - } - + static double inline linlin(double val, double inMin, double inMax, double outMin, double outMax) { + val = max(min(val, inMax), inMin); + return ((val - inMin) / (inMax - inMin) * (outMax - outMin)) + outMin; + } + + static double inline linexp(double val, double inMin, double inMax, double outMin, double outMax) { + //clipping + 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); + return (log(val/inMin) / log(inMax/inMin) * (outMax - outMin)) + outMin; + } + //changed to templated function, e.g. maxiMap::maxiClamp<int>(v, l, h); template<typename T> - static T inline clamp(T v, const T low, const T high) { + static T inline clamp(T v, const T low, const T high) { if (v > high) v = high; else if (v < low) { v = low; } - return v; - } + return v; + } }; + 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 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 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 compress(double input); + double input; double ratio; double currentRatio; double threshold; @@ -400,6 +406,10 @@ public: double attack; double release; double amplitude; + void setAttack(double attackMS); + void setRelease(double releaseMS); + void setThreshold(double thresholdI); + void setRatio(double ratioF); long holdtime; long holdcount; int attackphase,holdphase,releasephase; @@ -411,6 +421,7 @@ 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 adsr(double input,int trigger); double input; double output; double attack; @@ -418,8 +429,12 @@ public: double sustain; double release; double amplitude; + void setAttack(double attackMS); + void setRelease(double releaseMS); + void setDecay(double decayMS); + void setSustain(double sustainL); int trigger; - long holdtime; + long holdtime=1; long holdcount; int attackphase,decayphase,sustainphase,holdphase,releasephase; }; @@ -516,20 +531,20 @@ public: env = 0; } void setAttack(T attackMS) { - attack = pow( 0.01, 1.0 / (attackMS * maxiSettings::sampleRate * 0.001 ) ); + attack = pow( 0.01, 1.0 / (attackMS * maxiSettings::sampleRate * 0.001 ) ); } void setRelease(T releaseMS) { - release = pow( 0.01, 1.0 / (releaseMS * maxiSettings::sampleRate * 0.001 ) ); + release = pow( 0.01, 1.0 / (releaseMS * maxiSettings::sampleRate * 0.001 ) ); } inline T play(T input) { input = fabs(input); if (input>env) env = attack * (env - input) + input; else - env = release * (env - input) + input; + env = release * (env - input) + input; return env; } - void reset() {env=0;} + void reset() {env=0;} inline T getEnv(){return env;} inline void setEnv(T val){env = val;} private: @@ -539,7 +554,6 @@ private: typedef maxiEnvelopeFollowerType<double> maxiEnvelopeFollower; typedef maxiEnvelopeFollowerType<float> maxiEnvelopeFollowerF; -//from https://ccrma.stanford.edu/~jos/filters/DC_Blocker_Software_Implementations.html class maxiDCBlocker { public: double xm1, ym1; |
