diff options
Diffstat (limited to 'maximilian.h')
| -rwxr-xr-x | maximilian.h | 471 |
1 files changed, 385 insertions, 86 deletions
diff --git a/maximilian.h b/maximilian.h index 0cac59d..c292598 100755 --- a/maximilian.h +++ b/maximilian.h @@ -42,6 +42,9 @@ #include <string.h> #include <cstdlib> #include "math.h" +#ifdef _WIN32 //|| _WIN64 +#include <algorithm> +#endif using namespace std; #ifndef PI @@ -208,7 +211,6 @@ private: short myFormat; int myByteRate; short myBlockAlign; - short myBitsPerSample; double position, recordPosition; double speed; double output; @@ -221,22 +223,38 @@ public: long length; void getLength(); void setLength(unsigned long numSamples); + short myBitsPerSample; + - - char* myData; +// char* myData; short* temp; // get/set for the Path property ~maxiSample() { - if (myData) free(myData); +// if (myData) free(myData); if (temp) free(temp); printf("freeing SampleData"); } - maxiSample():myData(NULL),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) + return *this; + position=0; + recordPosition = 0; + myChannels = source.myChannels; + mySampleRate = maxiSettings::sampleRate; + free(temp); + myDataSize = source.myDataSize; + temp = (short*) malloc(myDataSize * sizeof(char)); + memcpy(temp, source.temp, myDataSize * sizeof(char)); + length = source.length; + return *this; + } bool load(string fileName, int channel=0); @@ -250,70 +268,77 @@ public: //read an ogg file into this class using stb_vorbis bool readOgg(); - void loopRecord(double newSample, const bool recordEnabled, const double recordMix) { + void loopRecord(double newSample, const bool recordEnabled, const double recordMix, double start = 0.0, double end = 1.0) { loopRecordLag.addSample(recordEnabled); + if (recordPosition < start * length) recordPosition = start * length; if(recordEnabled) { - double currentSample = ((short*)myData)[(unsigned long)recordPosition] / 32767.0; + double currentSample = temp[(unsigned long)recordPosition] / 32767.0; newSample = (recordMix * currentSample) + ((1.0 - recordMix) * newSample); newSample *= loopRecordLag.value(); - ((short*)myData)[(unsigned long)recordPosition] = newSample * 32767; + temp[(unsigned long)recordPosition] = newSample * 32767; } ++recordPosition; - if (recordPosition == length) - recordPosition=0; + if (recordPosition >= end * length) + recordPosition= start * length; } void clear(); void reset(); - - double play(); - - 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); - - 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 playLoop(double start, double end); // start and end are between 0.0 and 1.0 + + 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); bool save() { - save(myPath); + 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 (myData, 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 @@ -324,32 +349,41 @@ public: std::cout << myDataSize; return summary; } + + void normalise(float maxLevel = 0.99); //0 < maxLevel < 1.0 + void autoTrim(float alpha = 0.3, float threshold = 6000, bool trimStart = true, bool trimEnd = true); //alpha of lag filter (lower == slower reaction), threshold to mark start and end, < 32767 }; class maxiMap { public: - static double inline linlin(double val, double inMin, double inMax, double outMin, double outMax) { - 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 int inline clamp(int v, const int low, const int high) { - v = min(high, v); - v = max(low, v); - return v; - } + 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) { + if (v > high) + v = high; + else if (v < low) { + v = low; + } + return v; + } }; @@ -358,9 +392,12 @@ 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; @@ -368,6 +405,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; @@ -379,6 +420,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; @@ -386,8 +428,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; }; @@ -475,26 +521,279 @@ inline double maxiChorus::chorus(const double input, const unsigned int delay, c return (output1 + output2 + input) / 3.0; } -class maxiEnvelopeFollower { +template<typename T> +class maxiEnvelopeFollowerType { public: - maxiEnvelopeFollower() { + maxiEnvelopeFollowerType() { setAttack(100); setRelease(100); env = 0; } - void setAttack(double attackMS); - void setRelease(double releaseMS); - inline double play(double input) { + void setAttack(T attackMS) { + 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 ) ); + } + 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: - double attack, release, env; + T attack, release, env; +}; + +typedef maxiEnvelopeFollowerType<double> maxiEnvelopeFollower; +typedef maxiEnvelopeFollowerType<float> maxiEnvelopeFollowerF; + +class maxiDCBlocker { +public: + double xm1, ym1; + maxiDCBlocker() : xm1(0), ym1(0) {} + inline double play(double input, double R) { + ym1 = input - xm1 + R * ym1; + xm1 = input; + return ym1; + } +}; + +/* + State Variable Filter + + algorithm from http://www.cytomic.com/files/dsp/SvfLinearTrapOptimised.pdf + usage: + either set the parameters separately as required (to save CPU) + + filter.setCutoff(param1); + filter.setResonance(param2); + + w = filter.play(w, 0.0, 1.0, 0.0, 0.0); + + or set everything together at once + + w = filter.setCutoff(param1).setResonance(param2).play(w, 0.0, 1.0, 0.0, 0.0); + + */ +class maxiSVF { +public: + maxiSVF() : v0z(0), v1(0), v2(0) { setParams(1000, 1);} + + //20 < cutoff < 20000 + inline maxiSVF& setCutoff(double cutoff) { + setParams(cutoff, res); + return *this; + } + + //from 0 upwards, starts to ring from 2-3ish, cracks a bit around 10 + inline maxiSVF& setResonance(double q) { + setParams(freq, q); + return *this; + } + + //run the filter, and get a mixture of lowpass, bandpass, highpass and notch outputs + inline double play(double w, double lpmix, double bpmix, double hpmix, double notchmix) { + double low, band, high, notch; + double v1z = v1; + double v2z = v2; + double v3 = w + v0z - 2.0 * v2z; + v1 += g1*v3-g2*v1z; + v2 += g3*v3+g4*v1z; + v0z = w; + low = v2; + band = v1; + high = w-k*v1-v2; + notch = w-k*v1; + return (low * lpmix) + (band * bpmix) + (high * hpmix) + (notch * notchmix); + } + +private: + inline void setParams(double _freq, double _res) { + freq = _freq; + res = _res; + g = tan(PI * freq / maxiSettings::sampleRate); + damping = res == 0 ? 0 : 1.0 / res; + k = damping; + ginv = g / (1.0 + g * (g + k)); + g1 = ginv; + g2 = 2.0 * (g + k) * ginv; + g3 = g * ginv; + g4 = 2.0 * ginv; + } + + double v0z, v1, v2, g, damping, k, ginv, g1, g2, g3 ,g4; + double freq, res; + +}; + +class maxiKick { + +public: + maxiKick(); + double play(); + void setPitch(double pitch); + void setRelease(double releaseD); + void trigger(); + double pitch; + double output = 0 ; + double outputD =0 ; + double envOut; + bool useDistortion = false; + bool useLimiter = false; + bool useFilter = false; + double distortion = 0; + bool inverse = false; + double cutoff; + double resonance; + double gain = 1; + maxiOsc kick; + maxiEnv envelope; + maxiDistortion distort; + maxiFilter filter; +}; + +class maxiSnare { +public: + maxiSnare(); + double play(); + void setPitch(double pitch); + void setRelease(double releaseD); + void trigger(); + double pitch; + double output = 0 ; + double outputD = 0 ; + double envOut; + bool useDistortion = false; + bool useLimiter = false; + bool useFilter = true; + double distortion = 0; + bool inverse = false; + double cutoff; + double resonance; + double gain = 1; + maxiOsc tone; + maxiOsc noise; + maxiEnv envelope; + maxiDistortion distort; + maxiFilter filter; + + + +}; + +class maxiHats { + +public: + maxiHats(); + double play(); + void setPitch(double pitch); + void setRelease(double releaseD); + void trigger(); + double pitch; + double output = 0; + double outputD = 0; + double envOut; + bool useDistortion = false; + bool useLimiter = false; + bool useFilter = false; + double distortion = 0; + bool inverse = false; + double cutoff; + double resonance; + double gain = 1; + maxiOsc tone; + maxiOsc noise; + maxiEnv envelope; + maxiDistortion distort; + maxiSVF filter; + + +}; + + +class maxiSynth { + + + +}; + + +class granularSynth { + + + +}; + + +class maxiSampler { + +public: + maxiSampler(); + double play(); + void setPitch(double pitch, bool setall=false); + void midiNoteOn(double pitch, double velocity, bool setall=false); + void midiNoteOff(double pitch, double velocity, bool setall=false); + void setAttack(double attackD,bool setall=true); + void setDecay(double decayD,bool setall=true); + void setSustain(double sustainD,bool setall=true); + void setRelease(double releaseD,bool setall=true); + void setPosition(double positionD,bool setall=true); + void load(string inFile,bool setall=true); + void setNumVoices(int numVoices); + double position; + void trigger(); + double pitch[32]; + int originalPitch=67; + double outputs[32]; + double outputD = 0; + double envOut[32]; + double envOutGain[32]; + double output; + bool useDistortion = false; + bool useLimiter = false; + bool useFilter = false; + double distortion = 0; + bool inverse = false; + double cutoff; + double resonance; + double gain = 1; + int voices; + int currentVoice=0; + convert mtof; + maxiOsc LFO1; + maxiOsc LFO2; + maxiOsc LFO3; + maxiOsc LFO4; + maxiSample samples[32]; + maxiEnv envelopes[32]; + maxiDistortion distort; + maxiSVF filters[32]; + bool sustain = true; + + +}; + +class maxiClock { +public: + maxiClock(); + void ticker(); + void setTempo(double bpm); + void setTicksPerBeat(int ticksPerBeat); + maxiOsc timer; + int currentCount; + int lastCount; + int playHead; + double bps; + double bpm; + int ticks; + bool tick; + }; |
