From b45f635a1220d6fec04251f0c4f7e72ad1ff5389 Mon Sep 17 00:00:00 2001 From: Harry van Haaren Date: Fri, 17 May 2013 09:24:24 +0100 Subject: [PATCH] -Added Pitch-Shift code to looper, fixed some issues --- src/looper.cxx | 69 +++++++++++++++++++++++++++++++++++++++++++-- src/looper.hxx | 24 ++++++++-------- src/metronome.hxx | 3 ++ src/timemanager.hxx | 8 ++++-- 4 files changed, 89 insertions(+), 15 deletions(-) diff --git a/src/looper.cxx b/src/looper.cxx index 7cb89c9..90df868 100644 --- a/src/looper.cxx +++ b/src/looper.cxx @@ -7,6 +7,36 @@ extern Jack* jack; +Looper::Looper(int t) : + track(t), + state(STATE_STOPPED), + numBeats (4), + playedBeats(0), + stopRecordOnBar(false), + endPoint (0), + playPoint (0), + lastWrittenSampleIndex(0) +{ + // init faust pitch shift variables + fSamplingFreq = 44100; + IOTA = 0; + + int bufferSize = 1024; + + for ( int i = 0; i < bufferSize; i++) + tmpBuffer.push_back(0.f); + + for (int i=0; i<65536; i++) + fVec0[i] = 0; + + semitoneShift = 0.0f; + windowSize = 1000; + crossfadeSize = 1000; + + for (int i=0; i<2; i++) + fRec0[i] = 0; +} + void Looper::setState(State s) { if ( state == STATE_RECORDING ) @@ -37,7 +67,7 @@ void Looper::process(int nframes, Buffers* buffers) { if ( playPoint < endPoint ) { - out[i] += sample[playPoint]; + tmpBuffer[i] += sample[playPoint]; } // always update playPoint, even when not playing sound. // it updates the UI of progress @@ -54,7 +84,6 @@ void Looper::process(int nframes, Buffers* buffers) EventLooperProgress e(track, prog ); writeToGuiRingbuffer( &e ); } - // stopRecordOnBar ensures we record right up to the bar measure else if ( state == STATE_RECORDING || stopRecordOnBar ) { @@ -66,6 +95,11 @@ void Looper::process(int nframes, Buffers* buffers) } } } + + + // not pitch-shift the audio in the buffer + pitchShift( nframes, &tmpBuffer[0], out); + } @@ -133,3 +167,34 @@ void Looper::setLoopLength(float l) EventGuiPrint e( buffer ); writeToGuiRingbuffer( &e ); } + + +void Looper::pitchShift(int count, float* input, float* output) +{ + float fSlow0 = windowSize; + float fSlow1 = ((1 + fSlow0) - powf(2,(0.08333333333333333f * semitoneShift))); + float fSlow2 = (1.0f / crossfadeSize); + float fSlow3 = (fSlow0 - 1); + float* input0 = &input[0]; + float* output0 = &output[0]; + + for (int i=0; i #include #include "buffers.hxx" @@ -21,16 +22,7 @@ class Looper : public Observer // for notifications STATE_STOP_QUEUED, }; - Looper(int t) : - track(t), - state(STATE_STOPPED), - numBeats (4), - playedBeats(0), - stopRecordOnBar(false), - endPoint (0), - playPoint (0), - lastWrittenSampleIndex(0) - {} + Looper(int t); void bar(); void beat(); @@ -53,7 +45,17 @@ class Looper : public Observer // for notifications int endPoint, playPoint, lastWrittenSampleIndex; float sample[44100*60]; - + + // Pitch Shifting + void pitchShift(int count, float* input, float* output); + vector tmpBuffer; + int IOTA; + float fVec0[65536]; + float semitoneShift; + float windowSize; + float fRec0[2]; + float crossfadeSize; + float fSamplingFreq; }; #endif // LUPPP_LOOPER_H diff --git a/src/metronome.hxx b/src/metronome.hxx index a347c59..492be4f 100644 --- a/src/metronome.hxx +++ b/src/metronome.hxx @@ -30,6 +30,9 @@ class Metronome : public Observer beatSample[i]= sin(i*scale); barSample [i]= sin(i*scale*1.5); } + + // don't play after creation + playPoint = endPoint + 1; } void setActive(bool a) diff --git a/src/timemanager.hxx b/src/timemanager.hxx index 58dfd71..14d1675 100644 --- a/src/timemanager.hxx +++ b/src/timemanager.hxx @@ -18,7 +18,7 @@ class TimeManager { public: TimeManager(): - fpb(120), + fpb(22050), oldBeat(0) { tapTempoPos = 0; @@ -29,11 +29,13 @@ class TimeManager void setBpm(float bpm) { + //cout << "setBpm() " << bpm << endl; setFpb( 44100 / bpm * 60 ); } void setFpb(float f) { fpb = f; + //cout << "setFpb() " << fpb << endl; char buffer [50]; sprintf (buffer, "TM, setFpb() %i", int(f) ); @@ -48,6 +50,7 @@ class TimeManager void registerObserver(Observer* o) { + //cout << "registerObserver() " << fpb << endl; observers.push_back(o); o->setFpb( fpb ); } @@ -66,13 +69,14 @@ class TimeManager int tapFpb2 = tapTempo[2] - tapTempo[1]; int average = (tapFpb1 + tapFpb2) / 2; - setFpb(average); char buffer [50]; sprintf (buffer, "TM, tap() average = %i", average ); EventGuiPrint e( buffer ); writeToGuiRingbuffer( &e ); + setFpb(average); + // reset, so next 3 taps restart process tapTempoPos = 0; }