diff options
| author | mick grierson <mickgrierson@gmail.com> | 2016-03-04 14:14:56 +0000 |
|---|---|---|
| committer | mick grierson <mickgrierson@gmail.com> | 2016-03-04 14:14:56 +0000 |
| commit | ff891983f82464506b2f6545fd1d26c413638c64 (patch) | |
| tree | 91900ad09aa69a7f6efcb79285727bc865da4403 | |
| parent | 5dad0e449fb7f4ea35c0da1ee1c61efef2c83bc5 (diff) | |
fixing maxiGrains
| -rw-r--r-- | libs/maxiGrains.h | 1019 | ||||
| -rwxr-xr-x | main.cpp | 8 | ||||
| -rw-r--r-- | openFrameworks/ofxMaxim/libs/maxiGrains.h | 1017 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/Makefile (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/Makefile) | 0 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/Project.xcconfig (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/Project.xcconfig) | 0 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/addons.make (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/addons.make) | 0 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/.gitkeep (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/.gitkeep) | 0 | ||||
| -rwxr-xr-x | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/24620__anamorphosis__GMB_Kantilan_1.wav (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/24620__anamorphosis__GMB_Kantilan_1.wav) | bin | 441868 -> 441868 bytes | |||
| -rwxr-xr-x | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/2630__Jovica__133_bpm_ATTACK_LOOP_04_electrified_analog_kit_variation_16_mono.wav (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/2630__Jovica__133_bpm_ATTACK_LOOP_04_electrified_analog_kit_variation_16_mono.wav) | bin | 1273454 -> 1273454 bytes | |||
| -rwxr-xr-x | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/26393__brfindla__Calango1berimbau.wav (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/26393__brfindla__Calango1berimbau.wav) | bin | 1548688 -> 1548688 bytes | |||
| -rwxr-xr-x | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/59210__suonho__abstract_electrofunkbreakbeats_124bpm_mono.wav (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/59210__suonho__abstract_electrofunkbreakbeats_124bpm_mono.wav) | bin | 682882 -> 682882 bytes | |||
| -rwxr-xr-x | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/68373__juskiddink__Cello_open_string_bowed.wav (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/68373__juskiddink__Cello_open_string_bowed.wav) | bin | 1771694 -> 1771694 bytes | |||
| -rwxr-xr-x | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/71515__Microscopia__Wilhelm_Bruder_Sohne_Organ.wav (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/71515__Microscopia__Wilhelm_Bruder_Sohne_Organ.wav) | bin | 1657058 -> 1657058 bytes | |||
| -rwxr-xr-x | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/beat2.wav (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/beat2.wav) | bin | 211140 -> 211140 bytes | |||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/config.make (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/config.make) | 0 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/granular0_92.xcodeproj/project.pbxproj (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/project.pbxproj) | 0 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/granular0_92.xcodeproj/project.xcworkspace/contents.xcworkspacedata (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/project.xcworkspace/contents.xcworkspacedata) | 0 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/granular0_92.xcodeproj/xcshareddata/xcschemes/granular0_92 Debug.xcscheme (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/xcshareddata/xcschemes/granular0_92 Debug.xcscheme) | 0 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/granular0_92.xcodeproj/xcshareddata/xcschemes/granular0_92 Release.xcscheme (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/xcshareddata/xcschemes/granular0_92 Release.xcscheme) | 0 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/openFrameworks-Info.plist (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/openFrameworks-Info.plist) | 0 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/src/main.cpp (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/src/main.cpp) | 0 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/src/ofApp.cpp (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/src/ofApp.cpp) | 19 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/src/ofApp.h (renamed from openFrameworks/openFrameworksExamples/OSX/granular0_92/src/ofApp.h) | 4 | ||||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/project.xcworkspace/xcuserdata/michaelgrierson.xcuserdatad/UserInterfaceState.xcuserstate | bin | 12500 -> 0 bytes | |||
| -rw-r--r-- | openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/xcuserdata/michaelgrierson.xcuserdatad/xcschemes/xcschememanagement.plist | 27 |
25 files changed, 1388 insertions, 706 deletions
diff --git a/libs/maxiGrains.h b/libs/maxiGrains.h index a6b8c52..5fd5beb 100644 --- a/libs/maxiGrains.h +++ b/libs/maxiGrains.h @@ -1,13 +1,13 @@ -#ifndef _MAXI_GRAINS_H -#define _MAXI_GRAINS_H +#ifndef maxiGrains_2_hpp +#define maxiGrains_2_hpp #include "maximilian.h" #if defined(__APPLE_CC__) #include "accelerate/accelerate.h" //Mac users can uncommment the line below to use Apple's accelerate framework for calculating grains. This gives ~300% speed improvement and better sound quality, but doesn't work well on all machines. -//#define MAXIGRAINFAST +//#define MAXIGRAINFAST #endif #include <list> @@ -17,214 +17,184 @@ typedef unsigned long ulong; //window functions from http://en.wikipedia.org/wiki/Window_function#High-_and_moderate-resolution_windows struct hannWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return 0.5 * (1.0 - cos((2.0 * PI * windowPos) / (windowLength - 1))); - } + inline double operator()(ulong windowLength, ulong windowPos) { + return 0.5 * (1.0 - cos((2.0 * PI * windowPos) / (windowLength - 1))); + } }; //this window can produce clicks struct hammingWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return 0.54 - (0.46 * cos((2.0 * PI * windowPos) / (windowLength - 1))); - } + inline double operator()(ulong windowLength, ulong windowPos) { + return 0.54 - (0.46 * cos((2.0 * PI * windowPos) / (windowLength - 1))); + } }; struct cosineWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return sin((PI * windowPos) / (windowLength - 1)); - } + inline double operator()(ulong windowLength, ulong windowPos) { + return sin((PI * windowPos) / (windowLength - 1)); + } }; struct rectWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return 1; - } + inline double operator()(ulong windowLength, ulong windowPos) { + return 1; + } }; struct triangleWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return (2.0 / (windowLength-1.0)) * (((windowLength-1.0)/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0))); - } + inline double operator()(ulong windowLength, ulong windowPos) { + return (2.0 / (windowLength-1.0)) * (((windowLength-1.0)/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0))); + } }; struct triangleNZWinFunctor { - //non zero end points - inline double operator()(ulong windowLength, ulong windowPos) { - return (2.0 / windowLength) * ((windowLength/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0))); - } + //non zero end points + inline double operator()(ulong windowLength, ulong windowPos) { + return (2.0 / windowLength) * ((windowLength/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0))); + } }; struct blackmanHarrisWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return 0.35875 - - (0.48829 * cos((2 * PI * windowPos) / (windowLength-1))) + - (0.14128 * cos((4 * PI * windowPos) / (windowLength-1))) + - (0.01168 * cos((6 * PI * windowPos) / (windowLength-1))); - } + inline double operator()(ulong windowLength, ulong windowPos) { + return 0.35875 - + (0.48829 * cos((2 * PI * windowPos) / (windowLength-1))) + + (0.14128 * cos((4 * PI * windowPos) / (windowLength-1))) + + (0.01168 * cos((6 * PI * windowPos) / (windowLength-1))); + } }; struct blackmanNutallWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return 0.3635819 - - (0.4891775 * cos((2 * PI * windowPos) / (windowLength-1))) + - (0.1365995 * cos((4 * PI * windowPos) / (windowLength-1))) + - (0.0106411 * cos((6 * PI * windowPos) / (windowLength-1))); - } + inline double operator()(ulong windowLength, ulong windowPos) { + return 0.3635819 - + (0.4891775 * cos((2 * PI * windowPos) / (windowLength-1))) + + (0.1365995 * cos((4 * PI * windowPos) / (windowLength-1))) + + (0.0106411 * cos((6 * PI * windowPos) / (windowLength-1))); + } }; struct gaussianWinFunctor { - double gausDivisor; + double o; gaussianWinFunctor() { - init(0.3); - } - gaussianWinFunctor(double kurtosis) { - init(kurtosis); + o = 0.02; //compatible with MPTK } - void init(double kurtosis) { - gausDivisor = (-2.0 * kurtosis * kurtosis); + inline double operator()(ulong windowLength, ulong windowPos) { + double p = 1.0/(2.0*o*(windowLength+1)*(windowLength+1)); + double k = (double)windowPos-((double)(windowLength-1))/2.0; + return exp(-k*k*p); } - inline double operator()(ulong windowLength, ulong windowPos) { - double phase = ((windowPos / (double) windowLength) - 0.5) * 2.0; - return exp((phase * phase) / gausDivisor); - } }; template<typename F> class maxiGrainWindowCache { public: - unsigned int cacheSize; - - maxiGrainWindowCache() { - cacheSize = maxiSettings::sampleRate / 2.0; //allocate mem for up to 500ms grains - cache = (double**)malloc(cacheSize * sizeof(double*)); - for(int i=0; i < cacheSize; i++) { - cache[i] = NULL; - } - } - - ~maxiGrainWindowCache() { - for(int i=0; i < cacheSize; i++) { - if(NULL != cache[i]) { - free(cache[i]); - } - } + unsigned int cacheSize; + + maxiGrainWindowCache() { + cacheSize = maxiSettings::sampleRate / 2.0; //allocate mem for up to 500ms grains + cache = (double**)malloc(cacheSize * sizeof(double*)); + for(int i=0; i < cacheSize; i++) { + cache[i] = NULL; + } + } + + ~maxiGrainWindowCache() { + for(int i=0; i < cacheSize; i++) { + if(NULL != cache[i]) { + free(cache[i]); + } + } free(cache); - } - - double* getWindow(const unsigned int length) { - if (NULL == cache[length]) { - cache[length] = (double*)malloc(length * sizeof(double)); - for(int i=0; i < length; i++) { - cache[length][i] = F()(length, i); - } - } - return cache[length]; - } - + } + + double* getWindow(const unsigned int length) { + if (NULL == cache[length]) { + cache[length] = (double*)malloc(length * sizeof(double)); + for(int i=0; i < length; i++) { + cache[length][i] = F()(length, i); + } + } + return cache[length]; + } + private: - double** cache; - + double** cache; + }; class maxiGrainBase { public: - virtual double play() {} + virtual double play() {} virtual ~maxiGrainBase() {} - bool finished; + bool finished; }; -template<typename F> +template<class F, class maxiSample> class maxiGrain : public maxiGrainBase { public: - maxiSample *sample; + maxiSample *sample; double pos; - double dur; - long sampleStartPos; - long sampleIdx; - long sampleDur; - long sampleEndPos; - double freq; - double speed; - double inc; - double frequency; - double* window; - short* buffer; + double dur; + long sampleStartPos; + long sampleIdx; + long sampleDur; + long sampleEndPos; + double freq; + double speed; + double inc; + double frequency; + double* window; + // short* buffer; #if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) - double* grainSamples; + // double* grainSamples; #endif - /* - position between 0.0 and 1.0 - duration in seconds - */ - maxiGrain(maxiSample *sample, const double position, const double duration, const double speed, maxiGrainWindowCache<F> *windowCache) :sample(sample), pos(position), dur(duration), speed(speed) - { - buffer = sample->temp; - sampleStartPos = sample->length * pos; - sampleDur = dur * (double)sample->mySampleRate; - sampleDurMinusOne = sampleDur - 1; - sampleIdx = 0; - finished = 0; - freq = 1.0 / dur; - sampleEndPos = min(sample->length, sampleStartPos + sampleDur); - frequency = freq * speed; - if (frequency > 0) { - pos = sampleStartPos; - }else{ - pos = sampleEndPos; - } + /* + position between 0.0 and 1.0 + duration in seconds + */ + maxiGrain(maxiSample *_sample, const double position, const double duration, const double speed, maxiGrainWindowCache<F> *windowCache) :sample(_sample), pos(position), dur(duration), speed(speed) + { + // buffer = sample->temp; + sampleStartPos = (sample->length) * pos; + sampleDur = dur * (double)maxiSettings::sampleRate; + sampleDurMinusOne = sampleDur - 1; + sampleIdx = 0; + finished = 0; + freq = 1.0 / dur; + sampleEndPos = min(sample->length, sampleStartPos + sampleDur); + frequency = freq * speed; + if (frequency > 0) { + pos = sampleStartPos; + }else{ + pos = sampleEndPos; + } if (frequency != 0) { inc = sampleDur/(maxiSettings::sampleRate/frequency); }else inc = 0; - window = windowCache->getWindow(sampleDur); - -#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) - //premake the grain using fast vector functions, and quadratic interpolation - double *sourceData = (double*)malloc(sampleDur * sizeof(double)); - short* buffer = (short *)sample->temp; - //convert sample to double data - vDSP_vflt16D(buffer + sampleStartPos, 1, sourceData, 1, min(sampleDur, sample->length - sampleStartPos)); - //todo: wraping code - - grainSamples = (double*)malloc(sampleDur * sizeof(double)); - //make list of interpolation indexes - double* interpIndexes = (double*)malloc(sampleDur * sizeof(double)); - double interpPos = sampleStartPos; - for(int i=0; i < sampleDur; i++) { - interpIndexes[i] = interpPos - sampleStartPos; - interpPos += fabs(inc); - } - vDSP_vqintD(sourceData, interpIndexes, 1, grainSamples, 1, sampleDur, sampleDur); - if (frequency < 0) { - vDSP_vrvrsD(grainSamples,1, sampleDur); - } - static double divFactor = 32767.0; - vDSP_vsdivD(grainSamples, 1, &divFactor, grainSamples, 1, sampleDur); - vDSP_vmulD(grainSamples, 1, window, 1, grainSamples, 1, sampleDur); - delete sourceData, interpIndexes; -#endif - } - - ~maxiGrain() { + window = windowCache->getWindow(sampleDur); + + } + + ~maxiGrain() { #if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) - delete[] grainSamples; + delete[] grainSamples; #endif - } - - inline double play() { - double output = 0.0; - if (!finished) { + } + + inline double play() { + double output = 0.0; + if (!finished) { #if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) - output = grainSamples[sampleIdx]; + // output = grainSamples[sampleIdx]; #else - envValue = window[sampleIdx]; - double remainder; + envValue = window[sampleIdx]; + double remainder; pos += inc; - if (pos >= sample->length) + if (pos >= sample->length) pos -= sample->length; - else if (pos < 0) + else if (pos < 0) pos += sample->length; long posl = floor(pos); @@ -234,20 +204,21 @@ public: if (b >= sample->length) { b = 0; } - output = (double) ((1-remainder) * buffer[a] + - remainder * buffer[b])/32767.0;//linear interpolation - output *= envValue; + //output = (double) ((1-remainder) * sample->operator[](a) + + // remainder * sample->operator[](b))/32767.0;//linear interpolation + output = (double) ((1-remainder) * sample->temp[a] + remainder * sample->temp[b])/32767.0;//linear interpolation + output *= envValue; #endif - } - sampleIdx++; - if (sampleIdx == sampleDur) finished = true; - return output; - } - -protected: - maxiGrain(); - double envValue; - ulong sampleDurMinusOne; + } + sampleIdx++; + if (sampleIdx == sampleDur) finished = true; + return output; + } + +protected: + maxiGrain(); + double envValue; + ulong sampleDurMinusOne; }; @@ -255,173 +226,64 @@ typedef list<maxiGrainBase*> grainList; class maxiGrainPlayer { public: - grainList grains; - maxiSample *sample; - - maxiGrainPlayer(maxiSample *sample) : sample(sample) { - } - - void addGrain(maxiGrainBase *g) { - grains.push_back(g); - } - - inline double play() { - double total = 0.0; - grainList::iterator it = grains.begin(); - while(it != grains.end()) { - total += (*it)->play(); - if ((*it)->finished) { - delete(*it); - it = grains.erase(it); - }else{ - it++; - } - } - return total; - } -}; - -template<typename F> -class maxiTimestretch { -protected: - double position; -public: - maxiSample *sample; - maxiGrainPlayer *grainPlayer; - maxiGrainWindowCache<F> windowCache; - double randomOffset; - double looper; - - - - maxiTimestretch(maxiSample *sample) : sample(sample) { - position=0; - looper = 0; - grainPlayer = new maxiGrainPlayer(sample); - randomOffset=0; - } - - ~maxiTimestretch() { - delete grainPlayer; - } + grainList grains; + // maxiSample *sample; + // source *sample; - double getNormalisedPosition() { - return position / (double) sample->length; - } - double getPosition() { - return position; - } + // maxiGrainPlayer(maxiSample *sample) : sample(sample) { + // } - void setPosition(double pos) { - position = pos * sample->length; - position = maxiMap::clamp(position, 0, sample->length-1); + // maxiGrainPlayer(source *sample) : sample(sample) { + // } + + void addGrain(maxiGrainBase *g) { + grains.push_back(g); } - - - //play at a speed - inline double play(double speed, double grainLength, int overlaps, double posMod=0.0) { - position = position + speed; - looper++; - if (position > sample->length) position-= sample->length; - if (position < 0) position += sample->length; - double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; - if (looper > cycleLength + randomOffset) { - looper -= (cycleLength + randomOffset); - speed = (speed > 0 ? 1 : -1); - maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache); - grainPlayer->addGrain(g); - randomOffset = rand() % 10; - } - return grainPlayer->play(); - } - - //provide your own position iteration - inline double play2(double pos, double grainLength, int overlaps) { - looper++; - pos *= sample->length; - if (0 == floor(fmod(looper, grainLength * maxiSettings::sampleRate / overlaps))) { - maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(pos / sample->length)),0.0), grainLength, 1, &windowCache); - grainPlayer->addGrain(g); - } - return grainPlayer->play(); - } -}; - -//in maxiTimeStretch, the speed is either 1 or -1, and the actual speed value only affects the grain position -//in maxiPitchShift, speed is uncoupled from position and allowed to set it's value incrementally, resulting in pitchshift. -//with both high speed values and negative speed values there are some terrific artefacts! - -template<typename F> -class maxiPitchShift { -public: - double position; - long cycles; - maxiSample *sample; - maxiGrainPlayer *grainPlayer; - maxiGrainWindowCache<F> windowCache; - double randomOffset; - - maxiPitchShift(maxiSample *sample) : sample(sample) { - position=0; - cycles=0; - grainPlayer = new maxiGrainPlayer(sample); - randomOffset=0; - } - - ~maxiPitchShift() { - delete grainPlayer; - } - - double play(double speed, double grainLength, int overlaps, double posMod=0.0) { - position = position + 1; - cycles++; - if (position > sample->length) position=0; - if (position < 0) position = sample->length; - double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; - double cycleMod = fmod(cycles, cycleLength + randomOffset); - if (0 == floor(cycleMod)) { - // cout << cycleMod << endl; - //speed = (speed > 0 ? 1 : -1); - speed = speed - ((cycleMod / cycleLength) * 0.1); - maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache); - grainPlayer->addGrain(g); - // cout << grainPlayer->grains.size() << endl; - // randomOffset = rand() % 10; - // randomOffset = rand() % 10; - } - return grainPlayer->play(); - } - + inline double play() { + double total = 0.0; + grainList::iterator it = grains.begin(); + while(it != grains.end()) { + total += (*it)->play(); + if ((*it)->finished) { + delete(*it); + it = grains.erase(it); + }else{ + it++; + } + } + return total; + } }; //and here's maxiPitchStretch. Args to the play function are basically speed for 'pitch' and rate for playback rate. //the rest is the same. -template<typename F> -class maxiPitchStretch { +template<class F, class maxiSample> +class maxiTimePitchStretch { public: - double position; - maxiSample *sample; - maxiGrainPlayer *grainPlayer; - maxiGrainWindowCache<F> windowCache; - double randomOffset; + double position; + maxiSample *sample; + maxiGrainPlayer *grainPlayer; + maxiGrainWindowCache<F> windowCache; + double randomOffset; long loopStart, loopEnd, loopLength; double looper; - - maxiPitchStretch(maxiSample *sample) : sample(sample) { - grainPlayer = new maxiGrainPlayer(sample); - randomOffset=0; + + maxiTimePitchStretch(maxiSample *_sample) : sample(_sample) { + grainPlayer = new maxiGrainPlayer(); + randomOffset=0; loopStart = 0.0; + sample->getLength(); loopEnd = sample->length; - loopLength =sample->length; - position=0; + loopLength = sample->length; + position=0; looper = 0; - } + } double getNormalisedPosition() { - return position / (double) sample->length; + return position / (double) sample->getLength(); } double getPosition() { @@ -430,7 +292,7 @@ public: void setPosition(double pos) { position = pos * sample->length; - position = maxiMap::clamp(position, 0, sample->length-1); + position = maxiMap::clamp<double>(position, 0, sample->length-1); } void setLoopStart(double val) { @@ -442,26 +304,519 @@ public: loopEnd = val * sample->length; loopLength = loopEnd - loopStart; } - - ~maxiPitchStretch() { - delete grainPlayer; - } - - inline double play(double speed, double rate, double grainLength, int overlaps, double posMod=0.0) { - position = position + (1 * rate); + + + bool hasEnded() { + return position == loopEnd; + } + + ~maxiTimePitchStretch() { + delete grainPlayer; + } + + inline double play(double speed, double rate, double grainLength, int overlaps, double posMod=0.0) { + position = position + rate; + if (position >= loopEnd) position-= loopLength; + if (position < loopStart) position += loopLength; + return playNextGrain(speed, rate, grainLength, overlaps, posMod); + } + + inline double playOnce(double speed, double rate, double grainLength, int overlaps, double posMod=0.0) { + position = position + rate; + if (position >= loopEnd) position = loopEnd; + if (position < loopStart) position = loopEnd; + float val = 0; + if (position < loopEnd) + val = playNextGrain(speed, rate, grainLength, overlaps, posMod); + return val; + } + +protected: + inline double playNextGrain(double speed, double rate, double grainLength, int overlaps, double posMod) { looper++; - if (position >= loopEnd) position-= loopLength; - if (position < loopStart) position += loopLength; - double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; + double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; if (looper > cycleLength + randomOffset) { looper -= (cycleLength + randomOffset); - maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache); - grainPlayer->addGrain(g); + double pos = max(min(static_cast<double>(1.0), (position / sample->length) + posMod),static_cast<double>(0.0)); + maxiGrain<F, maxiSample> *g = new maxiGrain<F, maxiSample>(sample, + pos, + grainLength, speed, &windowCache); + grainPlayer->addGrain(g); randomOffset = rand() % 10; - } - return grainPlayer->play(); - } - + } + return grainPlayer->play(); + } + }; -#endif
\ No newline at end of file + +#endif /* maxiGrains_2_hpp */ + + +// +// +//#ifndef _MAXI_GRAINS_H +//#define _MAXI_GRAINS_H +//#include "maximilian.h" +// +//#if defined(__APPLE_CC__) +//#include "accelerate/accelerate.h" +////Mac users can uncommment the line below to use Apple's accelerate framework for calculating grains. This gives ~300% speed improvement and better sound quality, but doesn't work well on all machines. +//#define MAXIGRAINFAST +//#endif +// +//#include <list> +// +//typedef unsigned long ulong; +// +////window functions from http://en.wikipedia.org/wiki/Window_function#High-_and_moderate-resolution_windows +// +//struct hannWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return 0.5 * (1.0 - cos((2.0 * PI * windowPos) / (windowLength - 1))); +// } +//}; +// +////this window can produce clicks +//struct hammingWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return 0.54 - (0.46 * cos((2.0 * PI * windowPos) / (windowLength - 1))); +// } +//}; +// +// +//struct cosineWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return sin((PI * windowPos) / (windowLength - 1)); +// } +//}; +// +//struct rectWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return 1; +// } +//}; +// +//struct triangleWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return (2.0 / (windowLength-1.0)) * (((windowLength-1.0)/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0))); +// } +//}; +// +//struct triangleNZWinFunctor { +// //non zero end points +// inline double operator()(ulong windowLength, ulong windowPos) { +// return (2.0 / windowLength) * ((windowLength/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0))); +// } +//}; +// +//struct blackmanHarrisWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return 0.35875 - +// (0.48829 * cos((2 * PI * windowPos) / (windowLength-1))) + +// (0.14128 * cos((4 * PI * windowPos) / (windowLength-1))) + +// (0.01168 * cos((6 * PI * windowPos) / (windowLength-1))); +// } +//}; +// +//struct blackmanNutallWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return 0.3635819 - +// (0.4891775 * cos((2 * PI * windowPos) / (windowLength-1))) + +// (0.1365995 * cos((4 * PI * windowPos) / (windowLength-1))) + +// (0.0106411 * cos((6 * PI * windowPos) / (windowLength-1))); +// } +//}; +// +//struct gaussianWinFunctor { +// double gausDivisor; +// gaussianWinFunctor() { +// init(0.3); +// } +// gaussianWinFunctor(double kurtosis) { +// init(kurtosis); +// } +// void init(double kurtosis) { +// gausDivisor = (-2.0 * kurtosis * kurtosis); +// } +// inline double operator()(ulong windowLength, ulong windowPos) { +// double phase = ((windowPos / (double) windowLength) - 0.5) * 2.0; +// return exp((phase * phase) / gausDivisor); +// } +//}; +// +// +//template<typename F> +//class maxiGrainWindowCache { +//public: +// unsigned int cacheSize; +// +// maxiGrainWindowCache() { +// cacheSize = maxiSettings::sampleRate / 2.0; //allocate mem for up to 500ms grains +// cache = (double**)malloc(cacheSize * sizeof(double*)); +// for(int i=0; i < cacheSize; i++) { +// cache[i] = NULL; +// } +// } +// +// ~maxiGrainWindowCache() { +// for(int i=0; i < cacheSize; i++) { +// if(NULL != cache[i]) { +// free(cache[i]); +// } +// } +// free(cache); +// } +// +// double* getWindow(const unsigned int length) { +// if (NULL == cache[length]) { +// cache[length] = (double*)malloc(length * sizeof(double)); +// for(int i=0; i < length; i++) { +// cache[length][i] = F()(length, i); +// } +// } +// return cache[length]; +// } +// +//private: +// double** cache; +// +//}; +// +//class maxiGrainBase { +//public: +// virtual double play() {} +// virtual ~maxiGrainBase() {} +// bool finished; +//}; +// +//template<typename F> +//class maxiGrain : public maxiGrainBase { +//public: +// maxiSample *sample; +// double pos; +// double dur; +// long sampleStartPos; +// long sampleIdx; +// long sampleDur; +// long sampleEndPos; +// double freq; +// double speed; +// double inc; +// double frequency; +// double* window; +// short* buffer; +//#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) +// double* grainSamples; +//#endif +// /* +// position between 0.0 and 1.0 +// duration in seconds +// */ +// maxiGrain(maxiSample *sample, const double position, const double duration, const double speed, maxiGrainWindowCache<F> *windowCache) :sample(sample), pos(position), dur(duration), speed(speed) +// { +// buffer = sample->temp; +// sampleStartPos = sample->length * pos; +// sampleDur = dur * (double)sample->mySampleRate; +// sampleDurMinusOne = sampleDur - 1; +// sampleIdx = 0; +// finished = 0; +// freq = 1.0 / dur; +// sampleEndPos = min(sample->length, sampleStartPos + sampleDur); +// frequency = freq * speed; +// if (frequency > 0) { +// pos = sampleStartPos; +// }else{ +// pos = sampleEndPos; +// } +// if (frequency != 0) { +// inc = sampleDur/(maxiSettings::sampleRate/frequency); +// }else +// inc = 0; +// window = windowCache->getWindow(sampleDur); +// +//#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) +// //premake the grain using fast vector functions, and quadratic interpolation +// double *sourceData = (double*)malloc(sampleDur * sizeof(double)); +// short* buffer = (short *)sample->temp; +// //convert sample to double data +// vDSP_vflt16D(buffer + sampleStartPos, 1, sourceData, 1, min(sampleDur, sample->length - sampleStartPos)); +// //todo: wraping code +// +// grainSamples = (double*)malloc(sampleDur * sizeof(double)); +// //make list of interpolation indexes +// double* interpIndexes = (double*)malloc(sampleDur * sizeof(double)); +// double interpPos = sampleStartPos; +// for(int i=0; i < sampleDur; i++) { +// interpIndexes[i] = interpPos - sampleStartPos; +// interpPos += fabs(inc); +// } +// vDSP_vqintD(sourceData, interpIndexes, 1, grainSamples, 1, sampleDur, sampleDur); +// if (frequency < 0) { +// vDSP_vrvrsD(grainSamples,1, sampleDur); +// } +// static double divFactor = 32767.0; +// vDSP_vsdivD(grainSamples, 1, &divFactor, grainSamples, 1, sampleDur); +// vDSP_vmulD(grainSamples, 1, window, 1, grainSamples, 1, sampleDur); +// delete sourceData, interpIndexes; +//#endif +// } +// +// ~maxiGrain() { +//#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) +// delete[] grainSamples; +//#endif +// } +// +// inline double play() { +// double output = 0.0; +// if (!finished) { +//#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) +// output = grainSamples[sampleIdx]; +//#else +// envValue = window[sampleIdx]; +// double remainder; +// pos += inc; +// if (pos >= sample->length) +// pos -= sample->length; +// else if (pos < 0) +// pos += sample->length; +// +// long posl = floor(pos); +// remainder = pos - posl; +// long a = posl; +// long b = posl+1; +// if (b >= sample->length) { +// b = 0; +// } +// output = (double) ((1-remainder) * buffer[a] + +// remainder * buffer[b])/32767.0;//linear interpolation +// output *= envValue; +//#endif +// } +// sampleIdx++; +// if (sampleIdx == sampleDur) finished = true; +// return output; +// } +// +//protected: +// maxiGrain(); +// double envValue; +// ulong sampleDurMinusOne; +//}; +// +// +//typedef list<maxiGrainBase*> grainList; +// +//class maxiGrainPlayer { +//public: +// grainList grains; +// maxiSample *sample; +// +// maxiGrainPlayer(maxiSample *sample) : sample(sample) { +// } +// +// void addGrain(maxiGrainBase *g) { +// grains.push_back(g); +// } +// +// inline double play() { +// double total = 0.0; +// grainList::iterator it = grains.begin(); +// while(it != grains.end()) { +// total += (*it)->play(); +// if ((*it)->finished) { +// delete(*it); +// it = grains.erase(it); +// }else{ +// it++; +// } +// } +// return total; +// } +//}; +// +//template<typename F> +//class maxiTimestretch { +//protected: +// double position; +//public: +// maxiSample *sample; +// maxiGrainPlayer *grainPlayer; +// maxiGrainWindowCache<F> windowCache; +// double randomOffset; +// double looper; +// +// +// +// maxiTimestretch(maxiSample *sample) : sample(sample) { +// position=0; +// looper = 0; +// grainPlayer = new maxiGrainPlayer(sample); +// randomOffset=0; +// } +// +// ~maxiTimestretch() { +// delete grainPlayer; +// } +// +// double getNormalisedPosition() { +// return position / (double) sample->length; +// } +// +// double getPosition() { +// return position; +// } +// +// void setPosition(double pos) { +// position = pos * sample->length; +// position = maxiMap::clamp<double>(position, 0, sample->length-1); +// } +// +// +// //play at a speed +// inline double play(double speed, double grainLength, int overlaps, double posMod=0.0) { +// position = position + speed; +// looper++; +// if (position > sample->length) position-= sample->length; +// if (position < 0) position += sample->length; +// double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; +// if (looper > cycleLength + randomOffset) { +// looper -= (cycleLength + randomOffset); +// speed = (speed > 0 ? 1 : -1); +// maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache); +// grainPlayer->addGrain(g); +// randomOffset = rand() % 10; +// } +// return grainPlayer->play(); +// } +// +// +// //provide your own position iteration +// inline double play2(double pos, double grainLength, int overlaps) { +// looper++; +// pos *= sample->length; +// if (0 == floor(fmod(looper, grainLength * maxiSettings::sampleRate / overlaps))) { +// maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(pos / sample->length)),0.0), grainLength, 1, &windowCache); +// grainPlayer->addGrain(g); +// } +// return grainPlayer->play(); +// } +//}; +// +////in maxiTimeStretch, the speed is either 1 or -1, and the actual speed value only affects the grain position +////in maxiPitchShift, speed is uncoupled from position and allowed to set it's value incrementally, resulting in pitchshift. +////with both high speed values and negative speed values there are some terrific artefacts! +// +//template<typename F> +//class maxiPitchShift { +//public: +// double position; +// long cycles; +// maxiSample *sample; +// maxiGrainPlayer *grainPlayer; +// maxiGrainWindowCache<F> windowCache; +// double randomOffset; +// +// maxiPitchShift(maxiSample *sample) : sample(sample) { +// position=0; +// cycles=0; +// grainPlayer = new maxiGrainPlayer(sample); +// randomOffset=0; +// } +// +// ~maxiPitchShift() { +// delete grainPlayer; +// } +// +// double play(double speed, double grainLength, int overlaps, double posMod=0.0) { +// position = position + 1; +// cycles++; +// if (position > sample->length) position=0; +// if (position < 0) position = sample->length; +// double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; +// double cycleMod = fmod(cycles, cycleLength + randomOffset); +// if (0 == floor(cycleMod)) { +// // cout << cycleMod << endl; +// //speed = (speed > 0 ? 1 : -1); +// speed = speed - ((cycleMod / cycleLength) * 0.1); +// maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache); +// grainPlayer->addGrain(g); +// // cout << grainPlayer->grains.size() << endl; +// // randomOffset = rand() % 10; +// // randomOffset = rand() % 10; +// } +// return grainPlayer->play(); +// } +// +//}; +// +////and here's maxiPitchStretch. Args to the play function are basically speed for 'pitch' and rate for playback rate. +////the rest is the same. +// +//template<typename F> +//class maxiPitchStretch { +//public: +// double position; +// maxiSample *sample; +// maxiGrainPlayer *grainPlayer; +// maxiGrainWindowCache<F> windowCache; +// double randomOffset; +// long loopStart, loopEnd, loopLength; +// double looper; +// +// maxiPitchStretch(maxiSample *sample) : sample(sample) { +// grainPlayer = new maxiGrainPlayer(sample); +// randomOffset=0; +// loopStart = 0.0; +// loopEnd = sample->length; +// loopLength =sample->length; +// position=0; +// looper = 0; +// } +// +// double getNormalisedPosition() { +// return position / (double) sample->length; +// } +// +// double getPosition() { +// return position; +// } +// +// void setPosition(double pos) { +// position = pos * sample->length; +// position = maxiMap::clamp<double>(position, 0, sample->length-1); +// } +// +// void setLoopStart(double val) { +// loopStart = val * sample->length; +// loopLength = loopEnd - loopStart; +// } +// +// void setLoopEnd(double val) { +// loopEnd = val * sample->length; +// loopLength = loopEnd - loopStart; +// } +// +// ~maxiPitchStretch() { +// delete grainPlayer; +// } +// +// inline double play(double speed, double rate, double grainLength, int overlaps, double posMod=0.0) { +// position = position + (1 * rate); +// looper++; +// if (position >= loopEnd) position-= loopLength; +// if (position < loopStart) position += loopLength; +// double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; +// if (looper > cycleLength + randomOffset) { +// looper -= (cycleLength + randomOffset); +// maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache); +// grainPlayer->addGrain(g); +// randomOffset = rand() % 10; +// } +// return grainPlayer->play(); +// } +// +//}; +// +//#endif
\ No newline at end of file @@ -5,12 +5,12 @@ maxiDyn compressor; //this is a compressor double out; void setup() {//some inits - beats.load("/Users/mzed/GIT/Maximilian/beat2.wav");//load in your samples. Provide the full path to a wav file. + beats.load("/Users/michaelgrierson/Documents/workspace/Maximilian/beat2.wav");//load in your samples. Provide the full path to a wav file. printf("Summary:\n%s", beats.getSummary());//get info on samples if you like. - compressor.setAttack(100); - compressor.setRelease(300); - compressor.setThreshold(0.25); + compressor.setAttack(200); + compressor.setRelease(500); + compressor.setThreshold(0.2); compressor.setRatio(5); //you can set these any time you like. diff --git a/openFrameworks/ofxMaxim/libs/maxiGrains.h b/openFrameworks/ofxMaxim/libs/maxiGrains.h index fb3e102..5fd5beb 100644 --- a/openFrameworks/ofxMaxim/libs/maxiGrains.h +++ b/openFrameworks/ofxMaxim/libs/maxiGrains.h @@ -1,13 +1,13 @@ -#ifndef _MAXI_GRAINS_H -#define _MAXI_GRAINS_H +#ifndef maxiGrains_2_hpp +#define maxiGrains_2_hpp #include "maximilian.h" #if defined(__APPLE_CC__) #include "accelerate/accelerate.h" //Mac users can uncommment the line below to use Apple's accelerate framework for calculating grains. This gives ~300% speed improvement and better sound quality, but doesn't work well on all machines. -//#define MAXIGRAINFAST +//#define MAXIGRAINFAST #endif #include <list> @@ -17,214 +17,184 @@ typedef unsigned long ulong; //window functions from http://en.wikipedia.org/wiki/Window_function#High-_and_moderate-resolution_windows struct hannWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return 0.5 * (1.0 - cos((2.0 * PI * windowPos) / (windowLength - 1))); - } + inline double operator()(ulong windowLength, ulong windowPos) { + return 0.5 * (1.0 - cos((2.0 * PI * windowPos) / (windowLength - 1))); + } }; //this window can produce clicks struct hammingWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return 0.54 - (0.46 * cos((2.0 * PI * windowPos) / (windowLength - 1))); - } + inline double operator()(ulong windowLength, ulong windowPos) { + return 0.54 - (0.46 * cos((2.0 * PI * windowPos) / (windowLength - 1))); + } }; struct cosineWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return sin((PI * windowPos) / (windowLength - 1)); - } + inline double operator()(ulong windowLength, ulong windowPos) { + return sin((PI * windowPos) / (windowLength - 1)); + } }; struct rectWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return 1; - } + inline double operator()(ulong windowLength, ulong windowPos) { + return 1; + } }; struct triangleWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return (2.0 / (windowLength-1.0)) * (((windowLength-1.0)/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0))); - } + inline double operator()(ulong windowLength, ulong windowPos) { + return (2.0 / (windowLength-1.0)) * (((windowLength-1.0)/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0))); + } }; struct triangleNZWinFunctor { - //non zero end points - inline double operator()(ulong windowLength, ulong windowPos) { - return (2.0 / windowLength) * ((windowLength/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0))); - } + //non zero end points + inline double operator()(ulong windowLength, ulong windowPos) { + return (2.0 / windowLength) * ((windowLength/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0))); + } }; struct blackmanHarrisWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return 0.35875 - - (0.48829 * cos((2 * PI * windowPos) / (windowLength-1))) + - (0.14128 * cos((4 * PI * windowPos) / (windowLength-1))) + - (0.01168 * cos((6 * PI * windowPos) / (windowLength-1))); - } + inline double operator()(ulong windowLength, ulong windowPos) { + return 0.35875 - + (0.48829 * cos((2 * PI * windowPos) / (windowLength-1))) + + (0.14128 * cos((4 * PI * windowPos) / (windowLength-1))) + + (0.01168 * cos((6 * PI * windowPos) / (windowLength-1))); + } }; struct blackmanNutallWinFunctor { - inline double operator()(ulong windowLength, ulong windowPos) { - return 0.3635819 - - (0.4891775 * cos((2 * PI * windowPos) / (windowLength-1))) + - (0.1365995 * cos((4 * PI * windowPos) / (windowLength-1))) + - (0.0106411 * cos((6 * PI * windowPos) / (windowLength-1))); - } + inline double operator()(ulong windowLength, ulong windowPos) { + return 0.3635819 - + (0.4891775 * cos((2 * PI * windowPos) / (windowLength-1))) + + (0.1365995 * cos((4 * PI * windowPos) / (windowLength-1))) + + (0.0106411 * cos((6 * PI * windowPos) / (windowLength-1))); + } }; struct gaussianWinFunctor { - double gausDivisor; + double o; gaussianWinFunctor() { - init(0.3); - } - gaussianWinFunctor(double kurtosis) { - init(kurtosis); + o = 0.02; //compatible with MPTK } - void init(double kurtosis) { - gausDivisor = (-2.0 * kurtosis * kurtosis); + inline double operator()(ulong windowLength, ulong windowPos) { + double p = 1.0/(2.0*o*(windowLength+1)*(windowLength+1)); + double k = (double)windowPos-((double)(windowLength-1))/2.0; + return exp(-k*k*p); } - inline double operator()(ulong windowLength, ulong windowPos) { - double phase = ((windowPos / (double) windowLength) - 0.5) * 2.0; - return exp((phase * phase) / gausDivisor); - } }; template<typename F> class maxiGrainWindowCache { public: - unsigned int cacheSize; - - maxiGrainWindowCache() { - cacheSize = maxiSettings::sampleRate / 2.0; //allocate mem for up to 500ms grains - cache = (double**)malloc(cacheSize * sizeof(double*)); - for(int i=0; i < cacheSize; i++) { - cache[i] = NULL; - } - } - - ~maxiGrainWindowCache() { - for(int i=0; i < cacheSize; i++) { - if(NULL != cache[i]) { - free(cache[i]); - } - } + unsigned int cacheSize; + + maxiGrainWindowCache() { + cacheSize = maxiSettings::sampleRate / 2.0; //allocate mem for up to 500ms grains + cache = (double**)malloc(cacheSize * sizeof(double*)); + for(int i=0; i < cacheSize; i++) { + cache[i] = NULL; + } + } + + ~maxiGrainWindowCache() { + for(int i=0; i < cacheSize; i++) { + if(NULL != cache[i]) { + free(cache[i]); + } + } free(cache); - } - - double* getWindow(const unsigned int length) { - if (NULL == cache[length]) { - cache[length] = (double*)malloc(length * sizeof(double)); - for(int i=0; i < length; i++) { - cache[length][i] = F()(length, i); - } - } - return cache[length]; - } - + } + + double* getWindow(const unsigned int length) { + if (NULL == cache[length]) { + cache[length] = (double*)malloc(length * sizeof(double)); + for(int i=0; i < length; i++) { + cache[length][i] = F()(length, i); + } + } + return cache[length]; + } + private: - double** cache; - + double** cache; + }; class maxiGrainBase { public: - virtual double play() {} + virtual double play() {} virtual ~maxiGrainBase() {} - bool finished; + bool finished; }; -template<typename F> +template<class F, class maxiSample> class maxiGrain : public maxiGrainBase { public: - maxiSample *sample; + maxiSample *sample; double pos; - double dur; - long sampleStartPos; - long sampleIdx; - long sampleDur; - long sampleEndPos; - double freq; - double speed; - double inc; - double frequency; - double* window; - short* buffer; + double dur; + long sampleStartPos; + long sampleIdx; + long sampleDur; + long sampleEndPos; + double freq; + double speed; + double inc; + double frequency; + double* window; + // short* buffer; #if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) - double* grainSamples; + // double* grainSamples; #endif - /* - position between 0.0 and 1.0 - duration in seconds - */ - maxiGrain(maxiSample *sample, const double position, const double duration, const double speed, maxiGrainWindowCache<F> *windowCache) :sample(sample), pos(position), dur(duration), speed(speed) - { - buffer = sample->temp; - sampleStartPos = sample->length * pos; - sampleDur = dur * (double)sample->mySampleRate; - sampleDurMinusOne = sampleDur - 1; - sampleIdx = 0; - finished = 0; - freq = 1.0 / dur; - sampleEndPos = min(sample->length, sampleStartPos + sampleDur); - frequency = freq * speed; - if (frequency > 0) { - pos = sampleStartPos; - }else{ - pos = sampleEndPos; - } + /* + position between 0.0 and 1.0 + duration in seconds + */ + maxiGrain(maxiSample *_sample, const double position, const double duration, const double speed, maxiGrainWindowCache<F> *windowCache) :sample(_sample), pos(position), dur(duration), speed(speed) + { + // buffer = sample->temp; + sampleStartPos = (sample->length) * pos; + sampleDur = dur * (double)maxiSettings::sampleRate; + sampleDurMinusOne = sampleDur - 1; + sampleIdx = 0; + finished = 0; + freq = 1.0 / dur; + sampleEndPos = min(sample->length, sampleStartPos + sampleDur); + frequency = freq * speed; + if (frequency > 0) { + pos = sampleStartPos; + }else{ + pos = sampleEndPos; + } if (frequency != 0) { inc = sampleDur/(maxiSettings::sampleRate/frequency); }else inc = 0; - window = windowCache->getWindow(sampleDur); - -#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) - //premake the grain using fast vector functions, and quadratic interpolation - double *sourceData = (double*)malloc(sampleDur * sizeof(double)); - short* buffer = (short *)sample->temp; - //convert sample to double data - vDSP_vflt16D(buffer + sampleStartPos, 1, sourceData, 1, min(sampleDur, sample->length - sampleStartPos)); - //todo: wraping code - - grainSamples = (double*)malloc(sampleDur * sizeof(double)); - //make list of interpolation indexes - double* interpIndexes = (double*)malloc(sampleDur * sizeof(double)); - double interpPos = sampleStartPos; - for(int i=0; i < sampleDur; i++) { - interpIndexes[i] = interpPos - sampleStartPos; - interpPos += fabs(inc); - } - vDSP_vqintD(sourceData, interpIndexes, 1, grainSamples, 1, sampleDur, sampleDur); - if (frequency < 0) { - vDSP_vrvrsD(grainSamples,1, sampleDur); - } - static double divFactor = 32767.0; - vDSP_vsdivD(grainSamples, 1, &divFactor, grainSamples, 1, sampleDur); - vDSP_vmulD(grainSamples, 1, window, 1, grainSamples, 1, sampleDur); - delete sourceData, interpIndexes; -#endif - } - - ~maxiGrain() { + window = windowCache->getWindow(sampleDur); + + } + + ~maxiGrain() { #if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) - delete[] grainSamples; + delete[] grainSamples; #endif - } - - inline double play() { - double output = 0.0; - if (!finished) { + } + + inline double play() { + double output = 0.0; + if (!finished) { #if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) - output = grainSamples[sampleIdx]; + // output = grainSamples[sampleIdx]; #else - envValue = window[sampleIdx]; - double remainder; + envValue = window[sampleIdx]; + double remainder; pos += inc; - if (pos >= sample->length) + if (pos >= sample->length) pos -= sample->length; - else if (pos < 0) + else if (pos < 0) pos += sample->length; long posl = floor(pos); @@ -234,20 +204,21 @@ public: if (b >= sample->length) { b = 0; } - output = (double) ((1-remainder) * buffer[a] + - remainder * buffer[b])/32767.0;//linear interpolation - output *= envValue; + //output = (double) ((1-remainder) * sample->operator[](a) + + // remainder * sample->operator[](b))/32767.0;//linear interpolation + output = (double) ((1-remainder) * sample->temp[a] + remainder * sample->temp[b])/32767.0;//linear interpolation + output *= envValue; #endif - } - sampleIdx++; - if (sampleIdx == sampleDur) finished = true; - return output; - } - -protected: - maxiGrain(); - double envValue; - ulong sampleDurMinusOne; + } + sampleIdx++; + if (sampleIdx == sampleDur) finished = true; + return output; + } + +protected: + maxiGrain(); + double envValue; + ulong sampleDurMinusOne; }; @@ -255,173 +226,64 @@ typedef list<maxiGrainBase*> grainList; class maxiGrainPlayer { public: - grainList grains; - maxiSample *sample; - - maxiGrainPlayer(maxiSample *sample) : sample(sample) { - } - - void addGrain(maxiGrainBase *g) { - grains.push_back(g); - } - - inline double play() { - double total = 0.0; - grainList::iterator it = grains.begin(); - while(it != grains.end()) { - total += (*it)->play(); - if ((*it)->finished) { - delete(*it); - it = grains.erase(it); - }else{ - it++; - } - } - return total; - } -}; - -template<typename F> -class maxiTimestretch { -protected: - double position; -public: - maxiSample *sample; - maxiGrainPlayer *grainPlayer; - maxiGrainWindowCache<F> windowCache; - double randomOffset; - double looper; - - - - maxiTimestretch(maxiSample *sample) : sample(sample) { - position=0; - looper = 0; - grainPlayer = new maxiGrainPlayer(sample); - randomOffset=0; - } - - ~maxiTimestretch() { - delete grainPlayer; - } + grainList grains; + // maxiSample *sample; + // source *sample; - double getNormalisedPosition() { - return position / (double) sample->length; - } - double getPosition() { - return position; - } + // maxiGrainPlayer(maxiSample *sample) : sample(sample) { + // } - void setPosition(double pos) { - position = pos * sample->length; - position = maxiMap::clamp<double>(position, 0, sample->length-1); + // maxiGrainPlayer(source *sample) : sample(sample) { + // } + + void addGrain(maxiGrainBase *g) { + grains.push_back(g); } - - - //play at a speed - inline double play(double speed, double grainLength, int overlaps, double posMod=0.0) { - position = position + speed; - looper++; - if (position > sample->length) position-= sample->length; - if (position < 0) position += sample->length; - double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; - if (looper > cycleLength + randomOffset) { - looper -= (cycleLength + randomOffset); - speed = (speed > 0 ? 1 : -1); - maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache); - grainPlayer->addGrain(g); - randomOffset = rand() % 10; - } - return grainPlayer->play(); - } - - //provide your own position iteration - inline double play2(double pos, double grainLength, int overlaps) { - looper++; - pos *= sample->length; - if (0 == floor(fmod(looper, grainLength * maxiSettings::sampleRate / overlaps))) { - maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(pos / sample->length)),0.0), grainLength, 1, &windowCache); - grainPlayer->addGrain(g); - } - return grainPlayer->play(); - } -}; - -//in maxiTimeStretch, the speed is either 1 or -1, and the actual speed value only affects the grain position -//in maxiPitchShift, speed is uncoupled from position and allowed to set it's value incrementally, resulting in pitchshift. -//with both high speed values and negative speed values there are some terrific artefacts! - -template<typename F> -class maxiPitchShift { -public: - double position; - long cycles; - maxiSample *sample; - maxiGrainPlayer *grainPlayer; - maxiGrainWindowCache<F> windowCache; - double randomOffset; - - maxiPitchShift(maxiSample *sample) : sample(sample) { - position=0; - cycles=0; - grainPlayer = new maxiGrainPlayer(sample); - randomOffset=0; - } - - ~maxiPitchShift() { - delete grainPlayer; - } - - double play(double speed, double grainLength, int overlaps, double posMod=0.0) { - position = position + 1; - cycles++; - if (position > sample->length) position=0; - if (position < 0) position = sample->length; - double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; - double cycleMod = fmod(cycles, cycleLength + randomOffset); - if (0 == floor(cycleMod)) { - // cout << cycleMod << endl; - //speed = (speed > 0 ? 1 : -1); - speed = speed - ((cycleMod / cycleLength) * 0.1); - maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache); - grainPlayer->addGrain(g); - // cout << grainPlayer->grains.size() << endl; - // randomOffset = rand() % 10; - // randomOffset = rand() % 10; - } - return grainPlayer->play(); - } - + inline double play() { + double total = 0.0; + grainList::iterator it = grains.begin(); + while(it != grains.end()) { + total += (*it)->play(); + if ((*it)->finished) { + delete(*it); + it = grains.erase(it); + }else{ + it++; + } + } + return total; + } }; //and here's maxiPitchStretch. Args to the play function are basically speed for 'pitch' and rate for playback rate. //the rest is the same. -template<typename F> -class maxiPitchStretch { +template<class F, class maxiSample> +class maxiTimePitchStretch { public: - double position; - maxiSample *sample; - maxiGrainPlayer *grainPlayer; - maxiGrainWindowCache<F> windowCache; - double randomOffset; + double position; + maxiSample *sample; + maxiGrainPlayer *grainPlayer; + maxiGrainWindowCache<F> windowCache; + double randomOffset; long loopStart, loopEnd, loopLength; double looper; - - maxiPitchStretch(maxiSample *sample) : sample(sample) { - grainPlayer = new maxiGrainPlayer(sample); - randomOffset=0; + + maxiTimePitchStretch(maxiSample *_sample) : sample(_sample) { + grainPlayer = new maxiGrainPlayer(); + randomOffset=0; loopStart = 0.0; + sample->getLength(); loopEnd = sample->length; - loopLength =sample->length; - position=0; + loopLength = sample->length; + position=0; looper = 0; - } + } double getNormalisedPosition() { - return position / (double) sample->length; + return position / (double) sample->getLength(); } double getPosition() { @@ -442,26 +304,519 @@ public: loopEnd = val * sample->length; loopLength = loopEnd - loopStart; } - - ~maxiPitchStretch() { - delete grainPlayer; - } - - inline double play(double speed, double rate, double grainLength, int overlaps, double posMod=0.0) { - position = position + (1 * rate); + + + bool hasEnded() { + return position == loopEnd; + } + + ~maxiTimePitchStretch() { + delete grainPlayer; + } + + inline double play(double speed, double rate, double grainLength, int overlaps, double posMod=0.0) { + position = position + rate; + if (position >= loopEnd) position-= loopLength; + if (position < loopStart) position += loopLength; + return playNextGrain(speed, rate, grainLength, overlaps, posMod); + } + + inline double playOnce(double speed, double rate, double grainLength, int overlaps, double posMod=0.0) { + position = position + rate; + if (position >= loopEnd) position = loopEnd; + if (position < loopStart) position = loopEnd; + float val = 0; + if (position < loopEnd) + val = playNextGrain(speed, rate, grainLength, overlaps, posMod); + return val; + } + +protected: + inline double playNextGrain(double speed, double rate, double grainLength, int overlaps, double posMod) { looper++; - if (position >= loopEnd) position-= loopLength; - if (position < loopStart) position += loopLength; - double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; + double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; if (looper > cycleLength + randomOffset) { looper -= (cycleLength + randomOffset); - maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache); - grainPlayer->addGrain(g); + double pos = max(min(static_cast<double>(1.0), (position / sample->length) + posMod),static_cast<double>(0.0)); + maxiGrain<F, maxiSample> *g = new maxiGrain<F, maxiSample>(sample, + pos, + grainLength, speed, &windowCache); + grainPlayer->addGrain(g); randomOffset = rand() % 10; - } - return grainPlayer->play(); - } - + } + return grainPlayer->play(); + } + }; -#endif
\ No newline at end of file + +#endif /* maxiGrains_2_hpp */ + + +// +// +//#ifndef _MAXI_GRAINS_H +//#define _MAXI_GRAINS_H +//#include "maximilian.h" +// +//#if defined(__APPLE_CC__) +//#include "accelerate/accelerate.h" +////Mac users can uncommment the line below to use Apple's accelerate framework for calculating grains. This gives ~300% speed improvement and better sound quality, but doesn't work well on all machines. +//#define MAXIGRAINFAST +//#endif +// +//#include <list> +// +//typedef unsigned long ulong; +// +////window functions from http://en.wikipedia.org/wiki/Window_function#High-_and_moderate-resolution_windows +// +//struct hannWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return 0.5 * (1.0 - cos((2.0 * PI * windowPos) / (windowLength - 1))); +// } +//}; +// +////this window can produce clicks +//struct hammingWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return 0.54 - (0.46 * cos((2.0 * PI * windowPos) / (windowLength - 1))); +// } +//}; +// +// +//struct cosineWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return sin((PI * windowPos) / (windowLength - 1)); +// } +//}; +// +//struct rectWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return 1; +// } +//}; +// +//struct triangleWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return (2.0 / (windowLength-1.0)) * (((windowLength-1.0)/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0))); +// } +//}; +// +//struct triangleNZWinFunctor { +// //non zero end points +// inline double operator()(ulong windowLength, ulong windowPos) { +// return (2.0 / windowLength) * ((windowLength/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0))); +// } +//}; +// +//struct blackmanHarrisWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return 0.35875 - +// (0.48829 * cos((2 * PI * windowPos) / (windowLength-1))) + +// (0.14128 * cos((4 * PI * windowPos) / (windowLength-1))) + +// (0.01168 * cos((6 * PI * windowPos) / (windowLength-1))); +// } +//}; +// +//struct blackmanNutallWinFunctor { +// inline double operator()(ulong windowLength, ulong windowPos) { +// return 0.3635819 - +// (0.4891775 * cos((2 * PI * windowPos) / (windowLength-1))) + +// (0.1365995 * cos((4 * PI * windowPos) / (windowLength-1))) + +// (0.0106411 * cos((6 * PI * windowPos) / (windowLength-1))); +// } +//}; +// +//struct gaussianWinFunctor { +// double gausDivisor; +// gaussianWinFunctor() { +// init(0.3); +// } +// gaussianWinFunctor(double kurtosis) { +// init(kurtosis); +// } +// void init(double kurtosis) { +// gausDivisor = (-2.0 * kurtosis * kurtosis); +// } +// inline double operator()(ulong windowLength, ulong windowPos) { +// double phase = ((windowPos / (double) windowLength) - 0.5) * 2.0; +// return exp((phase * phase) / gausDivisor); +// } +//}; +// +// +//template<typename F> +//class maxiGrainWindowCache { +//public: +// unsigned int cacheSize; +// +// maxiGrainWindowCache() { +// cacheSize = maxiSettings::sampleRate / 2.0; //allocate mem for up to 500ms grains +// cache = (double**)malloc(cacheSize * sizeof(double*)); +// for(int i=0; i < cacheSize; i++) { +// cache[i] = NULL; +// } +// } +// +// ~maxiGrainWindowCache() { +// for(int i=0; i < cacheSize; i++) { +// if(NULL != cache[i]) { +// free(cache[i]); +// } +// } +// free(cache); +// } +// +// double* getWindow(const unsigned int length) { +// if (NULL == cache[length]) { +// cache[length] = (double*)malloc(length * sizeof(double)); +// for(int i=0; i < length; i++) { +// cache[length][i] = F()(length, i); +// } +// } +// return cache[length]; +// } +// +//private: +// double** cache; +// +//}; +// +//class maxiGrainBase { +//public: +// virtual double play() {} +// virtual ~maxiGrainBase() {} +// bool finished; +//}; +// +//template<typename F> +//class maxiGrain : public maxiGrainBase { +//public: +// maxiSample *sample; +// double pos; +// double dur; +// long sampleStartPos; +// long sampleIdx; +// long sampleDur; +// long sampleEndPos; +// double freq; +// double speed; +// double inc; +// double frequency; +// double* window; +// short* buffer; +//#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) +// double* grainSamples; +//#endif +// /* +// position between 0.0 and 1.0 +// duration in seconds +// */ +// maxiGrain(maxiSample *sample, const double position, const double duration, const double speed, maxiGrainWindowCache<F> *windowCache) :sample(sample), pos(position), dur(duration), speed(speed) +// { +// buffer = sample->temp; +// sampleStartPos = sample->length * pos; +// sampleDur = dur * (double)sample->mySampleRate; +// sampleDurMinusOne = sampleDur - 1; +// sampleIdx = 0; +// finished = 0; +// freq = 1.0 / dur; +// sampleEndPos = min(sample->length, sampleStartPos + sampleDur); +// frequency = freq * speed; +// if (frequency > 0) { +// pos = sampleStartPos; +// }else{ +// pos = sampleEndPos; +// } +// if (frequency != 0) { +// inc = sampleDur/(maxiSettings::sampleRate/frequency); +// }else +// inc = 0; +// window = windowCache->getWindow(sampleDur); +// +//#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) +// //premake the grain using fast vector functions, and quadratic interpolation +// double *sourceData = (double*)malloc(sampleDur * sizeof(double)); +// short* buffer = (short *)sample->temp; +// //convert sample to double data +// vDSP_vflt16D(buffer + sampleStartPos, 1, sourceData, 1, min(sampleDur, sample->length - sampleStartPos)); +// //todo: wraping code +// +// grainSamples = (double*)malloc(sampleDur * sizeof(double)); +// //make list of interpolation indexes +// double* interpIndexes = (double*)malloc(sampleDur * sizeof(double)); +// double interpPos = sampleStartPos; +// for(int i=0; i < sampleDur; i++) { +// interpIndexes[i] = interpPos - sampleStartPos; +// interpPos += fabs(inc); +// } +// vDSP_vqintD(sourceData, interpIndexes, 1, grainSamples, 1, sampleDur, sampleDur); +// if (frequency < 0) { +// vDSP_vrvrsD(grainSamples,1, sampleDur); +// } +// static double divFactor = 32767.0; +// vDSP_vsdivD(grainSamples, 1, &divFactor, grainSamples, 1, sampleDur); +// vDSP_vmulD(grainSamples, 1, window, 1, grainSamples, 1, sampleDur); +// delete sourceData, interpIndexes; +//#endif +// } +// +// ~maxiGrain() { +//#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) +// delete[] grainSamples; +//#endif +// } +// +// inline double play() { +// double output = 0.0; +// if (!finished) { +//#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST) +// output = grainSamples[sampleIdx]; +//#else +// envValue = window[sampleIdx]; +// double remainder; +// pos += inc; +// if (pos >= sample->length) +// pos -= sample->length; +// else if (pos < 0) +// pos += sample->length; +// +// long posl = floor(pos); +// remainder = pos - posl; +// long a = posl; +// long b = posl+1; +// if (b >= sample->length) { +// b = 0; +// } +// output = (double) ((1-remainder) * buffer[a] + +// remainder * buffer[b])/32767.0;//linear interpolation +// output *= envValue; +//#endif +// } +// sampleIdx++; +// if (sampleIdx == sampleDur) finished = true; +// return output; +// } +// +//protected: +// maxiGrain(); +// double envValue; +// ulong sampleDurMinusOne; +//}; +// +// +//typedef list<maxiGrainBase*> grainList; +// +//class maxiGrainPlayer { +//public: +// grainList grains; +// maxiSample *sample; +// +// maxiGrainPlayer(maxiSample *sample) : sample(sample) { +// } +// +// void addGrain(maxiGrainBase *g) { +// grains.push_back(g); +// } +// +// inline double play() { +// double total = 0.0; +// grainList::iterator it = grains.begin(); +// while(it != grains.end()) { +// total += (*it)->play(); +// if ((*it)->finished) { +// delete(*it); +// it = grains.erase(it); +// }else{ +// it++; +// } +// } +// return total; +// } +//}; +// +//template<typename F> +//class maxiTimestretch { +//protected: +// double position; +//public: +// maxiSample *sample; +// maxiGrainPlayer *grainPlayer; +// maxiGrainWindowCache<F> windowCache; +// double randomOffset; +// double looper; +// +// +// +// maxiTimestretch(maxiSample *sample) : sample(sample) { +// position=0; +// looper = 0; +// grainPlayer = new maxiGrainPlayer(sample); +// randomOffset=0; +// } +// +// ~maxiTimestretch() { +// delete grainPlayer; +// } +// +// double getNormalisedPosition() { +// return position / (double) sample->length; +// } +// +// double getPosition() { +// return position; +// } +// +// void setPosition(double pos) { +// position = pos * sample->length; +// position = maxiMap::clamp<double>(position, 0, sample->length-1); +// } +// +// +// //play at a speed +// inline double play(double speed, double grainLength, int overlaps, double posMod=0.0) { +// position = position + speed; +// looper++; +// if (position > sample->length) position-= sample->length; +// if (position < 0) position += sample->length; +// double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; +// if (looper > cycleLength + randomOffset) { +// looper -= (cycleLength + randomOffset); +// speed = (speed > 0 ? 1 : -1); +// maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache); +// grainPlayer->addGrain(g); +// randomOffset = rand() % 10; +// } +// return grainPlayer->play(); +// } +// +// +// //provide your own position iteration +// inline double play2(double pos, double grainLength, int overlaps) { +// looper++; +// pos *= sample->length; +// if (0 == floor(fmod(looper, grainLength * maxiSettings::sampleRate / overlaps))) { +// maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(pos / sample->length)),0.0), grainLength, 1, &windowCache); +// grainPlayer->addGrain(g); +// } +// return grainPlayer->play(); +// } +//}; +// +////in maxiTimeStretch, the speed is either 1 or -1, and the actual speed value only affects the grain position +////in maxiPitchShift, speed is uncoupled from position and allowed to set it's value incrementally, resulting in pitchshift. +////with both high speed values and negative speed values there are some terrific artefacts! +// +//template<typename F> +//class maxiPitchShift { +//public: +// double position; +// long cycles; +// maxiSample *sample; +// maxiGrainPlayer *grainPlayer; +// maxiGrainWindowCache<F> windowCache; +// double randomOffset; +// +// maxiPitchShift(maxiSample *sample) : sample(sample) { +// position=0; +// cycles=0; +// grainPlayer = new maxiGrainPlayer(sample); +// randomOffset=0; +// } +// +// ~maxiPitchShift() { +// delete grainPlayer; +// } +// +// double play(double speed, double grainLength, int overlaps, double posMod=0.0) { +// position = position + 1; +// cycles++; +// if (position > sample->length) position=0; +// if (position < 0) position = sample->length; +// double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; +// double cycleMod = fmod(cycles, cycleLength + randomOffset); +// if (0 == floor(cycleMod)) { +// // cout << cycleMod << endl; +// //speed = (speed > 0 ? 1 : -1); +// speed = speed - ((cycleMod / cycleLength) * 0.1); +// maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache); +// grainPlayer->addGrain(g); +// // cout << grainPlayer->grains.size() << endl; +// // randomOffset = rand() % 10; +// // randomOffset = rand() % 10; +// } +// return grainPlayer->play(); +// } +// +//}; +// +////and here's maxiPitchStretch. Args to the play function are basically speed for 'pitch' and rate for playback rate. +////the rest is the same. +// +//template<typename F> +//class maxiPitchStretch { +//public: +// double position; +// maxiSample *sample; +// maxiGrainPlayer *grainPlayer; +// maxiGrainWindowCache<F> windowCache; +// double randomOffset; +// long loopStart, loopEnd, loopLength; +// double looper; +// +// maxiPitchStretch(maxiSample *sample) : sample(sample) { +// grainPlayer = new maxiGrainPlayer(sample); +// randomOffset=0; +// loopStart = 0.0; +// loopEnd = sample->length; +// loopLength =sample->length; +// position=0; +// looper = 0; +// } +// +// double getNormalisedPosition() { +// return position / (double) sample->length; +// } +// +// double getPosition() { +// return position; +// } +// +// void setPosition(double pos) { +// position = pos * sample->length; +// position = maxiMap::clamp<double>(position, 0, sample->length-1); +// } +// +// void setLoopStart(double val) { +// loopStart = val * sample->length; +// loopLength = loopEnd - loopStart; +// } +// +// void setLoopEnd(double val) { +// loopEnd = val * sample->length; +// loopLength = loopEnd - loopStart; +// } +// +// ~maxiPitchStretch() { +// delete grainPlayer; +// } +// +// inline double play(double speed, double rate, double grainLength, int overlaps, double posMod=0.0) { +// position = position + (1 * rate); +// looper++; +// if (position >= loopEnd) position-= loopLength; +// if (position < loopStart) position += loopLength; +// double cycleLength = grainLength * maxiSettings::sampleRate / overlaps; +// if (looper > cycleLength + randomOffset) { +// looper -= (cycleLength + randomOffset); +// maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache); +// grainPlayer->addGrain(g); +// randomOffset = rand() % 10; +// } +// return grainPlayer->play(); +// } +// +//}; +// +//#endif
\ No newline at end of file diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/Makefile b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/Makefile index 8d8e4c0..8d8e4c0 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/Makefile +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/Makefile diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/Project.xcconfig b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/Project.xcconfig index e570b15..e570b15 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/Project.xcconfig +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/Project.xcconfig diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/addons.make b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/addons.make index 328952e..328952e 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/addons.make +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/addons.make diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/.gitkeep b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/.gitkeep index e69de29..e69de29 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/.gitkeep +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/.gitkeep diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/24620__anamorphosis__GMB_Kantilan_1.wav b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/24620__anamorphosis__GMB_Kantilan_1.wav Binary files differindex 81666d1..81666d1 100755 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/24620__anamorphosis__GMB_Kantilan_1.wav +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/24620__anamorphosis__GMB_Kantilan_1.wav diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/2630__Jovica__133_bpm_ATTACK_LOOP_04_electrified_analog_kit_variation_16_mono.wav b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/2630__Jovica__133_bpm_ATTACK_LOOP_04_electrified_analog_kit_variation_16_mono.wav Binary files differindex 490d9ea..490d9ea 100755 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/2630__Jovica__133_bpm_ATTACK_LOOP_04_electrified_analog_kit_variation_16_mono.wav +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/2630__Jovica__133_bpm_ATTACK_LOOP_04_electrified_analog_kit_variation_16_mono.wav diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/26393__brfindla__Calango1berimbau.wav b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/26393__brfindla__Calango1berimbau.wav Binary files differindex a9c93a4..a9c93a4 100755 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/26393__brfindla__Calango1berimbau.wav +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/26393__brfindla__Calango1berimbau.wav diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/59210__suonho__abstract_electrofunkbreakbeats_124bpm_mono.wav b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/59210__suonho__abstract_electrofunkbreakbeats_124bpm_mono.wav Binary files differindex b23c5f0..b23c5f0 100755 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/59210__suonho__abstract_electrofunkbreakbeats_124bpm_mono.wav +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/59210__suonho__abstract_electrofunkbreakbeats_124bpm_mono.wav diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/68373__juskiddink__Cello_open_string_bowed.wav b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/68373__juskiddink__Cello_open_string_bowed.wav Binary files differindex 19064f2..19064f2 100755 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/68373__juskiddink__Cello_open_string_bowed.wav +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/68373__juskiddink__Cello_open_string_bowed.wav diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/71515__Microscopia__Wilhelm_Bruder_Sohne_Organ.wav b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/71515__Microscopia__Wilhelm_Bruder_Sohne_Organ.wav Binary files differindex 98860be..98860be 100755 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/71515__Microscopia__Wilhelm_Bruder_Sohne_Organ.wav +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/71515__Microscopia__Wilhelm_Bruder_Sohne_Organ.wav diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/beat2.wav b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/beat2.wav Binary files differindex c71cee6..c71cee6 100755 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/bin/data/beat2.wav +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/bin/data/beat2.wav diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/config.make b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/config.make index df10f64..df10f64 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/config.make +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/config.make diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/project.pbxproj b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/granular0_92.xcodeproj/project.pbxproj index 755dcd2..755dcd2 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/project.pbxproj +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/granular0_92.xcodeproj/project.pbxproj diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/granular0_92.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 919434a..919434a 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/granular0_92.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/xcshareddata/xcschemes/granular0_92 Debug.xcscheme b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/granular0_92.xcodeproj/xcshareddata/xcschemes/granular0_92 Debug.xcscheme index 6f7c747..6f7c747 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/xcshareddata/xcschemes/granular0_92 Debug.xcscheme +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/granular0_92.xcodeproj/xcshareddata/xcschemes/granular0_92 Debug.xcscheme diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/xcshareddata/xcschemes/granular0_92 Release.xcscheme b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/granular0_92.xcodeproj/xcshareddata/xcschemes/granular0_92 Release.xcscheme index 19fd904..19fd904 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/xcshareddata/xcschemes/granular0_92 Release.xcscheme +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/granular0_92.xcodeproj/xcshareddata/xcschemes/granular0_92 Release.xcscheme diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/openFrameworks-Info.plist b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/openFrameworks-Info.plist index 8d64d2b..8d64d2b 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/openFrameworks-Info.plist +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/openFrameworks-Info.plist diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/src/main.cpp b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/src/main.cpp index e57370b..e57370b 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/src/main.cpp +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/src/main.cpp diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/src/ofApp.cpp b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/src/ofApp.cpp index 7e9bfdf..52ae7b0 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/src/ofApp.cpp +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/src/ofApp.cpp @@ -39,11 +39,11 @@ void ofApp::setup(){ - ts = new maxiTimestretch<grainPlayerWin>(&samp); - ts2 = new maxiTimestretch<grainPlayerWin>(&samp2); - ts3 = new maxiTimestretch<grainPlayerWin>(&samp3); - ts4 = new maxiTimestretch<grainPlayerWin>(&samp4); - ts5 = new maxiTimestretch<grainPlayerWin>(&samp5); + ts = new maxiTimePitchStretch<grainPlayerWin, maxiSample>(&samp); + ts2 = new maxiTimePitchStretch<grainPlayerWin, maxiSample>(&samp2); + ts3 = new maxiTimePitchStretch<grainPlayerWin, maxiSample>(&samp3); + ts4 = new maxiTimePitchStretch<grainPlayerWin, maxiSample>(&samp4); + ts5 = new maxiTimePitchStretch<grainPlayerWin, maxiSample>(&samp5); stretches.push_back(ts); stretches.push_back(ts2); stretches.push_back(ts3); @@ -134,11 +134,9 @@ void ofApp::draw(){ 100 + ((int)(ofGetFrameNum() * 1.4) % 255), ofGetFrameNum() % 255, oct.averages[i] / 20.0 * 255.0); - // ofCircle(ofGetWidth() / 2, ofGetHeight()/2, i * 5); glPushMatrix(); glTranslatef(ofGetWidth()/2,ofGetHeight()/2, 0); glRotatef(0.01 * ofGetFrameNum() * speed * i, 0.01 * ofGetFrameNum() * speed * i,0.01 * ofGetFrameNum() * speed * i, 0); - // glutWireSphere(i * 5, 2 + (10 - (fabs(speed) * 10)), 2 + (fabs(speed) * 10)); ofDrawSphere(0, 0, i * 5); glPopMatrix(); } @@ -165,9 +163,8 @@ void ofApp::audioOut(float * output, int bufferSize, int nChannels) { */ - // wave = stretches[current]->play(speed, grainLength, 5, 0); - wave = stretches[current]->play(speed, 0.1, 4, 0); - // wave = stretches[current]->play2(pos, 0.1, 4); + wave = stretches[current]->play(1.,speed, grainLength, 4, 0); + if (fft.process(wave)) { oct.calculate(fft.magnitudes); } @@ -222,6 +219,8 @@ void ofApp::mouseMoved(int x, int y){ speed = ((double ) x1 / ofGetWidth() * 4.0) - 2.0; grainLength = ((double) y1 / ofGetHeight() * 0.1) + 0.001; + if (grainLength < 0.01 ) grainLength = 0.01; + if (grainLength > 0.4 ) grainLength = 0.4; pos = ((double) x1 / ofGetWidth() * 2.0); // cout << pos << endl; diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/src/ofApp.h b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/src/ofApp.h index 3f8e034..a1d4d64 100644 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/src/ofApp.h +++ b/openFrameworks/openFrameworksExamples/OSX/OF0.9.2_OSX_Granular0_92/src/ofApp.h @@ -56,9 +56,9 @@ public: double wave,sample,outputs[2]; maxiSample samp, samp2, samp3, samp4, samp5; - vector<maxiTimestretch<grainPlayerWin>*> stretches; + vector<maxiTimePitchStretch<grainPlayerWin, maxiSample>*> stretches; maxiMix mymix; - maxiTimestretch<grainPlayerWin> *ts, *ts2, *ts3, *ts4, *ts5; + maxiTimePitchStretch<grainPlayerWin, maxiSample> *ts, *ts2, *ts3, *ts4, *ts5; double speed, grainLength; ofxMaxiFFT fft; diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/project.xcworkspace/xcuserdata/michaelgrierson.xcuserdatad/UserInterfaceState.xcuserstate b/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/project.xcworkspace/xcuserdata/michaelgrierson.xcuserdatad/UserInterfaceState.xcuserstate Binary files differdeleted file mode 100644 index 023c379..0000000 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/project.xcworkspace/xcuserdata/michaelgrierson.xcuserdatad/UserInterfaceState.xcuserstate +++ /dev/null diff --git a/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/xcuserdata/michaelgrierson.xcuserdatad/xcschemes/xcschememanagement.plist b/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/xcuserdata/michaelgrierson.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index f1ba9be..0000000 --- a/openFrameworks/openFrameworksExamples/OSX/granular0_92/granular0_92.xcodeproj/xcuserdata/michaelgrierson.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>SchemeUserState</key> - <dict> - <key>granular0_92 Debug.xcscheme_^#shared#^_</key> - <dict> - <key>orderHint</key> - <integer>0</integer> - </dict> - <key>granular0_92 Release.xcscheme_^#shared#^_</key> - <dict> - <key>orderHint</key> - <integer>1</integer> - </dict> - </dict> - <key>SuppressBuildableAutocreation</key> - <dict> - <key>E4B69B5A0A3A1756003C02F2</key> - <dict> - <key>primary</key> - <true/> - </dict> - </dict> -</dict> -</plist> |
