diff options
| author | Chris Kiefer <chrisk13fer@gmail.com> | 2013-07-05 11:03:20 +0100 |
|---|---|---|
| committer | Chris Kiefer <chrisk13fer@gmail.com> | 2013-07-05 11:03:20 +0100 |
| commit | 7f4c6ff482637ea9be4fe69448099fc3cebe73fd (patch) | |
| tree | 0008691e62024d1639841dfad88ab4c41d83c4d8 | |
| parent | 7e200e7f4e18022046b8ba694930827a8672a8f1 (diff) | |
sample looping methods
| -rw-r--r-- | ofxMaxim/ofxMaxim/libs/maximilian.cpp | 106 | ||||
| -rwxr-xr-x | ofxMaxim/ofxMaxim/libs/maximilian.h | 47 |
2 files changed, 130 insertions, 23 deletions
diff --git a/ofxMaxim/ofxMaxim/libs/maximilian.cpp b/ofxMaxim/ofxMaxim/libs/maximilian.cpp index 68de474..e26e153 100644 --- a/ofxMaxim/ofxMaxim/libs/maximilian.cpp +++ b/ofxMaxim/ofxMaxim/libs/maximilian.cpp @@ -566,8 +566,8 @@ bool maxiSample::read() { bool result; ifstream inFile( myPath.c_str(), ios::in | ios::binary); - result = inFile; - if (inFile) { + result = inFile.is_open(); + if (result) { bool datafound = false; inFile.seekg(4, ios::beg); inFile.read( (char*) &myChunkSize, 4 ); // read the ChunkSize @@ -645,7 +645,16 @@ bool maxiSample::read() double maxiSample::play() { position++; - if ((long) position == length) position=0; + if ((long) position >= length) position=0; + output = (double) temp[(long)position]/32767.0; + return output; +} + +//start end and points are between 0 and 1 +double maxiSample::playLoop(double start, double end) { + 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; } @@ -661,6 +670,20 @@ double maxiSample::playOnce() { } +void maxiSample::setPosition(double newPos) { + position = maxiMap::clamp<double>(newPos, 0.0, 1.0) * length; +} + +double maxiSample::playUntil(double end) { + position++; + if ((long) position<length * end) + output = (double) temp[(long)position]/32767.0; + else { + output=0; + } + return output; +} + double maxiSample::playOnce(double speed) { position=position+((speed*chandiv)/(maxiSettings::sampleRate/mySampleRate)); double remainder = position - (long) position; @@ -1069,6 +1092,74 @@ void maxiSample::reset() { } +void maxiSample::normalise(float maxLevel) { + short maxValue = 0; + for(int i=0; i < length; i++) { + if (abs(temp[i]) > maxValue) { + maxValue = abs(temp[i]); + } + } + float scale = 32767.0 * maxLevel / (float) maxValue; + for(int i=0; i < length; i++) { + temp[i] = round(scale * (float) temp[i]); + } +} + +void maxiSample::autoTrim(float alpha, float threshold, bool trimStart, bool trimEnd) { + + int startMarker=0; + if(trimStart) { + maxiLagExp<float> startLag(alpha, 0); + while(startMarker < length) { + startLag.addSample(abs(temp[startMarker])); + if (startLag.value() > threshold) { + break; + } + startMarker++; + } + } + + int endMarker = length-1; + if(trimEnd) { + maxiLagExp<float> endLag(alpha, 0); + while(endMarker > 0) { + endLag.addSample(abs(temp[endMarker])); + if (endLag.value() > threshold) { + break; + } + endMarker--; + } + } + + cout << "Autotrim: start: " << startMarker << ", end: " << endMarker << endl; + + int newLength = endMarker - startMarker; + if (newLength > 0) { + short *newData = (short*) malloc(sizeof(short) * newLength); + for(int i=0; i < newLength; i++) { + newData[i] = temp[i+startMarker]; + } + free(temp); + temp = newData; + myDataSize = newLength * 2; + length=newLength; + position=0; + recordPosition=0; + //envelope the start + int fadeSize=min((long)100, length); + for(int i=0; i < fadeSize; i++) { + float factor = i / (float) fadeSize; + temp[i] = round(temp[i] * factor); + temp[length - 1 - i] = round(temp[length - 1 - i] * factor); + } + } +} + + + + + + @@ -1248,12 +1339,3 @@ double convert::mtof(int midinote) { return mtofarray[midinote]; } - -void maxiEnvelopeFollower::setAttack(double attackMS) { - attack = pow( 0.01, 1.0 / (attackMS * maxiSettings::sampleRate * 0.001 ) ); -} - -void maxiEnvelopeFollower::setRelease(double releaseMS) { - release = pow( 0.01, 1.0 / (releaseMS * maxiSettings::sampleRate * 0.001 ) ); -} - diff --git a/ofxMaxim/ofxMaxim/libs/maximilian.h b/ofxMaxim/ofxMaxim/libs/maximilian.h index ce3ddd1..f46a2e3 100755 --- a/ofxMaxim/ofxMaxim/libs/maximilian.h +++ b/ofxMaxim/ofxMaxim/libs/maximilian.h @@ -30,6 +30,12 @@ * */ +/* + Feature request: + maxiNANINFAlarm + maxiLimiter + */ + #ifndef MAXIMILIAN_H #define MAXIMILIAN_H @@ -262,8 +268,9 @@ 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 = temp[(unsigned long)recordPosition] / 32767.0; newSample = (recordMix * currentSample) + ((1.0 - recordMix) * newSample); @@ -271,8 +278,8 @@ public: temp[(unsigned long)recordPosition] = newSample * 32767; } ++recordPosition; - if (recordPosition == length) - recordPosition=0; + if (recordPosition >= end * length) + recordPosition= start * length; } void clear(); @@ -280,10 +287,16 @@ public: void reset(); 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); @@ -335,12 +348,16 @@ public: 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); 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) { + val = max(min(val, inMax), inMin); return ((val - inMin) / (inMax - inMin) * (outMax - outMin)) + outMin; } @@ -490,16 +507,21 @@ 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; @@ -508,12 +530,15 @@ public: return env; } void reset() {env=0;} - inline double getEnv(){return env;} - inline void setEnv(double val){env = val;} + 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; + //from https://ccrma.stanford.edu/~jos/filters/DC_Blocker_Software_Implementations.html class maxiDCBlocker { public: |
