diff --git a/src/filters/filters.cpp b/src/filters/filters.cpp
index 7877c63..60c32e0 100644
--- a/src/filters/filters.cpp
+++ b/src/filters/filters.cpp
@@ -22,12 +22,11 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-#include "SC_PlugIn.h"
#include "fir.hpp"
InterfaceTable *ft;
PluginLoad(flex_filters) {
ft = inTable;
- registerUnit(ft, "FIR", false);
+ registerUnit(ft, "FIR", false);
}
diff --git a/src/filters/fir.cpp b/src/filters/fir.cpp
index c4216e1..73f5a0c 100644
--- a/src/filters/fir.cpp
+++ b/src/filters/fir.cpp
@@ -25,7 +25,7 @@ along with this program. If not, see .
#include "fir.hpp"
extern InterfaceTable *ft;
-FIR::FIR() {
+FlexPlugins::FIR::FIR() {
m_z = static_cast(RTAlloc(mWorld, fullBufferSize() * sizeof(float)));
for (size_t i = 0; i < fullBufferSize(); i++) {
m_z[i] = 0.f;
@@ -34,26 +34,26 @@ FIR::FIR() {
next(1);
}
-FIR::~FIR() {
+FlexPlugins::FIR::~FIR() {
if (m_z) RTFree(mWorld, m_z);
}
-void FIR::next(int inNumSamples) {
+void FlexPlugins::FIR::next(int inNumSamples) {
size_t numCoefs = static_cast(mNumInputs - 1);
numCoefs = sc_clip(numCoefs, 0, static_cast(fullBufferSize()));
const float *inBuf = in(0);
float *outBuf = out(0);
- for (size_t xxi = 0; xxi < inNumSamples; xxi++) {
+ for (size_t i = 0; i < inNumSamples; i++) {
float convResult = 0.f;
// unit delay
- for (size_t xxj = fullBufferSize() - 1; xxj > 0; xxj--) {
- m_z[xxj] = m_z[xxj-1];
+ for (size_t j = fullBufferSize() - 1; j > 0; j--) {
+ m_z[j] = m_z[j-1];
}
- m_z[0] = inBuf[xxi];
+ m_z[0] = inBuf[i];
// convolve
- for (size_t xxk = 0; xxk < numCoefs; xxk++) {
- convResult += in0(1+xxk) * m_z[xxk];
+ for (size_t k = 0; k < numCoefs; k++) {
+ convResult += in0(1+k) * m_z[k];
}
- outBuf[xxi] = convResult;
+ outBuf[i] = convResult;
}
}
\ No newline at end of file
diff --git a/src/filters/fir.hpp b/src/filters/fir.hpp
index 17368b7..552caef 100644
--- a/src/filters/fir.hpp
+++ b/src/filters/fir.hpp
@@ -26,13 +26,15 @@ along with this program. If not, see .
#include "SC_PlugIn.hpp"
-class FIR : public SCUnit {
-public:
- FIR();
- ~FIR();
-
-private:
- void next(int inNumSamples);
- float *m_z;
- size_t m_delaySize;
-};
\ No newline at end of file
+namespace FlexPlugins {
+ class FIR : public SCUnit {
+ public:
+ FIR();
+ ~FIR();
+
+ private:
+ void next(int inNumSamples);
+ float *m_z;
+ size_t m_delaySize;
+ };
+}
\ No newline at end of file
diff --git a/src/generators/LoopPhasor.schelp b/src/generators/LoopPhasor.schelp
index b73e35e..053ae46 100644
--- a/src/generators/LoopPhasor.schelp
+++ b/src/generators/LoopPhasor.schelp
@@ -67,27 +67,29 @@ b = Buffer.read(s, p);
x = Bus.audio(s, 1);
SynthDef(\ptr, {
- var sig;
- sig = LoopPhasor.ar(\t_start.tr(0.0), \t_end.tr(0.0), \rate.kr(1.0) * BufRateScale.ir(b), 0.0, BufFrames.kr(b), \loopStart.ir(0), \loopEnd.ir(1));
- Out.ar(\out.kr(0), sig);
+ arg rate=1, loopStart=0, loopEnd=1, out=0, trigEnd=0.0;
+ var sig;
+ sig = LoopPhasor.ar(0.0, trigEnd, 1 * BufRateScale.ir(b), 0.0, BufFrames.ir(b), loopStart, loopEnd);
+ sig.poll;
+ Out.ar(out, sig);
}).add;
SynthDef(\player, {
- var sig, ptr_in;
- ptr_in = In.ar(\ptr.kr(0));
- sig = BufRd.ar(1, b, ptr_in, 0);
- Out.ar(0, sig);
+ arg ptr;
+ var sig, ptr_in;
+ ptr_in = In.ar(ptr);
+ sig = BufRd.ar(1, b, ptr_in, 0);
+ Out.ar(0, sig);
}).add;
+)
// we need two synths: a pointer synth and a player synth
-y = Synth(\ptr, [\out, x, \loopStart, 80e3, \loopEnd, 120e3]);
+y = Synth(\ptr, [\out, x, \loopStart, 8e4, \loopEnd, 9e4]);
z = Synth(\player, [\ptr, x], addAction: \addToTail);
// to stop looping and end naturally
-y.set(\t_end, 1.0);
+y.set(\trigEnd, 1.0);
-// free the synths
z.free;
y.free;
-)
::
\ No newline at end of file
diff --git a/src/generators/generators.cpp b/src/generators/generators.cpp
index 90cdf2a..c9b0435 100644
--- a/src/generators/generators.cpp
+++ b/src/generators/generators.cpp
@@ -22,7 +22,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-#include "SC_PlugIn.h"
+#include "SC_PlugIn.hpp"
#include "loopPhasor.hpp"
#include "impulseDropout.hpp"
#include "impulseJitter.hpp"
@@ -31,7 +31,7 @@ InterfaceTable *ft;
PluginLoad(flexplugin_generators) {
ft = inTable;
- DefineSimpleUnit(ImpulseDropout);
- DefineDtorUnit(ImpulseJitter);
- DefineSimpleUnit(LoopPhasor);
+ registerUnit(ft, "ImpulseDropout", false);
+ registerUnit(ft, "ImpulseJitter", false);
+ registerUnit(ft, "LoopPhasor", false);
}
diff --git a/src/generators/impulseDropout.cpp b/src/generators/impulseDropout.cpp
index 64d217d..7cd0a90 100644
--- a/src/generators/impulseDropout.cpp
+++ b/src/generators/impulseDropout.cpp
@@ -51,86 +51,147 @@ static inline float testWrapPhase(double prev_inc, double& phase) {
}
}
-void ImpulseDropout_next_aa(ImpulseDropout* unit, int inNumSamples) {
- float* out = OUT(0);
- float* freqIn = IN(0);
- float* offIn = IN(1);
- float dropProbIn = IN0(2);
+FlexPlugins::ImpulseDropout::ImpulseDropout() {
+ mPhaseIncrement = in0(0) * mFreqMul;
+ mPhaseOffset = in0(1);
+ mFreqMul = static_cast(mRate->mSampleDur);
+
+ double initOff = mPhaseOffset;
+ double initInc = mPhaseIncrement;
+ double initPhase = sc_wrap(initOff, 0.0, 1.0);
+
+ // Initial phase offset of 0 means output of 1 on first sample.
+ // Set phase to wrap point to trigger impulse on first sample
+ if (initPhase == 0.0 && initInc >= 0.0) {
+ initPhase = 1.0; // positive frequency trigger/wrap position
+ }
+ mPhase = initPhase;
+
+ UnitCalcFunc func;
+ switch (inRate(0)) {
+ case calc_FullRate:
+ switch (inRate(1)) {
+ case calc_ScalarRate:
+ set_calc_function();
+ next_ai(1);
+ break;
+ case calc_BufRate:
+ set_calc_function();
+ next_ak(1);
+ break;
+ case calc_FullRate:
+ set_calc_function();
+ next_aa(1);
+ break;
+ }
+ break;
+ case calc_BufRate:
+ case calc_ScalarRate:
+ if (inRate(1) == calc_ScalarRate) {
+ set_calc_function();
+ next_ki(1);
+ } else {
+ set_calc_function();
+ next_ki(1);
+ }
+ break;
+ }
+
+ mPhase = initPhase;
+ mPhaseOffset = initOff;
+ mPhaseIncrement = initInc;
+}
+
+void FlexPlugins::ImpulseDropout::next_aa(int inNumSamples) {
+ float* outBuf = out(0);
+ const float* freqIn = in(0);
+ const float* offIn = in(1);
+ float dropProbIn = in0(2);
// Collect UGen state
- double phase = unit->mPhase;
- double inc = unit->mPhaseIncrement;
- float freqMul = unit->mFreqMul;
- double prevOff = unit->mPhaseOffset;
+ double phase = mPhase;
+ double inc = mPhaseIncrement;
+ float freqMul = mFreqMul;
+ double prevOff = mPhaseOffset;
- RGET
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
+ RGen* rgen = mParent->mRGen;
+ uint32 s1 = rgen->s1; \
+ uint32 s2 = rgen->s2; \
+ uint32 s3 = rgen->s3;
+
+ for (int i = 0; i < inNumSamples; i++) {
float impulseResult = testWrapPhase(inc, phase);
// Drop the impulse if necessary
- if (impulseResult > 0.5f && rgen.frand() < dropProbIn) {
+ if (impulseResult > 0.5f && rgen->frand() < dropProbIn) {
impulseResult = 0.f;
}
- double off = static_cast(offIn[xxn]);
+ double off = static_cast(offIn[i]);
double offInc = off - prevOff;
phase += offInc;
testWrapPhase(inc, phase);
- inc = freqIn[xxn] * freqMul;
- out[xxn] = impulseResult;
+ inc = freqIn[i] * freqMul;
+ outBuf[i] = impulseResult;
phase += inc;
prevOff = off;
}
- unit->mPhase = phase;
- unit->mPhaseOffset = prevOff;
- unit->mPhaseIncrement = inc;
+ mPhase = phase;
+ mPhaseOffset = prevOff;
+ mPhaseIncrement = inc;
}
-void ImpulseDropout_next_ai(ImpulseDropout* unit, int inNumSamples) {
- float* out = OUT(0);
- float freqIn = IN0(0);
- float dropProbIn = IN0(2);
+void FlexPlugins::ImpulseDropout::next_ai(int inNumSamples) {
+ float* outBuf = out(0);
+ float freqIn = in0(0);
+ float dropProbIn = in0(2);
// Collect UGen state
- double phase = unit->mPhase;
- double inc = unit->mPhaseIncrement;
- float freqMul = unit->mFreqMul;
-
- RGET
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
+ double phase = mPhase;
+ double inc = mPhaseIncrement;
+ float freqMul = mFreqMul;
+
+ RGen* rgen = mParent->mRGen;
+ uint32 s1 = rgen->s1; \
+ uint32 s2 = rgen->s2; \
+ uint32 s3 = rgen->s3;
+ for (int i = 0; i < inNumSamples; i++) {
float impulseResult = testWrapPhase(inc, phase);
// Drop the impulse if necessary
- if (impulseResult > 0.5f && rgen.frand() < dropProbIn) {
+ if (impulseResult > 0.5f && rgen->frand() < dropProbIn) {
impulseResult = 0.f;
}
inc = freqIn * freqMul;
- out[xxn] = impulseResult;
+ outBuf[i] = impulseResult;
phase += inc;
}
- unit->mPhase = phase;
- unit->mPhaseIncrement = inc;
+ mPhase = phase;
+ mPhaseIncrement = inc;
}
-void ImpulseDropout_next_ak(ImpulseDropout* unit, int inNumSamples) {
- float* out = OUT(0);
- float freqIn = IN0(0);
- double off = IN0(1);
- float dropProbIn = IN0(2);
+void FlexPlugins::ImpulseDropout::next_ak(int inNumSamples) {
+ float* outBuf = out(0);
+ float freqIn = in0(0);
+ double off = in0(1);
+ float dropProbIn = in0(2);
// Collect UGen state
- double phase = unit->mPhase;
- double inc = unit->mPhaseIncrement;
- float freqMul = unit->mFreqMul;
- double prevOff = unit->mPhaseOffset;
+ double phase = mPhase;
+ double inc = mPhaseIncrement;
+ float freqMul = mFreqMul;
+ double prevOff = mPhaseOffset;
- double offSlope = CALCSLOPE(off, prevOff);
+ double offSlope = calcSlope(off, prevOff);
bool offChanged = offSlope != 0.f;
- RGET
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
+ RGen* rgen = mParent->mRGen;
+ uint32 s1 = rgen->s1; \
+ uint32 s2 = rgen->s2; \
+ uint32 s3 = rgen->s3;
+ for (int i = 0; i < inNumSamples; i++) {
float impulseResult = testWrapPhase(inc, phase);
// Drop the impulse if necessary
- if (impulseResult > 0.5f && rgen.frand() < dropProbIn) {
+ if (impulseResult > 0.5f && rgen->frand() < dropProbIn) {
impulseResult = 0.f;
}
if (offChanged) {
@@ -138,183 +199,80 @@ void ImpulseDropout_next_ak(ImpulseDropout* unit, int inNumSamples) {
testWrapPhase(inc, phase);
}
inc = freqIn * freqMul;
- out[xxn] = impulseResult;
+ outBuf[i] = impulseResult;
phase += inc;
}
- unit->mPhase = phase;
- unit->mPhaseOffset = off;
- unit->mPhaseIncrement = inc;
+ mPhase = phase;
+ mPhaseOffset = off;
+ mPhaseIncrement = inc;
}
-void ImpulseDropout_next_ki(ImpulseDropout* unit, int inNumSamples) {
- float* out = OUT(0);
- double inc = IN0(0) * unit->mFreqMul;
- float dropProbIn = IN0(2);
+void FlexPlugins::ImpulseDropout::next_ki(int inNumSamples) {
+ float* outBuf = out(0);
+ double inc = in0(0) * mFreqMul;
+ float dropProbIn = in0(2);
// Collect UGen state
- double phase = unit->mPhase;
- double prevInc = unit->mPhaseIncrement;
+ double phase = mPhase;
+ double prevInc = mPhaseIncrement;
- double incSlope = CALCSLOPE(inc, prevInc);
+ double incSlope = calcSlope(inc, prevInc);
- RGET
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
+ RGen* rgen = mParent->mRGen;
+ uint32 s1 = rgen->s1; \
+ uint32 s2 = rgen->s2; \
+ uint32 s3 = rgen->s3;
+ for (int i = 0; i < inNumSamples; i++) {
float impulseResult = testWrapPhase(prevInc, phase);
// Drop the impulse if necessary
- if (impulseResult > 0.5f && rgen.frand() < dropProbIn) {
+ if (impulseResult > 0.5f && rgen->frand() < dropProbIn) {
impulseResult = 0.f;
}
- out[xxn] = impulseResult;
+ outBuf[i] = impulseResult;
prevInc += incSlope;
phase += prevInc;
}
- unit->mPhase = phase;
- unit->mPhaseIncrement = inc;
+ mPhase = phase;
+ mPhaseIncrement = inc;
}
-void ImpulseDropout_next_kk(ImpulseDropout* unit, int inNumSamples) {
- float* out = OUT(0);
- double inc = IN0(0) * unit->mFreqMul;
- double off = IN0(1);
- float dropProbIn = IN0(2);
+void FlexPlugins::ImpulseDropout::next_kk(int inNumSamples) {
+ float* outBuf = out(0);
+ double inc = in0(0) * mFreqMul;
+ double off = in0(1);
+ float dropProbIn = in0(2);
// Collect UGen state
- double phase = unit->mPhase;
- double prevInc = unit->mPhaseIncrement;
- double prevOff = unit->mPhaseOffset;
+ double phase = mPhase;
+ double prevInc = mPhaseIncrement;
+ double prevOff = mPhaseOffset;
- double incSlope = CALCSLOPE(inc, prevInc);
- double phaseSlope = CALCSLOPE(off, prevOff);
+ double incSlope = calcSlope(inc, prevInc);
+ double phaseSlope = calcSlope(off, prevOff);
bool phOffChanged = phaseSlope != 0.f;
- RGET
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
+ RGen* rgen = mParent->mRGen;
+ uint32 s1 = rgen->s1; \
+ uint32 s2 = rgen->s2; \
+ uint32 s3 = rgen->s3;
+ for (int i = 0; i < inNumSamples; i++) {
float impulseResult = testWrapPhase(prevInc, phase);
// Drop the impulse if necessary
- if (impulseResult > 0.5f && rgen.frand() < dropProbIn) {
+ if (impulseResult > 0.5f && rgen->frand() < dropProbIn) {
impulseResult = 0.f;
}
if (phOffChanged) {
phase += phaseSlope;
testWrapPhase(prevInc, phase);
}
- out[xxn] = impulseResult;
+ outBuf[i] = impulseResult;
prevInc += incSlope;
phase += prevInc;
}
- unit->mPhase = phase;
- unit->mPhaseOffset = off;
- unit->mPhaseIncrement = inc;
-}
-
-void ImpulseDropout_next_ii(ImpulseDropout* unit, int inNumSamples) {
- float* out = OUT(0);
- float dropProbIn = IN0(2);
-
- // Collect UGen state
- double inc = unit->mPhaseIncrement;
- double phase = unit->mPhase;
-
- RGET
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
- float impulseResult = testWrapPhase(inc, phase);
- // Drop the impulse if necessary
- if (impulseResult > 0.5f && rgen.frand() < dropProbIn) {
- impulseResult = 0.f;
- }
- out[xxn] = impulseResult;
- phase += inc;
- }
-
- unit->mPhase = phase;
+ mPhase = phase;
+ mPhaseOffset = off;
+ mPhaseIncrement = inc;
}
-
-void ImpulseDropout_next_ik(ImpulseDropout* unit, int inNumSamples) {
- float* out = OUT(0);
- double off = IN0(1);
- float dropProbIn = IN0(2);
-
- // Collect UGen state
- double phase = unit->mPhase;
- double inc = unit->mPhaseIncrement;
- double prevOff = unit->mPhaseOffset;
-
- double phaseSlope = CALCSLOPE(off, prevOff);
- bool phOffChanged = phaseSlope != 0.f;
-
- RGET
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
- float impulseResult = testWrapPhase(inc, phase);
- // Drop the impulse if necessary
- if (impulseResult > 0.5f && rgen.frand() < dropProbIn) {
- impulseResult = 0.f;
- }
- if (phOffChanged) {
- phase += phaseSlope;
- testWrapPhase(inc, phase);
- }
- out[xxn] = impulseResult;
- phase += inc;
- }
-
- unit->mPhase = phase;
- unit->mPhaseOffset = off;
-}
-
-// Construct the ImpulseDropout
-void ImpulseDropout_Ctor(ImpulseDropout* unit) {
- unit->mPhaseIncrement = IN0(0) * unit->mFreqMul;
- unit->mPhaseOffset = IN0(1);
- unit->mFreqMul = static_cast(unit->mRate->mSampleDur);
-
- double initOff = unit->mPhaseOffset;
- double initInc = unit->mPhaseIncrement;
- double initPhase = sc_wrap(initOff, 0.0, 1.0);
-
- // Initial phase offset of 0 means output of 1 on first sample.
- // Set phase to wrap point to trigger impulse on first sample
- if (initPhase == 0.0 && initInc >= 0.0) {
- initPhase = 1.0; // positive frequency trigger/wrap position
- }
- unit->mPhase = initPhase;
-
- UnitCalcFunc func;
- switch (INRATE(0)) {
- case calc_FullRate:
- switch (INRATE(1)) {
- case calc_ScalarRate:
- func = (UnitCalcFunc)ImpulseDropout_next_ai;
- break;
- case calc_BufRate:
- func = (UnitCalcFunc)ImpulseDropout_next_ak;
- break;
- case calc_FullRate:
- func = (UnitCalcFunc)ImpulseDropout_next_aa;
- break;
- }
- break;
- case calc_BufRate:
- if (INRATE(1) == calc_ScalarRate) {
- func = (UnitCalcFunc)ImpulseDropout_next_ki;
- } else {
- func = (UnitCalcFunc)ImpulseDropout_next_kk;
- }
- break;
- case calc_ScalarRate:
- if (INRATE(1) == calc_ScalarRate) {
- func = (UnitCalcFunc)ImpulseDropout_next_ki;
- } else {
- func = (UnitCalcFunc)ImpulseDropout_next_kk;
- }
- break;
- }
- unit->mCalcFunc = func;
- func(unit, 1);
-
- unit->mPhase = initPhase;
- unit->mPhaseOffset = initOff;
- unit->mPhaseIncrement = initInc;
-}
\ No newline at end of file
diff --git a/src/generators/impulseDropout.hpp b/src/generators/impulseDropout.hpp
index eb79286..4098c9a 100644
--- a/src/generators/impulseDropout.hpp
+++ b/src/generators/impulseDropout.hpp
@@ -23,18 +23,20 @@ along with this program. If not, see .
*/
#pragma once
-#include "SC_PlugIn.h"
-#define HEAP_MAX_SIZE 1024
-
-// Represents an ImpulseDropout UGen.
-struct ImpulseDropout : public Unit {
- double mPhase, mPhaseOffset, mPhaseIncrement;
- float mFreqMul;
-};
-
-void ImpulseDropout_Ctor(ImpulseDropout* unit);
-void ImpulseDropout_next_aa(ImpulseDropout* unit, int inNumSamples);
-void ImpulseDropout_next_ai(ImpulseDropout* unit, int inNumSamples);
-void ImpulseDropout_next_ak(ImpulseDropout* unit, int inNumSamples);
-void ImpulseDropout_next_ki(ImpulseDropout* unit, int inNumSamples);
-void ImpulseDropout_next_kk(ImpulseDropout* unit, int inNumSamples);
+#include "SC_PlugIn.hpp"
+
+namespace FlexPlugins {
+ // Represents an ImpulseDropout UGen.
+ class ImpulseDropout : public SCUnit {
+ public:
+ ImpulseDropout();
+ private:
+ void next_aa(int inNumSamples);
+ void next_ai(int inNumSamples);
+ void next_ak(int inNumSamples);
+ void next_ki(int inNumSamples);
+ void next_kk(int inNumSamples);
+ double mPhase, mPhaseOffset, mPhaseIncrement;
+ float mFreqMul;
+ };
+}
\ No newline at end of file
diff --git a/src/generators/impulseJitter.cpp b/src/generators/impulseJitter.cpp
index 95ebfc0..ed4a6c0 100644
--- a/src/generators/impulseJitter.cpp
+++ b/src/generators/impulseJitter.cpp
@@ -23,6 +23,7 @@ along with this program. If not, see .
*/
#include "impulseJitter.hpp"
+#include "SC_Rate.h"
extern InterfaceTable *ft;
// This is a copy of the static function from LFUGens.cpp in server/plugins.
@@ -52,153 +53,224 @@ static inline float testWrapPhase(double prev_inc, double& phase) {
}
-void ImpulseJitter_next_aa(ImpulseJitter* unit, int inNumSamples) {
- float* out = OUT(0);
- float* freq = IN(0);
- float* offIn = IN(1);
- float jitterFracIn = IN0(2);
+// Construct the ImpulseJitter
+FlexPlugins::ImpulseJitter::ImpulseJitter() {
+ mPhaseIncrement = in0(0) * mFreqMul;
+ mPhaseOffset = in0(1);
+ mFreqMul = static_cast(mRate->mSampleDur);
+ mImpulseHeap.maxSize = HEAP_MAX_SIZE; // hard coded for now
+ mImpulseHeap.size = 1;
+ mImpulseHeap.heap = (int*)RTAlloc(mWorld, HEAP_MAX_SIZE * sizeof(int));
+
+ double initOff = mPhaseOffset;
+ double initInc = mPhaseIncrement;
+ double initPhase = sc_wrap(initOff, 0.0, 1.0);
+
+ // Initial phase offset of 0 means output of 1 on first sample.
+ // Set phase to wrap point to trigger impulse on first sample
+ if (initPhase == 0.0 && initInc >= 0.0) {
+ initPhase = 1.0; // positive frequency trigger/wrap position
+ }
+ mPhase = initPhase;
+
+ UnitCalcFunc func;
+ switch (inRate(0)) {
+ case calc_FullRate:
+ switch (inRate(1)) {
+ case calc_ScalarRate:
+ set_calc_function();
+ next_ai(1);
+ break;
+ case calc_BufRate:
+ set_calc_function();
+ next_ak(1);
+ break;
+ case calc_FullRate:
+ set_calc_function();
+ next_aa(1);
+ break;
+ }
+ break;
+ case calc_ScalarRate:
+ case calc_BufRate:
+ if (inRate(1) == calc_ScalarRate) {
+ set_calc_function();
+ next_ki(1);
+ } else {
+ set_calc_function();
+ next_kk(1);
+ }
+ break;
+ }
+
+ mPhase = initPhase;
+ mPhaseOffset = initOff;
+ mPhaseIncrement = initInc;
+}
+
+FlexPlugins::ImpulseJitter::~ImpulseJitter() {
+ RTFree(mWorld, mImpulseHeap.heap);
+}
+
+void FlexPlugins::ImpulseJitter::next_aa(int inNumSamples) {
+ float* outBuf = out(0);
+ const float* freq = in(0);
+ const float* offIn = in(1);
+ float jitterFracIn = in0(2);
// Collect UGen state
- double phase = unit->mPhase;
- double inc = unit->mPhaseIncrement;
- float freqMul = unit->mFreqMul;
- double prevOff = unit->mPhaseOffset;
+ double phase = mPhase;
+ double inc = mPhaseIncrement;
+ float freqMul = mFreqMul;
+ double prevOff = mPhaseOffset;
// The maximum distance an impulse can be displaced
- int jitterWidth = static_cast(jitterFracIn * unit->mImpulseHeap.maxSize);
+ int jitterWidth = static_cast(jitterFracIn * mImpulseHeap.maxSize);
// Zero out the output buffer
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
- out[xxn] = 0.f;
+ for (int i = 0; i < inNumSamples; i++) {
+ outBuf[i] = 0.f;
}
// Update the impulse table indices
- for (int xxn = 1; xxn < unit->mImpulseHeap.size; xxn++) {
- unit->mImpulseHeap.heap[xxn] -= inNumSamples;
+ for (int i = 1; i < mImpulseHeap.size; i++) {
+ mImpulseHeap.heap[i] -= inNumSamples;
}
// Retrieve impulses for this block
- while (heapPeek(&unit->mImpulseHeap) < inNumSamples && unit->mImpulseHeap.size > 1) {
- out[heapPop(&unit->mImpulseHeap)] = 1.f;
+ while (heapPeek(&mImpulseHeap) < inNumSamples && mImpulseHeap.size > 1) {
+ outBuf[heapPop(&mImpulseHeap)] = 1.f;
}
- RGET
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
- size_t heapEffectiveSize = static_cast(HEAP_MAX_SIZE / (12 * sc_log2(freq[xxn])));
+ RGen* rgen = mParent->mRGen;
+ uint32 s1 = rgen->s1; \
+ uint32 s2 = rgen->s2; \
+ uint32 s3 = rgen->s3;
+
+ for (int i = 0; i < inNumSamples; i++) {
+ size_t heapEffectiveSize = static_cast(HEAP_MAX_SIZE / (12 * sc_log2(freq[i])));
float impulseResult = testWrapPhase(inc, phase);
if (impulseResult > 0.5f) {
- int idx = rgen.irand(jitterWidth) + xxn;
+ int idx = rgen->irand(jitterWidth) + i;
if (idx < inNumSamples) {
- out[idx] = 1.f;
- } else if (unit->mImpulseHeap.size < heapEffectiveSize) {
- heapInsert(&unit->mImpulseHeap, idx);
+ outBuf[idx] = 1.f;
+ } else if (mImpulseHeap.size < heapEffectiveSize) {
+ heapInsert(&mImpulseHeap, idx);
}
}
- double off = static_cast(offIn[xxn]);
+ double off = static_cast(offIn[i]);
double offInc = off - prevOff;
phase += offInc;
testWrapPhase(inc, phase);
- inc = freq[xxn] * freqMul;
+ inc = freq[i] * freqMul;
phase += inc;
prevOff = off;
}
- unit->mPhase = phase;
- unit->mPhaseOffset = prevOff;
- unit->mPhaseIncrement = inc;
+ mPhase = phase;
+ mPhaseOffset = prevOff;
+ mPhaseIncrement = inc;
}
-void ImpulseJitter_next_ai(ImpulseJitter* unit, int inNumSamples) {
- float* out = OUT(0);
- float freq = IN0(0);
- float jitterFracIn = IN0(2);
+void FlexPlugins::ImpulseJitter::next_ai(int inNumSamples) {
+ float* outBuf = out(0);
+ float freq = in0(0);
+ float jitterFracIn = in0(2);
size_t heapEffectiveSize = static_cast(HEAP_MAX_SIZE / (12 * sc_log2(freq)));
// Collect UGen state
- double phase = unit->mPhase;
- double inc = unit->mPhaseIncrement;
- float freqMul = unit->mFreqMul;
+ double phase = mPhase;
+ double inc = mPhaseIncrement;
+ float freqMul = mFreqMul;
// The maximum distance an impulse can be displaced
- int jitterWidth = static_cast(jitterFracIn * unit->mImpulseHeap.maxSize);
+ int jitterWidth = static_cast(jitterFracIn * mImpulseHeap.maxSize);
// Zero out the output buffer
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
- out[xxn] = 0.f;
+ for (int i = 0; i < inNumSamples; i++) {
+ outBuf[i] = 0.f;
}
// Update the impulse table indices
- for (int xxn = 1; xxn < unit->mImpulseHeap.size; xxn++) {
- unit->mImpulseHeap.heap[xxn] -= inNumSamples;
+ for (int i = 1; i < mImpulseHeap.size; i++) {
+ mImpulseHeap.heap[i] -= inNumSamples;
}
// Retrieve impulses for this block
- while (heapPeek(&unit->mImpulseHeap) < inNumSamples && unit->mImpulseHeap.size > 1) {
- out[heapPop(&unit->mImpulseHeap)] = 1.f;
+ while (heapPeek(&mImpulseHeap) < inNumSamples && mImpulseHeap.size > 1) {
+ outBuf[heapPop(&mImpulseHeap)] = 1.f;
}
- RGET
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
+ RGen* rgen = mParent->mRGen;
+ uint32 s1 = rgen->s1; \
+ uint32 s2 = rgen->s2; \
+ uint32 s3 = rgen->s3;
+
+ for (int i = 0; i < inNumSamples; i++) {
float impulseResult = testWrapPhase(inc, phase);
if (impulseResult > 0.5f) {
- int idx = rgen.irand(jitterWidth) + xxn;
+ int idx = rgen->irand(jitterWidth) + i;
if (idx < inNumSamples) {
- out[idx] = 1.f;
- } else if (unit->mImpulseHeap.size < heapEffectiveSize) {
- heapInsert(&unit->mImpulseHeap, idx);
+ outBuf[idx] = 1.f;
+ } else if (mImpulseHeap.size < heapEffectiveSize) {
+ heapInsert(&mImpulseHeap, idx);
}
}
inc = freq * freqMul;
phase += inc;
}
- unit->mPhase = phase;
- unit->mPhaseIncrement = inc;
+ mPhase = phase;
+ mPhaseIncrement = inc;
}
-void ImpulseJitter_next_ak(ImpulseJitter* unit, int inNumSamples) {
- float* out = OUT(0);
- float freq = IN0(0);
- double off = IN0(1);
- float jitterFracIn = IN0(2);
+void FlexPlugins::ImpulseJitter::next_ak(int inNumSamples) {
+ float* outBuf = out(0);
+ float freq = in0(0);
+ double off = in0(1);
+ float jitterFracIn = in0(2);
size_t heapEffectiveSize = static_cast(HEAP_MAX_SIZE / (12 * sc_log2(freq)));
// Collect UGen state
- double phase = unit->mPhase;
- double inc = unit->mPhaseIncrement;
- float freqMul = unit->mFreqMul;
- double prevOff = unit->mPhaseOffset;
+ double phase = mPhase;
+ double inc = mPhaseIncrement;
+ float freqMul = mFreqMul;
+ double prevOff = mPhaseOffset;
- double offSlope = CALCSLOPE(off, prevOff);
+ double offSlope = calcSlope(off, prevOff);
bool offChanged = offSlope != 0.f;
// The maximum distance an impulse can be displaced
- int jitterWidth = static_cast(jitterFracIn * unit->mImpulseHeap.maxSize);
+ int jitterWidth = static_cast(jitterFracIn * mImpulseHeap.maxSize);
// Zero out the output buffer
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
- out[xxn] = 0.f;
+ for (int i = 0; i < inNumSamples; i++) {
+ outBuf[i] = 0.f;
}
// Update the impulse table indices
- for (int xxn = 1; xxn < unit->mImpulseHeap.size; xxn++) {
- unit->mImpulseHeap.heap[xxn] -= inNumSamples;
+ for (int i = 1; i < mImpulseHeap.size; i++) {
+ mImpulseHeap.heap[i] -= inNumSamples;
}
// Retrieve impulses for this block
- while (heapPeek(&unit->mImpulseHeap) < inNumSamples && unit->mImpulseHeap.size > 1) {
- out[heapPop(&unit->mImpulseHeap)] = 1.f;
+ while (heapPeek(&mImpulseHeap) < inNumSamples && mImpulseHeap.size > 1) {
+ outBuf[heapPop(&mImpulseHeap)] = 1.f;
}
- RGET
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
+ RGen* rgen = mParent->mRGen;
+ uint32 s1 = rgen->s1; \
+ uint32 s2 = rgen->s2; \
+ uint32 s3 = rgen->s3;
+
+ for (int i = 0; i < inNumSamples; i++) {
float impulseResult = testWrapPhase(inc, phase);
if (impulseResult > 0.5f) {
- int idx = rgen.irand(jitterWidth) + xxn;
+ int idx = rgen->irand(jitterWidth) + i;
if (idx < inNumSamples) {
- out[idx] = 1.f;
- } else if (unit->mImpulseHeap.size < heapEffectiveSize) {
- heapInsert(&unit->mImpulseHeap, idx);
+ outBuf[idx] = 1.f;
+ } else if (mImpulseHeap.size < heapEffectiveSize) {
+ heapInsert(&mImpulseHeap, idx);
}
}
if (offChanged) {
@@ -209,105 +281,113 @@ void ImpulseJitter_next_ak(ImpulseJitter* unit, int inNumSamples) {
phase += inc;
}
- unit->mPhase = phase;
- unit->mPhaseOffset = off;
- unit->mPhaseIncrement = inc;
+ mPhase = phase;
+ mPhaseOffset = off;
+ mPhaseIncrement = inc;
}
-void ImpulseJitter_next_ki(ImpulseJitter* unit, int inNumSamples) {
- float* out = OUT(0);
- double freq = IN0(0);
- double inc = freq * unit->mFreqMul;
- float jitterFracIn = IN0(2);
+void FlexPlugins::ImpulseJitter::next_ki(int inNumSamples) {
+ float* outBuf = out(0);
+ double freq = in0(0);
+ double inc = freq * mFreqMul;
+ float jitterFracIn = in0(2);
size_t heapEffectiveSize = static_cast(HEAP_MAX_SIZE / (12 * sc_log2(freq)));
// Collect UGen state
- double phase = unit->mPhase;
- double prevInc = unit->mPhaseIncrement;
+ double phase = mPhase;
+ double prevInc = mPhaseIncrement;
- double incSlope = CALCSLOPE(inc, prevInc);
+ double incSlope = calcSlope(inc, prevInc);
// The maximum distance an impulse can be displaced
- int jitterWidth = static_cast(jitterFracIn * unit->mImpulseHeap.maxSize);
+ int jitterWidth = static_cast(jitterFracIn * mImpulseHeap.maxSize);
// Zero out the output buffer
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
- out[xxn] = 0.f;
+ for (int i = 0; i < inNumSamples; i++) {
+ outBuf[i] = 0.f;
}
// Update the impulse table indices
- for (int xxn = 1; xxn < unit->mImpulseHeap.size; xxn++) {
- unit->mImpulseHeap.heap[xxn] -= inNumSamples;
+ for (int i = 1; i < mImpulseHeap.size; i++) {
+ mImpulseHeap.heap[i] -= inNumSamples;
}
// Retrieve impulses for this block
- while (heapPeek(&unit->mImpulseHeap) < inNumSamples && unit->mImpulseHeap.size > 1) {
- out[heapPop(&unit->mImpulseHeap)] = 1.f;
+ while (heapPeek(&mImpulseHeap) < inNumSamples && mImpulseHeap.size > 1) {
+ outBuf[heapPop(&mImpulseHeap)] = 1.f;
}
- RGET
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
+ RGen* rgen = mParent->mRGen;
+ uint32 s1 = rgen->s1; \
+ uint32 s2 = rgen->s2; \
+ uint32 s3 = rgen->s3;
+
+ for (int i = 0; i < inNumSamples; i++) {
float impulseResult = testWrapPhase(prevInc, phase);
if (impulseResult > 0.5f) {
- int idx = rgen.irand(jitterWidth) + xxn;
+ int idx = rgen->irand(jitterWidth) + i;
if (idx < inNumSamples) {
- out[idx] = 1.f;
- } else if (unit->mImpulseHeap.size < heapEffectiveSize) {
- heapInsert(&unit->mImpulseHeap, idx);
+ outBuf[idx] = 1.f;
+ } else if (mImpulseHeap.size < heapEffectiveSize) {
+ heapInsert(&mImpulseHeap, idx);
}
}
prevInc += incSlope;
phase += prevInc;
}
- unit->mPhase = phase;
- unit->mPhaseIncrement = inc;
+ mPhase = phase;
+ mPhaseIncrement = inc;
}
-void ImpulseJitter_next_kk(ImpulseJitter* unit, int inNumSamples) {
- float* out = OUT(0);
- double freq = IN0(0);
- double inc = freq * unit->mFreqMul;
- double off = IN0(1);
- float jitterFracIn = IN0(2);
+void FlexPlugins::ImpulseJitter::next_kk(int inNumSamples) {
+ float* outBuf = out(0);
+ double freq = in0(0);
+ double inc = freq * mFreqMul;
+ double off = in0(1);
+ float jitterFracIn = in0(2);
size_t heapEffectiveSize = static_cast(HEAP_MAX_SIZE / (12 * sc_log2(freq)));
// Collect UGen state
- double phase = unit->mPhase;
- double prevInc = unit->mPhaseIncrement;
- double prevOff = unit->mPhaseOffset;
+ double phase = mPhase;
+ double prevInc = mPhaseIncrement;
+ double prevOff = mPhaseOffset;
- double incSlope = CALCSLOPE(inc, prevInc);
- double phaseSlope = CALCSLOPE(off, prevOff);
+ double incSlope = calcSlope(inc, prevInc);
+ double phaseSlope = calcSlope(off, prevOff);
bool phOffChanged = phaseSlope != 0.f;
// The maximum distance an impulse can be displaced
- int jitterWidth = static_cast(jitterFracIn * unit->mImpulseHeap.maxSize);
+ int jitterWidth = static_cast(jitterFracIn * mImpulseHeap.maxSize);
// Zero out the output buffer
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
- out[xxn] = 0.f;
+ for (int i = 0; i < inNumSamples; i++) {
+ outBuf[i] = 0.f;
}
// Update the impulse table indices
- for (int xxn = 1; xxn < unit->mImpulseHeap.size; xxn++) {
- unit->mImpulseHeap.heap[xxn] -= inNumSamples;
+ for (int i = 1; i < mImpulseHeap.size; i++) {
+ mImpulseHeap.heap[i] -= inNumSamples;
}
// Retrieve impulses for this block
- while (heapPeek(&unit->mImpulseHeap) < inNumSamples && unit->mImpulseHeap.size > 1) {
- out[heapPop(&unit->mImpulseHeap)] = 1.f;
+ while (heapPeek(&mImpulseHeap) < inNumSamples && mImpulseHeap.size > 1) {
+ outBuf[heapPop(&mImpulseHeap)] = 1.f;
}
- RGET
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
+ RGen* rgen = mParent->mRGen;
+ uint32 s1 = rgen->s1; \
+ uint32 s2 = rgen->s2; \
+ uint32 s3 = rgen->s3;
+
+ for (int i = 0; i < inNumSamples; i++) {
float impulseResult = testWrapPhase(prevInc, phase);
if (impulseResult > 0.5f) {
- int idx = rgen.irand(jitterWidth) + xxn;
+ int idx = rgen->irand(jitterWidth) + i;
if (idx < inNumSamples) {
- out[idx] = 1.f;
- } else if (unit->mImpulseHeap.size < heapEffectiveSize) {
- heapInsert(&unit->mImpulseHeap, idx);
+ outBuf[idx] = 1.f;
+ } else if (mImpulseHeap.size < heapEffectiveSize) {
+ heapInsert(&mImpulseHeap, idx);
}
}
if (phOffChanged) {
@@ -318,76 +398,7 @@ void ImpulseJitter_next_kk(ImpulseJitter* unit, int inNumSamples) {
phase += prevInc;
}
- unit->mPhase = phase;
- unit->mPhaseOffset = off;
- unit->mPhaseIncrement = inc;
+ mPhase = phase;
+ mPhaseOffset = off;
+ mPhaseIncrement = inc;
}
-
-// Construct the ImpulseJitter
-void ImpulseJitter_Ctor(ImpulseJitter* unit) {
- unit->mPhaseIncrement = IN0(0) * unit->mFreqMul;
- unit->mPhaseOffset = IN0(1);
- unit->mFreqMul = static_cast(unit->mRate->mSampleDur);
- unit->mImpulseHeap.maxSize = HEAP_MAX_SIZE; // hard coded for now
- unit->mImpulseHeap.size = 1;
- unit->mImpulseHeap.heap = (int*)RTAlloc(unit->mWorld, HEAP_MAX_SIZE * sizeof(int));
-
- double initOff = unit->mPhaseOffset;
- double initInc = unit->mPhaseIncrement;
- double initPhase = sc_wrap(initOff, 0.0, 1.0);
-
- // Initial phase offset of 0 means output of 1 on first sample.
- // Set phase to wrap point to trigger impulse on first sample
- if (initPhase == 0.0 && initInc >= 0.0) {
- initPhase = 1.0; // positive frequency trigger/wrap position
- }
- unit->mPhase = initPhase;
-
- UnitCalcFunc func;
- switch (INRATE(0)) {
- case calc_FullRate:
- switch (INRATE(1)) {
- case calc_ScalarRate:
- func = (UnitCalcFunc)ImpulseJitter_next_ai;
- //printf("Calc function set to ai\n");
- break;
- case calc_BufRate:
- func = (UnitCalcFunc)ImpulseJitter_next_ak;
- //printf("Calc function set to ak\n");
- break;
- case calc_FullRate:
- func = (UnitCalcFunc)ImpulseJitter_next_aa;
- //printf("Calc function set to aa\n");
- break;
- }
- break;
- case calc_BufRate:
- if (INRATE(1) == calc_ScalarRate) {
- func = (UnitCalcFunc)ImpulseJitter_next_ki;
- //printf("Calc function set to ki\n");
- } else {
- func = (UnitCalcFunc)ImpulseJitter_next_kk;
- //printf("Calc function set to kk\n");
- }
- break;
- case calc_ScalarRate:
- if (INRATE(1) == calc_ScalarRate) {
- func = (UnitCalcFunc)ImpulseJitter_next_ki;
- //printf("Calc function set to ki\n");
- } else {
- func = (UnitCalcFunc)ImpulseJitter_next_kk;
- //printf("Calc function set to kk\n");
- }
- break;
- }
- unit->mCalcFunc = func;
- func(unit, 1);
-
- unit->mPhase = initPhase;
- unit->mPhaseOffset = initOff;
- unit->mPhaseIncrement = initInc;
-}
-
-void ImpulseJitter_Dtor(ImpulseJitter* unit) {
- RTFree(unit->mWorld, unit->mImpulseHeap.heap);
-}
\ No newline at end of file
diff --git a/src/generators/impulseJitter.hpp b/src/generators/impulseJitter.hpp
index d1deaf6..e876710 100644
--- a/src/generators/impulseJitter.hpp
+++ b/src/generators/impulseJitter.hpp
@@ -23,21 +23,25 @@ along with this program. If not, see .
*/
#pragma once
-#include "SC_PlugIn.h"
+#include "SC_PlugIn.hpp"
#include "arrayheap.hpp"
#define HEAP_MAX_SIZE 1024
-// Represents an ImpulseJitter UGen.
-struct ImpulseJitter : public Unit {
- double mPhase, mPhaseOffset, mPhaseIncrement;
- float mFreqMul;
- IntMinHeap mImpulseHeap;
-};
-
-void ImpulseJitter_Ctor(ImpulseJitter* unit);
-void ImpulseJitter_Dtor(ImpulseJitter* unit);
-void ImpulseJitter_next_aa(ImpulseJitter* unit, int inNumSamples);
-void ImpulseJitter_next_ai(ImpulseJitter* unit, int inNumSamples);
-void ImpulseJitter_next_ak(ImpulseJitter* unit, int inNumSamples);
-void ImpulseJitter_next_ki(ImpulseJitter* unit, int inNumSamples);
-void ImpulseJitter_next_kk(ImpulseJitter* unit, int inNumSamples);
+
+namespace FlexPlugins {
+ // Represents an ImpulseJitter UGen.
+ class ImpulseJitter : public SCUnit {
+ public:
+ ImpulseJitter();
+ ~ImpulseJitter();
+ private:
+ void next_aa(int inNumSamples);
+ void next_ai(int inNumSamples);
+ void next_ak(int inNumSamples);
+ void next_ki(int inNumSamples);
+ void next_kk(int inNumSamples);
+ double mPhase, mPhaseOffset, mPhaseIncrement;
+ float mFreqMul;
+ IntMinHeap mImpulseHeap;
+ };
+}
diff --git a/src/generators/loopPhasor.cpp b/src/generators/loopPhasor.cpp
index d00107c..166fc4c 100644
--- a/src/generators/loopPhasor.cpp
+++ b/src/generators/loopPhasor.cpp
@@ -23,210 +23,174 @@ along with this program. If not, see .
*/
#include "loopPhasor.hpp"
+#include "SC_Rate.h"
extern InterfaceTable *ft;
// Construct the LoopPhasor
-void LoopPhasor_Ctor(LoopPhasor* unit) {
+FlexPlugins::LoopPhasor::LoopPhasor() {
// Set the calculation function
- if (unit->mCalcRate == calc_FullRate) {
- if (INRATE(0) == calc_FullRate) {
- if (INRATE(1) == calc_FullRate) {
- SETCALC(LoopPhasor_next_aa);
- } else {
- SETCALC(LoopPhasor_next_ak);
- }
+ if (inRate(2) == calc_FullRate) {
+ if (inRate(0) == calc_FullRate) {
+ set_calc_function();
+ Print("Set aa\n");
+ next_aa(1);
} else {
- SETCALC(LoopPhasor_next_kk);
+ Print("Set ak\n");
+ set_calc_function();
+ next_ak(1);
}
} else {
- SETCALC(LoopPhasor_next_ak);
+ Print("Set kk\n");
+ set_calc_function();
+ next_k(1);
}
// Initialize the triggers
- unit->m_prevTriggerStart = IN0(0);
- unit->m_prevTriggerFinish = IN0(1);
- unit->m_triggerFinishState = false;
+ m_prevTriggerStart = in0(0);
+ m_prevTriggerFinish = in0(1);
+ m_loopState = false;
// Initialize the output
- unit->m_level = IN0(3);
- ZOUT0(0) = static_cast(unit->m_level);
+ m_level = in0(3);
}
-// Calculates samples for a LoopPhasor.kr UGen
-void LoopPhasor_next_kk(LoopPhasor* unit, int inNumSamples) {
+// all parameters are control rate
+void FlexPlugins::LoopPhasor::next_k(int inNumSamples) {
// Pointer to output array
- float* out = OUT(0);
+ float* outBuf = out(0);
// Get new parameters of the LoopPhasor
- float triggerReturnToStart = IN0(0);
- float triggerFinish = IN0(1);
- double rate = IN0(2);
- double startPosition = IN0(3);
- double endPosition = IN0(4);
- double loopStart = IN0(5);
- double loopEnd = IN0(6);
-
- // Get current state of the LoopPhasor
- float previousTriggerReturnToStart = unit->m_prevTriggerStart; // trigger return to start
- float previousTriggerFinish = unit->m_prevTriggerFinish; // trigger finish
- double level = unit->m_level;
+ const float triggerReturnToStart = in0(0);
+ const float triggerFinish = in0(1);
+ const float rate = in0(2);
+ const float startPosition = in0(3);
+ const float endPosition = in0(4);
+ const float loopStart = in0(5);
+ const float loopEnd = in0(6);
// Handle trigger return to start
- if (previousTriggerReturnToStart <= 0.f && triggerReturnToStart > 0.f) {
- level = startPosition;
+ if (m_prevTriggerStart <= 0.f && triggerReturnToStart > 0.f) {
+ m_level = startPosition;
}
- // Handle trigger finish. This just flips the finish trigger.
- if (previousTriggerFinish <= 0.f && triggerFinish > 0.f) {
- unit->m_triggerFinishState = !(unit->m_triggerFinishState);
+ // Handle trigger finish. This just flips the loop state.
+ if (m_prevTriggerFinish <= 0.f && triggerFinish > 0.f) {
+ m_triggerFinishState = !m_triggerFinishState;
}
// Compute output block
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
- // If we haven't triggered completion
- if (!unit->m_triggerFinishState) {
- // If we're inside the looping part of the LoopPhasor
- if (level >= loopStart && level <= loopEnd) {
- level = sc_wrap(level, loopStart, loopEnd);
- } else {
- level = sc_wrap(level, startPosition, endPosition);
+ for (int i = 0; i < inNumSamples; i++) {
+ if (!m_triggerFinishState) {
+ if (m_level >= loopStart) {
+ m_loopState = true;
+ }
+ if (m_loopState) {
+ m_level = sc_wrap(m_level, loopStart, loopEnd);
}
}
- // Otherwise we wrap up
else {
- level = sc_max(level, startPosition);
- level = sc_min(level, endPosition);
+ m_loopState = false;
+ m_level = sc_clip(m_level, startPosition, endPosition);
}
- out[xxn] = static_cast(level);
- level += rate;
+ outBuf[i] = static_cast(m_level);
+ m_level += rate;
}
// Update the state of the LoopPhasor
- unit->m_prevTriggerStart = triggerReturnToStart;
- unit->m_prevTriggerFinish = triggerFinish;
- unit->m_level = level;
+ m_prevTriggerStart = triggerReturnToStart;
+ m_prevTriggerFinish = triggerFinish;
}
-// Calculates samples for a LoopPhasor.ar ugen with .kr parameters
-void LoopPhasor_next_ak(LoopPhasor* unit, int inNumSamples) {
+// rate parameter is audio rate
+void FlexPlugins::LoopPhasor::next_ak(int inNumSamples) {
// Pointer to output array
- float* out = OUT(0);
+ float* outBuf = out(0);
// Get new parameters of the LoopPhasor
- float *triggerReturnToStart = IN(0);
- float *triggerFinish = IN(1);
- double rate = IN0(2);
- double startPosition = IN0(3);
- double endPosition = IN0(4);
- double loopStart = IN0(5);
- double loopEnd = IN0(6);
-
- // Get current state of the LoopPhasor
- float previousTriggerReturnToStart = unit->m_prevTriggerStart;
- float previousTriggerFinish = unit->m_prevTriggerFinish;
- double level = unit->m_level;
+ const float triggerReturnToStart = in0(0);
+ const float triggerFinish = in0(1);
+ const float *rate = in(2);
+ const float startPosition = in0(3);
+ const float endPosition = in0(4);
+ const float loopStart = in0(5);
+ const float loopEnd = in0(6);
- // Compute output block
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
- // If we reset to start
- if (previousTriggerReturnToStart <= 0.f && triggerReturnToStart[xxn] > 0.f) {
- float frac = 1.f - previousTriggerReturnToStart / (triggerReturnToStart[xxn] - previousTriggerReturnToStart);
- level = startPosition + frac * rate;
- }
+ // Handle trigger return to start
+ if (m_prevTriggerStart <= 0.f && triggerReturnToStart > 0.f) {
+ m_level = startPosition;
+ }
- // Handle trigger finish. This just flips the finish trigger.
- if (previousTriggerFinish <= 0.f && triggerFinish[xxn] > 0.f) {
- unit->m_triggerFinishState = !(unit->m_triggerFinishState);
- }
+ // Handle trigger finish. This just flips the finish trigger.
+ if (m_prevTriggerFinish <= 0.f && triggerFinish > 0.f) {
+ m_triggerFinishState = !(m_triggerFinishState);
+ }
- // Wrapping: if we haven't triggered completion
- if (!unit->m_triggerFinishState) {
- // if we're inside the looping part of the LoopPhasor
- if (level >= loopStart && level <= loopEnd) {
- level = sc_wrap(level, loopStart, loopEnd);
- } else {
- level = sc_wrap(level, startPosition, endPosition);
+ // Compute output block
+ for (int i = 0; i < inNumSamples; i++) {
+ if (!m_triggerFinishState) {
+ if (m_level >= loopStart) {
+ m_loopState = true;
+ }
+ if (m_loopState) {
+ m_level = sc_wrap(m_level, loopStart, loopEnd);
}
}
- // Wrapping: if we have triggered completion
else {
- level = sc_max(level, startPosition);
- level = sc_min(level, endPosition);
+ m_level = sc_clip(m_level, startPosition, endPosition);
}
- out[xxn] = static_cast(level);
- level += rate;
- previousTriggerReturnToStart = triggerReturnToStart[xxn];
- previousTriggerFinish = triggerFinish[xxn];
+ outBuf[i] = static_cast(m_level);
+ m_level += rate[i];
}
-
- // update the state of the LoopPhasor
- unit->m_prevTriggerStart = previousTriggerReturnToStart;
- unit->m_prevTriggerFinish = previousTriggerFinish;
- unit->m_level = level;
+ m_prevTriggerStart = triggerReturnToStart;
+ m_prevTriggerFinish = triggerFinish;
}
-// Calculates samples for a LoopPhasor.ar UGen with .ar parameters
-void LoopPhasor_next_aa(LoopPhasor* unit, int inNumSamples) {
- float* out = OUT(0);
+// first two parameters are audio rate
+void FlexPlugins::LoopPhasor::next_aa(int inNumSamples) {
+ float* outBuf = out(0);
// Get new parameters of the LoopPhasor
- float *triggerReturnToStart = IN(0);
- float *triggerFinish = IN(1);
- float *rate = IN(2);
- double startPosition = IN0(3);
- double endPosition = IN0(4);
- double loopStart = IN0(5);
- double loopEnd = IN0(6);
-
- // Get current state of the LoopPhasor
- float previousTriggerReturnToStart = unit->m_prevTriggerStart;
- float previousTriggerFinish = unit->m_prevTriggerFinish;
- double level = unit->m_level;
-
- float *in = triggerReturnToStart;
- float previn = previousTriggerReturnToStart;
+ const float *triggerReturnToStart = in(0);
+ const float triggerFinish = in0(1);
+ const float *rate = in(2);
+ const float startPosition = in0(3);
+ const float endPosition = in0(4);
+ const float loopStart = in0(5);
+ const float loopEnd = in0(6);
+
+ // Handle trigger finish. This just flips the finish trigger.
+ if (m_prevTriggerFinish <= 0.f && triggerFinish > 0.f) {
+ m_triggerFinishState = !(m_triggerFinishState);
+ }
// Compute output block
- for (int xxn = 0; xxn < inNumSamples; xxn++) {
+ for (int i = 0; i < inNumSamples; i++) {
// Handle trigger return to start
- if (previousTriggerReturnToStart <= 0.f && triggerReturnToStart[xxn] > 0.f) {
- float frac = 1.f - previousTriggerReturnToStart / (triggerReturnToStart[xxn] - previousTriggerReturnToStart);
- level = startPosition + frac * rate[xxn];
- }
-
- // Handle trigger finish. This just flips the finish trigger.
- if (previousTriggerFinish <= 0.f && triggerFinish[xxn] > 0.f) {
- unit->m_triggerFinishState = !(unit->m_triggerFinishState);
+ if (m_prevTriggerStart <= 0.f && triggerReturnToStart[i] > 0.f) {
+ float frac = 1.f - m_prevTriggerStart / (triggerReturnToStart[i] - m_prevTriggerStart);
+ m_level = startPosition + frac * rate[i];
}
- // Wrapping: if we haven't triggered completion
- if (!unit->m_triggerFinishState) {
- // If we're inside the looping part of the LoopPhasor
- if (level >= loopStart && level <= loopEnd) {
- level = sc_wrap(level, loopStart, loopEnd);
- } else {
- level = sc_wrap(level, startPosition, endPosition);
+ if (!m_triggerFinishState) {
+ if (m_level >= loopStart) {
+ m_loopState = true;
+ }
+ if (m_loopState) {
+ m_level = sc_wrap(m_level, loopStart, loopEnd);
}
}
- // Wrapping: if we have triggered completion
else {
- level = sc_max(level, startPosition);
- level = sc_min(level, endPosition);
+ m_level = sc_clip(m_level, startPosition, endPosition);
}
- out[xxn] = static_cast(level);
- level += rate[xxn];
- previousTriggerReturnToStart = triggerReturnToStart[xxn];
- previousTriggerFinish = triggerFinish[xxn];
+ outBuf[i] = static_cast(m_level);
+ m_level += rate[i];
+ m_prevTriggerStart = triggerReturnToStart[i];
}
-
- // update the state of the LoopPhasor at the end of the calculation block
- unit->m_prevTriggerStart = previousTriggerReturnToStart;
- unit->m_prevTriggerFinish = previousTriggerFinish;
- unit->m_level = level;
+ m_prevTriggerFinish = triggerFinish;
}
diff --git a/src/generators/loopPhasor.hpp b/src/generators/loopPhasor.hpp
index d710fdd..7277df0 100644
--- a/src/generators/loopPhasor.hpp
+++ b/src/generators/loopPhasor.hpp
@@ -23,17 +23,22 @@ along with this program. If not, see .
*/
#pragma once
-#include "SC_PlugIn.h"
-
-// Represents a LoopPhasor UGen.
-struct LoopPhasor : public Unit {
- double m_level; // LoopPhasor output level (position of the phasor between `start` and `end`)
- float m_prevTriggerStart; // previous value of trigger to return to start position
- float m_prevTriggerFinish; // previous value of trigger to finish
- bool m_triggerFinishState; // current state of finish trigger (true - finish; false - continue looping)
-};
-
-void LoopPhasor_Ctor(LoopPhasor* unit);
-void LoopPhasor_next_aa(LoopPhasor* unit, int inNumSamples);
-void LoopPhasor_next_ak(LoopPhasor* unit, int inNumSamples);
-void LoopPhasor_next_kk(LoopPhasor* unit, int inNumSamples);
+#include "SC_PlugIn.hpp"
+
+namespace FlexPlugins {
+ // Represents a LoopPhasor UGen.
+ class LoopPhasor : public SCUnit {
+ public:
+ LoopPhasor();
+
+ private:
+ void next_ak(int inNumSamples);
+ void next_aa(int inNumSamples);
+ void next_k(int inNumSamples);
+ float m_level; // LoopPhasor output level (position of the phasor between `start` and `end`)
+ float m_prevTriggerStart; // previous value of trigger to return to start position
+ float m_prevTriggerFinish; // previous value of trigger to finish
+ bool m_triggerFinishState; // current state of finish trigger (true - finish; false - continue looping)
+ float m_loopState; // Tracks if we are currently looping
+ };
+}
diff --git a/src/pv/pv.cpp b/src/pv/pv.cpp
index ba9adb3..f7fe46f 100644
--- a/src/pv/pv.cpp
+++ b/src/pv/pv.cpp
@@ -22,7 +22,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-#include "SC_InterfaceTable.h"
#include "pvCFreeze.hpp"
#include "pvOther.hpp"
#include "pvStretch.hpp"
@@ -31,9 +30,9 @@ InterfaceTable *ft;
PluginLoad(PV_flexplugins) {
ft = inTable;
- DefineSimpleUnit(PV_MagMirror);
- DefineSimpleUnit(PV_MagSqueeze);
- DefineSimpleUnit(PV_MagXFade);
- DefineDtorUnit(PV_PlayBufStretch);
- DefineDtorUnit(PV_CFreeze);
+ registerUnit(ft, "PV_MagSqueeze", false);
+ registerUnit(ft, "PV_MagMirror", false);
+ registerUnit(ft, "PV_MagXFade", false);
+ registerUnit(ft, "PV_PlayBufStretch", false);
+ registerUnit(ft, "PV_CFreeze", false);
}
diff --git a/src/pv/pvCFreeze.cpp b/src/pv/pvCFreeze.cpp
index 67700a1..1458c15 100644
--- a/src/pv/pvCFreeze.cpp
+++ b/src/pv/pvCFreeze.cpp
@@ -27,30 +27,31 @@ along with this program. If not, see .
extern InterfaceTable *ft;
-void PV_CFreeze_next(PV_CFreeze *unit, int inNumSamples) {
+void FlexPlugins::PV_CFreeze::next(int inNumSamples) {
+ PV_CFreeze *unit = this;
PV_GET_BUF
- float freezeState = IN0(1);
+ float freezeState = in0(1);
// allocate the buffers
- if (!unit->mMags) {
+ if (!mMags) {
// MxN where N is num bins, and M is num frames. Acts as a circular buffer.
- unit->mMags = (float*)RTAlloc(unit->mWorld, numbins * sizeof(float) * unit->mNumFrames);
+ mMags = (float*)RTAlloc(mWorld, numbins * sizeof(float) * mNumFrames);
// M (num frames)
- unit->mDc = (float*)RTAlloc(unit->mWorld, sizeof(float) * unit->mNumFrames);
+ mDc = (float*)RTAlloc(mWorld, sizeof(float) * mNumFrames);
// M (num frames)
- unit->mNyq = (float*)RTAlloc(unit->mWorld, sizeof(float) * unit->mNumFrames);
+ mNyq = (float*)RTAlloc(mWorld, sizeof(float) * mNumFrames);
// N (num bins)
- unit->mPhase = (float*)RTAlloc(unit->mWorld, numbins * sizeof(float));
+ mPhase = (float*)RTAlloc(mWorld, numbins * sizeof(float));
// MxN where N is num bins, and M is num frames.
- // Acts as a circular buffer corresponding to unit->mMags.
- unit->mPhaseDiffs = (float*)RTAlloc(unit->mWorld, numbins * sizeof(float) * unit->mNumFrames);
- ClearFFTUnitIfMemFailed(unit->mMags);
- ClearFFTUnitIfMemFailed(unit->mDc);
- ClearFFTUnitIfMemFailed(unit->mNyq);
- ClearFFTUnitIfMemFailed(unit->mPhase);
- ClearFFTUnitIfMemFailed(unit->mPhaseDiffs);
- unit->mNumBins = numbins;
- unit->mWritePtr = 0;
- } else if (numbins != unit->mNumBins) {
+ // Acts as a circular buffer corresponding to mMags.
+ mPhaseDiffs = (float*)RTAlloc(mWorld, numbins * sizeof(float) * mNumFrames);
+ ClearFFTUnitIfMemFailed(mMags);
+ ClearFFTUnitIfMemFailed(mDc);
+ ClearFFTUnitIfMemFailed(mNyq);
+ ClearFFTUnitIfMemFailed(mPhase);
+ ClearFFTUnitIfMemFailed(mPhaseDiffs);
+ mNumBins = numbins;
+ mWritePtr = 0;
+ } else if (numbins != mNumBins) {
// Cannot allow the FFT size to change
return;
}
@@ -60,64 +61,64 @@ void PV_CFreeze_next(PV_CFreeze *unit, int inNumSamples) {
if (freezeState > 0.f) {
RGET
// Pull random DC and nyquist magnitudes
- p->dc = unit->mDc[rgen.irand(unit->mNumFrames)];
- p->nyq = unit->mNyq[rgen.irand(unit->mNumFrames)];
- for (int xxn = 0; xxn < unit->mNumBins; xxn++) {
+ p->dc = mDc[rgen.irand(mNumFrames)];
+ p->nyq = mNyq[rgen.irand(mNumFrames)];
+ for (int xxn = 0; xxn < mNumBins; xxn++) {
// For each bin, grab a random magnitude and phase diff pair
- int idx = rgen.irand(unit->mNumFrames);
- idx = idx * unit->mNumBins + xxn;
- p->bin[xxn].mag = unit->mMags[idx];
- unit->mPhase[xxn] = sc_wrap(unit->mPhase[xxn] + unit->mPhaseDiffs[idx], 0.f, static_cast(twopi));
- p->bin[xxn].phase = unit->mPhase[xxn];
+ int idx = rgen.irand(mNumFrames);
+ idx = idx * mNumBins + xxn;
+ p->bin[xxn].mag = mMags[idx];
+ mPhase[xxn] = sc_wrap(mPhase[xxn] + mPhaseDiffs[idx], 0.f, static_cast(twopi));
+ p->bin[xxn].phase = mPhase[xxn];
}
} else {
// We're writing to a circular buffer, so pull the current magnitude and phase diff arrays
- float *currentMagArr = unit->mMags + (unit->mWritePtr * unit->mNumBins);
- float *currentPhaseDiffArr = unit->mPhaseDiffs + (unit->mWritePtr * unit->mNumBins);
+ float *currentMagArr = mMags + (mWritePtr * mNumBins);
+ float *currentPhaseDiffArr = mPhaseDiffs + (mWritePtr * mNumBins);
for (int xxn = 0; xxn < numbins; xxn++) {
currentMagArr[xxn] = p->bin[xxn].mag;
- currentPhaseDiffArr[xxn] = sc_wrap(p->bin[xxn].phase - unit->mPhase[xxn], 0.f, static_cast(twopi));
- unit->mPhase[xxn] = p->bin[xxn].phase;
+ currentPhaseDiffArr[xxn] = sc_wrap(p->bin[xxn].phase - mPhase[xxn], 0.f, static_cast(twopi));
+ mPhase[xxn] = p->bin[xxn].phase;
}
- unit->mDc[unit->mWritePtr] = p->dc;
- unit->mNyq[unit->mWritePtr] = p->nyq;
- unit->mWritePtr++;
- unit->mWritePtr %= unit->mNumFrames;
+ mDc[mWritePtr] = p->dc;
+ mNyq[mWritePtr] = p->nyq;
+ mWritePtr++;
+ mWritePtr %= mNumFrames;
}
}
-void PV_CFreeze_Ctor(PV_CFreeze *unit) {
- SETCALC(PV_CFreeze_next);
- OUT0(0) = IN0(0);
- unit->mMags = nullptr;
- unit->mDc = nullptr;
- unit->mNyq = nullptr;
- unit->mPhase = nullptr;
- unit->mPhaseDiffs = nullptr;
- int numFrames = static_cast(IN0(2));
+FlexPlugins::PV_CFreeze::PV_CFreeze() {
+ mMags = nullptr;
+ mDc = nullptr;
+ mNyq = nullptr;
+ mPhase = nullptr;
+ mPhaseDiffs = nullptr;
+ int numFrames = static_cast(in0(2));
// prevent the user from doing something nuts
- unit->mNumFrames = sc_clip(numFrames, 1, 64);
+ mNumFrames = sc_clip(numFrames, 1, 64);
+ set_calc_function();
+ next(1);
}
-void PV_CFreeze_Dtor(PV_CFreeze *unit) {
- if (unit->mMags) {
- RTFree(unit->mWorld, unit->mMags);
- unit->mMags = nullptr;
+FlexPlugins::PV_CFreeze::~PV_CFreeze() {
+ if (mMags) {
+ RTFree(mWorld, mMags);
+ mMags = nullptr;
}
- if (unit->mDc) {
- RTFree(unit->mWorld, unit->mDc);
- unit->mDc = nullptr;
+ if (mDc) {
+ RTFree(mWorld, mDc);
+ mDc = nullptr;
}
- if (unit->mNyq) {
- RTFree(unit->mWorld, unit->mNyq);
- unit->mNyq = nullptr;
+ if (mNyq) {
+ RTFree(mWorld, mNyq);
+ mNyq = nullptr;
}
- if (unit->mPhase) {
- RTFree(unit->mWorld, unit->mPhase);
- unit->mPhase = nullptr;
+ if (mPhase) {
+ RTFree(mWorld, mPhase);
+ mPhase = nullptr;
}
- if (unit->mPhaseDiffs) {
- RTFree(unit->mWorld, unit->mPhaseDiffs);
- unit->mPhaseDiffs = nullptr;
+ if (mPhaseDiffs) {
+ RTFree(mWorld, mPhaseDiffs);
+ mPhaseDiffs = nullptr;
}
}
diff --git a/src/pv/pvCFreeze.hpp b/src/pv/pvCFreeze.hpp
index 9d76180..bd8b0b1 100644
--- a/src/pv/pvCFreeze.hpp
+++ b/src/pv/pvCFreeze.hpp
@@ -23,19 +23,24 @@ along with this program. If not, see .
*/
#pragma once
-#include "SC_Unit.h"
-
-struct PV_CFreeze : public Unit {
- int mNumBins; // The number of FFT bins
- int mNumFrames; // The number of candidate FFT frames to maintain
- float *mMags; // The 2D array of FFT mags
- float *mDc; // The 1D array of FFT DC values
- float *mNyq; // The 1D array of FFT Nyquist values
- float *mPhase; // The most recent phase array
- float *mPhaseDiffs; // The 2D array of FFT phase differences
- size_t mWritePtr; // The write pointer
-};
-
-void PV_CFreeze_next(PV_CFreeze *unit, int inNumSamples);
-void PV_CFreeze_Ctor(PV_CFreeze *unit);
-void PV_CFreeze_Dtor(PV_CFreeze *unit);
\ No newline at end of file
+#include "SC_PlugIn.hpp"
+
+namespace FlexPlugins {
+ class PV_CFreeze : public SCUnit {
+ public:
+ PV_CFreeze();
+ ~PV_CFreeze();
+
+ private:
+ void next(int inNumSamples);
+
+ int mNumBins; // The number of FFT bins
+ int mNumFrames; // The number of candidate FFT frames to maintain
+ float *mMags; // The 2D array of FFT mags
+ float *mDc; // The 1D array of FFT DC values
+ float *mNyq; // The 1D array of FFT Nyquist values
+ float *mPhase; // The most recent phase array
+ float *mPhaseDiffs; // The 2D array of FFT phase differences
+ size_t mWritePtr; // The write pointer
+ };
+}
diff --git a/src/pv/pvOther.cpp b/src/pv/pvOther.cpp
index 55f1efa..4f20a68 100644
--- a/src/pv/pvOther.cpp
+++ b/src/pv/pvOther.cpp
@@ -27,10 +27,11 @@ along with this program. If not, see .
extern InterfaceTable *ft;
-void PV_MagSqueeze_next(PV_MagSqueeze *unit, int inNumSamples) {
+void FlexPlugins::PV_MagSqueeze::next(int inNumSamples) {
+ PV_MagSqueeze *unit = this;
PV_GET_BUF
- float low = IN0(1);
- float high = IN0(2);
+ float low = in0(1);
+ float high = in0(2);
SCPolarBuf *p = ToPolarApx(buf);
float min = p->dc;
float max = p->dc;
@@ -52,12 +53,13 @@ void PV_MagSqueeze_next(PV_MagSqueeze *unit, int inNumSamples) {
}
}
-void PV_MagSqueeze_Ctor(PV_MagSqueeze *unit) {
- SETCALC(PV_MagSqueeze_next);
- OUT0(0) = IN0(0);
+FlexPlugins::PV_MagSqueeze::PV_MagSqueeze() {
+ set_calc_function();
+ next(1);
}
-void PV_MagMirror_next(PV_MagMirror *unit, int inNumSamples) {
+void FlexPlugins::PV_MagMirror::next(int inNumSamples) {
+ PV_MagMirror *unit = this;
PV_GET_BUF
SCPolarBuf *p = ToPolarApx(buf);
float min = p->dc;
@@ -79,14 +81,15 @@ void PV_MagMirror_next(PV_MagMirror *unit, int inNumSamples) {
}
}
-void PV_MagMirror_Ctor(PV_MagMirror *unit) {
- SETCALC(PV_MagMirror_next);
- OUT0(0) = IN0(0);
+FlexPlugins::PV_MagMirror::PV_MagMirror() {
+ set_calc_function();
+ next(1);
}
-void PV_MagXFade_next(PV_MagXFade *unit, int inNumSamples) {
+void FlexPlugins::PV_MagXFade::next(int inNumSamples) {
+ PV_MagXFade *unit = this;
PV_GET_BUF2
- float crossfade = IN0(2);
+ float crossfade = in0(2);
crossfade = sc_clip(crossfade, 0.f, 1.f);
SCPolarBuf *p = ToPolarApx(buf1);
SCPolarBuf *q = ToPolarApx(buf2);
@@ -106,7 +109,7 @@ void PV_MagXFade_next(PV_MagXFade *unit, int inNumSamples) {
}
}
-void PV_MagXFade_Ctor(PV_MagXFade *unit) {
- SETCALC(PV_MagXFade_next);
- OUT0(0) = IN0(0);
+FlexPlugins::PV_MagXFade::PV_MagXFade() {
+ set_calc_function();
+ next(1);
}
\ No newline at end of file
diff --git a/src/pv/pvOther.hpp b/src/pv/pvOther.hpp
index 899d6b2..1921ae5 100644
--- a/src/pv/pvOther.hpp
+++ b/src/pv/pvOther.hpp
@@ -23,16 +23,27 @@ along with this program. If not, see .
*/
#pragma once
-#include "SC_Unit.h"
-
-struct PV_MagSqueeze : public Unit {};
-void PV_MagSqueeze_next(PV_MagSqueeze *unit, int inNumSamples);
-void PV_MagSqueeze_Ctor(PV_MagSqueeze *unit);
-
-struct PV_MagMirror : public Unit {};
-void PV_MagMirror_next(PV_MagMirror *unit, int inNumSamples);
-void PV_MagMirror_Ctor(PV_MagMirror *unit);
-
-struct PV_MagXFade : public Unit {};
-void PV_MagXFade_next(PV_MagXFade *unit, int inNumSamples);
-void PV_MagXFade_Ctor(PV_MagXFade *unit);
\ No newline at end of file
+#include "SC_PlugIn.hpp"
+
+namespace FlexPlugins {
+ class PV_MagSqueeze : public SCUnit {
+ public:
+ PV_MagSqueeze();
+ private:
+ void next(int inNumSamples);
+ };
+
+ class PV_MagMirror : public SCUnit {
+ public:
+ PV_MagMirror();
+ private:
+ void next(int inNumSamples);
+ };
+
+ class PV_MagXFade : public SCUnit {
+ public:
+ PV_MagXFade();
+ private:
+ void next(int inNumSamples);
+ };
+}
\ No newline at end of file
diff --git a/src/pv/pvStretch.cpp b/src/pv/pvStretch.cpp
index 9db9cc1..f994baa 100644
--- a/src/pv/pvStretch.cpp
+++ b/src/pv/pvStretch.cpp
@@ -30,76 +30,77 @@ along with this program. If not, see .
extern InterfaceTable *ft;
-void PV_PlayBufStretch_Ctor(PV_PlayBufStretch *unit) {
+FlexPlugins::PV_PlayBufStretch::PV_PlayBufStretch() {
+ PV_PlayBufStretch *unit = this;
PV_GET_BUF
// Connect to the STFT buffer. For now, we only allow this in the constructor.
- float fstftbufnum = IN0(1);
+ float fstftbufnum = in0(1);
uint32 stftbufnum = static_cast(fstftbufnum);
- if (stftbufnum >= unit->mWorld->mNumSndBufs) stftbufnum = 0;
- unit->m_fbufnum = fstftbufnum;
- unit->m_buf = unit->mWorld->mSndBufs + stftbufnum;
- unit->m_outFramePrev = nullptr;
- unit->m_frameNext = nullptr;
- unit->m_framePrev1 = nullptr;
- unit->m_framePrev2 = nullptr;
- size_t peakRadius = static_cast(sc_clip(IN0(6), 1.f, 32.f));
- unit->m_peakFinder = (PeakFinder*)RTAlloc(unit->mWorld, sizeof(PeakFinder));
- new (unit->m_peakFinder) PeakFinder(static_cast(buf->samples), peakRadius);
- unit->m_peakFinder->memLoad(RTAlloc(unit->mWorld, unit->m_peakFinder->memSize()));
+ if (stftbufnum >= mWorld->mNumSndBufs) stftbufnum = 0;
+ m_fbufnum = fstftbufnum;
+ m_buf = mWorld->mSndBufs + stftbufnum;
+ m_outFramePrev = nullptr;
+ m_frameNext = nullptr;
+ m_framePrev1 = nullptr;
+ m_framePrev2 = nullptr;
+ size_t peakRadius = static_cast(sc_clip(in0(6), 1.f, 32.f));
+ m_peakFinder = (PeakFinder*)RTAlloc(mWorld, sizeof(PeakFinder));
+ new (m_peakFinder) PeakFinder(static_cast(buf->samples), peakRadius);
+ m_peakFinder->memLoad(RTAlloc(mWorld, m_peakFinder->memSize()));
// Configure position
- float startPos = sc_clip(IN0(2), 0.0, 1.0);
- unit->m_pos = 0.f;
- unit->m_startPos = startPos;
- unit->m_firstFrame = true;
+ float startPos = sc_clip(in0(2), 0.0, 1.0);
+ m_pos = 0.f;
+ m_startPos = startPos;
+ m_firstFrame = true;
- SETCALC(PV_PlayBufStretch_next);
- OUT0(0) = IN0(0);
+ set_calc_function();
+ next(1);
}
-void PV_PlayBufStretch_Dtor(PV_PlayBufStretch *unit) {
- if (unit->m_peakFinder) {
- void *reservedMem = unit->m_peakFinder->memRetrieve();
+FlexPlugins::PV_PlayBufStretch::~PV_PlayBufStretch() {
+ if (m_peakFinder) {
+ void *reservedMem = m_peakFinder->memRetrieve();
if (reservedMem) {
- RTFree(unit->mWorld, reservedMem);
+ RTFree(mWorld, reservedMem);
}
- RTFree(unit->mWorld, unit->m_peakFinder);
+ RTFree(mWorld, m_peakFinder);
}
- if (unit->m_outFramePrev) {
- RTFree(unit->mWorld, unit->m_outFramePrev);
+ if (m_outFramePrev) {
+ RTFree(mWorld, m_outFramePrev);
}
- if (unit->m_frameNext) {
- RTFree(unit->mWorld, unit->m_frameNext);
+ if (m_frameNext) {
+ RTFree(mWorld, m_frameNext);
}
- if (unit->m_framePrev1) {
- RTFree(unit->mWorld, unit->m_framePrev1);
+ if (m_framePrev1) {
+ RTFree(mWorld, m_framePrev1);
}
- if (unit->m_framePrev2) {
- RTFree(unit->mWorld, unit->m_framePrev2);
+ if (m_framePrev2) {
+ RTFree(mWorld, m_framePrev2);
}
}
-void PV_PlayBufStretch_next(PV_PlayBufStretch *unit, int inNumSamples) {
+void FlexPlugins::PV_PlayBufStretch::next(int inNumSamples) {
+ PV_PlayBufStretch *unit = this;
PV_GET_BUF
// This section of the code is for acquiring the STFT buffer and information about it.
// It has to be run every time because we cannot be sure the user has not freed the buffer.
// We also have to verify important details about the buffer to make sure we can read from it at all.
- const SndBuf *stftBuf = unit->m_buf;
- if (!stftBuf) {
+ if (!m_buf) {
OUT0(0) = -1.f;
std::cout << "WARNING: The stftBuffer could not be accessed. Aborting.\n";
return;
}
ACQUIRE_SNDBUF_SHARED(stftBuf);
- const float* bufData __attribute__((__unused__)) = stftBuf->data;
- const float* stftData __attribute__((__unused__)) = stftBuf->data + 3;
- const uint32 bufChannels __attribute__((__unused__)) = stftBuf->channels;
- const uint32 bufSamples __attribute__((__unused__)) = stftBuf->samples;
- const uint32 bufFrames = stftBuf->frames;
+ const float* bufData __attribute__((__unused__)) = m_buf->data;
+ const float* stftData __attribute__((__unused__)) = m_buf->data + 3;
+ const uint32 bufChannels __attribute__((__unused__)) = m_buf->channels;
+ const uint32 bufSamples __attribute__((__unused__)) = m_buf->samples;
+ const uint32 bufFrames = m_buf->frames;
// first 3 frames have analysis parameters
- const int stftFrames = (static_cast(stftBuf->samples) - 3) / static_cast(buf->samples);
+ const int stftFrames = (static_cast(m_buf->samples) - 3) / static_cast(buf->samples);
// If the buffer is improperly configured, we cannot use it.
if (bufChannels != 1) {
@@ -133,64 +134,66 @@ void PV_PlayBufStretch_next(PV_PlayBufStretch *unit, int inNumSamples) {
}
// The first time through, we need to allocate the SCPolarBuf storage in the UGen.
- if (!unit->m_outFramePrev) {
+ if (!m_outFramePrev) {
// This is an annoying way to have to allocate memory,
// but it seems to be necessary based on how SCPolarBuf is defined.
- float *outFramePrev = (float*)RTAlloc(unit->mWorld, stftBufFftSize * sizeof(float));
- float *frameNext = (float*)RTAlloc(unit->mWorld, stftBufFftSize * sizeof(float));
- float *framePrev1 = (float*)RTAlloc(unit->mWorld, stftBufFftSize * sizeof(float));
- float *framePrev2 = (float*)RTAlloc(unit->mWorld, stftBufFftSize * sizeof(float));
- unit->m_outFramePrev = (SCPolarBuf*)outFramePrev;
- unit->m_frameNext = (SCPolarBuf*)frameNext;
- unit->m_framePrev1 = (SCPolarBuf*)framePrev1;
- unit->m_framePrev2 = (SCPolarBuf*)framePrev2;
+ float *outFramePrev = (float*)RTAlloc(mWorld, stftBufFftSize * sizeof(float));
+ float *frameNext = (float*)RTAlloc(mWorld, stftBufFftSize * sizeof(float));
+ float *framePrev1 = (float*)RTAlloc(mWorld, stftBufFftSize * sizeof(float));
+ float *framePrev2 = (float*)RTAlloc(mWorld, stftBufFftSize * sizeof(float));
+ m_outFramePrev = (SCPolarBuf*)outFramePrev;
+ m_frameNext = (SCPolarBuf*)frameNext;
+ m_framePrev1 = (SCPolarBuf*)framePrev1;
+ m_framePrev2 = (SCPolarBuf*)framePrev2;
}
- float startPos = sc_clip(IN0(2), 0.0, 1.0);
- const float rate = IN0(3);
- const float loop = IN0(4);
+ float startPos = sc_clip(in0(2), 0.0, 1.0);
+ const float rate = in0(3);
+ const float loop = in0(4);
- if (startPos != unit->m_startPos) {
- unit->m_startPos = startPos;
- unit->m_firstFrame = true;
+ if (startPos != m_startPos) {
+ m_startPos = startPos;
+ m_firstFrame = true;
// std::cout << "Start pos changed\n";
}
// Now that we've run setup, we're ready to read STFT data and perform phase vocoder stretching.
// First we need to figure out where we are, and if that means we need to loop or quit.
- float newPos = unit->m_pos + rate;
+ float newPos = m_pos + rate;
if (newPos > stftFrames - 1) {
if (loop && rate > 0) {
- unit->m_firstFrame = true;
+ m_firstFrame = true;
startPos = 0;
} else if (rate <= 0) {
// clip it to the last possible frame if we're working backwards
newPos = stftFrames - 1;
} else {
- OUT0(0) = -1.f;
+ float *outBuf = out(0);
+ outBuf[0] = -1.f;
RELEASE_SNDBUF_SHARED(stftBuf);
- DoneAction(static_cast(IN0(7)), unit);
+ DoneAction(static_cast(in0(7)), this);
return;
}
} else if (newPos < 0) {
if (loop && rate < 0) {
- unit->m_firstFrame = true;
+ m_firstFrame = true;
startPos = 1;
} else if (rate >= 0) {
// clip it to the first frame if we're working forwards
newPos = 0;
} else {
- OUT0(0) = -1.f;
+ float *outBuf = out(0);
+ outBuf[0] = -1.f;
RELEASE_SNDBUF_SHARED(stftBuf);
- DoneAction(static_cast(IN0(7)), unit);
+ DoneAction(static_cast(in0(7)), this);
return;
}
}
// The first frame has to be cloned directly from the STFT buffer with no phase adjustments.
// This is essential to make sure that subsequent phase calculations are correctly aligned.
- if (unit->m_firstFrame) {
+ if (m_firstFrame) {
// Compute the index of the first frame
size_t firstFrameIdx = static_cast(std::round(startPos * (stftFrames-1)));
@@ -203,16 +206,16 @@ void PV_PlayBufStretch_next(PV_PlayBufStretch *unit, int inNumSamples) {
// We always need to store the resultant FFT frame in the UGen.
// It is used in the next call to PV_PlayBufStretch_next, for
// phase vocoder calculations.
- fillPolarBuf(currentFftFrame, unit->m_outFramePrev, stftBufFftSize);
+ fillPolarBuf(currentFftFrame, m_outFramePrev, stftBufFftSize);
// We have to advance by one frame because we need to be able to compute frequency for time stretching.
- unit->m_pos = static_cast(firstFrameIdx + 1);
- unit->m_firstFrame = false;
+ m_pos = static_cast(firstFrameIdx + 1);
+ m_firstFrame = false;
}
// For frames other than the first frame, we'll need to perform phase computation.
else {
- size_t phaseLock = sc_clip(static_cast(IN0(5)), 0, 2);
+ size_t phaseLock = sc_clip(static_cast(in0(5)), 0, 2);
SCPolarBuf *p = ToPolarApx(buf);
size_t roundedPos = static_cast(std::round(newPos));
@@ -226,37 +229,37 @@ void PV_PlayBufStretch_next(PV_PlayBufStretch *unit, int inNumSamples) {
} else if (lastPos >= stftFrames) {
lastPos = roundedPos - 1;
}
- fillPolarBuf(stftData + (roundedPos * stftBufFftSize), unit->m_frameNext, stftBufFftSize);
- fillPolarBuf(stftData + (lastPos * stftBufFftSize), unit->m_framePrev1, stftBufFftSize);
+ fillPolarBuf(stftData + (roundedPos * stftBufFftSize), m_frameNext, stftBufFftSize);
+ fillPolarBuf(stftData + (lastPos * stftBufFftSize), m_framePrev1, stftBufFftSize);
// Render the output FFT frame
switch (phaseLock) {
case 1:
Stretch2Puckette(
- unit->m_frameNext,
- unit->m_framePrev1,
+ m_frameNext,
+ m_framePrev1,
p,
- unit->m_outFramePrev,
+ m_outFramePrev,
stftBufFftSize,
stftBufHopSize
);
break;
case 2:
Stretch2LarocheDolson(
- unit->m_frameNext,
- unit->m_framePrev1,
+ m_frameNext,
+ m_framePrev1,
p,
- unit->m_outFramePrev,
- unit->m_peakFinder,
+ m_outFramePrev,
+ m_peakFinder,
stftBufFftSize,
stftBufHopSize
);
break;
default:
Stretch2(
- unit->m_frameNext,
- unit->m_framePrev1,
+ m_frameNext,
+ m_framePrev1,
p,
- unit->m_outFramePrev,
+ m_outFramePrev,
stftBufFftSize,
stftBufHopSize
);
@@ -277,19 +280,19 @@ void PV_PlayBufStretch_next(PV_PlayBufStretch *unit, int inNumSamples) {
}
// We are in between these two frames
- fillPolarBuf(stftData + (hi * stftBufFftSize), unit->m_frameNext, stftBufFftSize);
- fillPolarBuf(stftData + (lo * stftBufFftSize), unit->m_framePrev1, stftBufFftSize);
+ fillPolarBuf(stftData + (hi * stftBufFftSize), m_frameNext, stftBufFftSize);
+ fillPolarBuf(stftData + (lo * stftBufFftSize), m_framePrev1, stftBufFftSize);
// This is the frame right before that. It's needed to compute the previous instantaneous frequencies.
- fillPolarBuf(stftData + (loprev * stftBufFftSize), unit->m_framePrev2, stftBufFftSize);
+ fillPolarBuf(stftData + (loprev * stftBufFftSize), m_framePrev2, stftBufFftSize);
// Render the output FFT frame
switch (phaseLock) {
case 1:
Stretch3Puckette(
- unit->m_frameNext,
- unit->m_framePrev1,
- unit->m_framePrev2,
+ m_frameNext,
+ m_framePrev1,
+ m_framePrev2,
p,
- unit->m_outFramePrev,
+ m_outFramePrev,
newPos-static_cast(lo),
stftBufFftSize,
stftBufHopSize
@@ -297,12 +300,12 @@ void PV_PlayBufStretch_next(PV_PlayBufStretch *unit, int inNumSamples) {
break;
case 2:
Stretch3LarocheDolson(
- unit->m_frameNext,
- unit->m_framePrev1,
- unit->m_framePrev2,
+ m_frameNext,
+ m_framePrev1,
+ m_framePrev2,
p,
- unit->m_outFramePrev,
- unit->m_peakFinder,
+ m_outFramePrev,
+ m_peakFinder,
newPos-static_cast(lo),
stftBufFftSize,
stftBufHopSize
@@ -310,11 +313,11 @@ void PV_PlayBufStretch_next(PV_PlayBufStretch *unit, int inNumSamples) {
break;
default:
Stretch3(
- unit->m_frameNext,
- unit->m_framePrev1,
- unit->m_framePrev2,
+ m_frameNext,
+ m_framePrev1,
+ m_framePrev2,
p,
- unit->m_outFramePrev,
+ m_outFramePrev,
newPos-static_cast(lo),
stftBufFftSize,
stftBufHopSize
@@ -324,8 +327,8 @@ void PV_PlayBufStretch_next(PV_PlayBufStretch *unit, int inNumSamples) {
// We always need to store the resultant FFT frame in the UGen.
// It is used in the next call to PV_PlayBufStretch_next, for
// phase vocoder calculations.
- copyPolarBuf(p, unit->m_outFramePrev, static_cast(numbins));
- unit->m_pos = newPos;
+ copyPolarBuf(p, m_outFramePrev, static_cast(numbins));
+ m_pos = newPos;
}
RELEASE_SNDBUF_SHARED(stftBuf);
@@ -342,7 +345,7 @@ void PV_PlayBufStretch_next(PV_PlayBufStretch *unit, int inNumSamples) {
/// \param outFramePrev The previously computed output STFT frame
/// \param fftSize The FFT size
/// \param hopSize The hop size
-void Stretch2(
+void FlexPlugins::PV_PlayBufStretch::Stretch2(
const SCPolarBuf *frame,
const SCPolarBuf *framePrev,
SCPolarBuf *outFrame,
@@ -381,7 +384,7 @@ void Stretch2(
/// \param outFramePrev The previously computed output STFT frame
/// \param fftSize The FFT size
/// \param hopSize The hop size
-void Stretch2Puckette(
+void FlexPlugins::PV_PlayBufStretch::Stretch2Puckette(
const SCPolarBuf *frame,
const SCPolarBuf *framePrev,
SCPolarBuf *outFrame,
@@ -434,7 +437,7 @@ void Stretch2Puckette(
/// \param peakFinder The PeakFinder instance for determining peak locations in the magnitude spectrum
/// \param fftSize The FFT size
/// \param hopSize The hop size
-void Stretch2LarocheDolson(
+void FlexPlugins::PV_PlayBufStretch::Stretch2LarocheDolson(
const SCPolarBuf *frame,
const SCPolarBuf *framePrev,
SCPolarBuf *outFrame,
@@ -550,7 +553,7 @@ void Stretch2LarocheDolson(
/// \param pos The position between framePrev1 and frameNext (0 < pos < 1)
/// \param fftSize The FFT size
/// \param hopSize The hop size
-void Stretch3(
+void FlexPlugins::PV_PlayBufStretch::Stretch3(
const SCPolarBuf *frameNext,
const SCPolarBuf *framePrev1,
const SCPolarBuf *framePrev2,
@@ -602,7 +605,7 @@ void Stretch3(
/// \param pos The position between framePrev1 and frameNext (0 < pos < 1)
/// \param fftSize The FFT size
/// \param hopSize The hop size
-void Stretch3Puckette(
+void FlexPlugins::PV_PlayBufStretch::Stretch3Puckette(
const SCPolarBuf *frameNext,
const SCPolarBuf *framePrev1,
const SCPolarBuf *framePrev2,
@@ -668,7 +671,7 @@ void Stretch3Puckette(
/// \param pos The position between framePrev1 and frameNext (0 < pos < 1)
/// \param fftSize The FFT size
/// \param hopSize The hop size
-static void Stretch3LarocheDolson(
+void FlexPlugins::PV_PlayBufStretch::Stretch3LarocheDolson(
const SCPolarBuf *frameNext,
const SCPolarBuf *framePrev1,
const SCPolarBuf *framePrev2,
@@ -821,7 +824,7 @@ static void Stretch3LarocheDolson(
/// \param fftBuf The FFT frame from the STFT buffer
/// \param [out] polarBuf The SCPolarBuf to copy to
/// \param fftSize The FFT size
-void fillPolarBuf(const float *fftBuf, SCPolarBuf *polarBuf, size_t fftSize) {
+void FlexPlugins::PV_PlayBufStretch::fillPolarBuf(const float *fftBuf, SCPolarBuf *polarBuf, size_t fftSize) {
polarBuf->dc = fftBuf[0];
polarBuf->nyq = fftBuf[1];
for (size_t xxn = 2, xxk = 0; xxn < fftSize; xxn+=2, xxk++) {
@@ -837,7 +840,7 @@ void fillPolarBuf(const float *fftBuf, SCPolarBuf *polarBuf, size_t fftSize) {
/// \param sourceBuf The source buffer
/// \param [out] destBuf The destination buffer
/// \param numbins The number of bins in the SCPolarBuf (fftSize/2-1)
-void copyPolarBuf(const SCPolarBuf *sourceBuf, SCPolarBuf *destBuf, size_t numbins) {
+void FlexPlugins::PV_PlayBufStretch::copyPolarBuf(const SCPolarBuf *sourceBuf, SCPolarBuf *destBuf, size_t numbins) {
destBuf->dc = sourceBuf->dc;
destBuf->nyq = sourceBuf->nyq;
for (size_t xxn = 0; xxn < numbins; xxn++) {
@@ -846,11 +849,10 @@ void copyPolarBuf(const SCPolarBuf *sourceBuf, SCPolarBuf *destBuf, size_t numbi
}
}
+FlexPlugins::Peak::Peak(size_t peak) : peak(peak) {}
+FlexPlugins::Peak::Peak(size_t peak, size_t leftValley, size_t rightValley) : peak(peak), leftValley(leftValley), rightValley(rightValley) {}
-Peak::Peak(size_t peak) : peak(peak) {}
-Peak::Peak(size_t peak, size_t leftValley, size_t rightValley) : peak(peak), leftValley(leftValley), rightValley(rightValley) {}
-
-PeakFinder::PeakFinder(size_t fftSize, size_t radius) {
+FlexPlugins::PeakFinder::PeakFinder(size_t fftSize, size_t radius) {
m_maxSize = fftSize/2-1;
m_radius = radius;
m_size = 0;
@@ -859,34 +861,34 @@ PeakFinder::PeakFinder(size_t fftSize, size_t radius) {
m_queueR = nullptr;
}
-void PeakFinder::memLoad(void* arr) {
+void FlexPlugins::PeakFinder::memLoad(void* arr) {
size_t *data = (size_t*)arr;
m_queueL = data;
m_queueR = data + m_radius;
peaks = (Peak*)(data + 2 * m_radius);
}
-size_t PeakFinder::memSize() const {
+size_t FlexPlugins::PeakFinder::memSize() const {
return m_radius * 2 * sizeof(size_t) + m_maxSize * sizeof(Peak);
}
-void* PeakFinder::memRetrieve() {
+void* FlexPlugins::PeakFinder::memRetrieve() {
return (void*)m_queueL;
}
-void PeakFinder::clear() {
+void FlexPlugins::PeakFinder::clear() {
m_size = 0;
}
-size_t PeakFinder::maxSize() const {
+size_t FlexPlugins::PeakFinder::maxSize() const {
return m_maxSize;
}
-size_t PeakFinder::size() const {
+size_t FlexPlugins::PeakFinder::size() const {
return m_size;
}
-void PeakFinder::analyze(const SCPolarBuf *buf) {
+void FlexPlugins::PeakFinder::analyze(const SCPolarBuf *buf) {
// We can only perform the analysis if we have enough bins
if (m_queueL && m_maxSize > m_radius * 2 + 1) {
m_size = 0; // clear any existing data
diff --git a/src/pv/pvStretch.hpp b/src/pv/pvStretch.hpp
index fe70e1a..29f83d3 100644
--- a/src/pv/pvStretch.hpp
+++ b/src/pv/pvStretch.hpp
@@ -22,256 +22,256 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#pragma once
-#include "SC_Unit.h"
+#include "SC_PlugIn.hpp"
#include "FFT_UGens.h"
-class Peak {
-public:
- Peak(size_t peak);
- Peak(size_t peak, size_t leftValley, size_t rightValley);
- size_t peak, leftValley, rightValley;
-};
-
-class PeakFinder {
-public:
- /// Constructs the PeakFinder
- ///
- /// \param fftSize The FFT size
- PeakFinder(size_t fftSize, size_t radius);
-
- /// Finds peaks in the provided SCPolarBuf. Note that this buffer must correspond
- /// to the original FFT size provided for the PeakFinder--otherwise memory errors may occur.
- ///
- /// \param buf The buffer to analyze
- void analyze(const SCPolarBuf *buf);
-
- /// Loads memory from the external SuperCollider allocator. Memory is allocated
- /// using RTAlloc() and the size is specified by the memSize() method.
- ///
- /// \param arr The allocated memory
- void memLoad(void *arr);
-
- /// Gets the memory size required for the PeakFinder
- size_t memSize() const;
-
- /// Gets the max size of the PeakFinder
- ///
- /// \returns The max size
- size_t maxSize() const;
-
- /// Gets the current size of the PeakFinder (the number of peaks stored)
- ///
- /// \returns The current size
- size_t size() const;
-
- /// Clears the PeakFinder
- void clear();
-
- /// Gets a pointer to the memory that was allocated for the PeakFinder
- /// so that it can be deallocated
- ///
- /// \return The memory pointer
- void* memRetrieve();
-
- Peak *peaks;
-private:
- size_t m_maxSize, m_size, m_radius;
- size_t *m_queueL, *m_queueR;
-};
-
-/// Stores the state of a PV_PlayBufStretch UGen instance
-struct PV_PlayBufStretch : public Unit {
- /// The index of the buffer with STFT data
- float m_fbufnum;
-
- /// The buffer with STFT data
- SndBuf *m_buf;
-
- /// The most recent output STFT frame
- SCPolarBuf *m_outFramePrev;
-
- /// The next STFT frame after the current position
- SCPolarBuf *m_frameNext;
-
- /// The STFT frame right before the current position
- SCPolarBuf *m_framePrev1;
-
- /// The STFT frame two positions before the current position
- SCPolarBuf *m_framePrev2;
-
- /// The peak finding utility for the Laroche/Dolson stretching algorithm
- PeakFinder *m_peakFinder;
-
- /// Between 0 and 1; represents the start position of playback.
- /// If it jumps during playback, playback will be restarted
- /// at the new m_startPos.
- float m_startPos;
-
- /// A fractional STFT frame index. Unlike m_startPos, it corresponds to the
- /// integer index of the current STFT frame (from 0 to M-1).
- /// Used for interpolating position.
- float m_pos;
-
- /// For the first frame, we need to read phase data directly
- /// instead of computing it.
- bool m_firstFrame;
-};
-
-/// Initializes a new PV_PlayBufStretch UGen
-void PV_PlayBufStretch_Ctor(PV_PlayBufStretch *unit);
-
-/// Frees memory created by the PV_PlayBufStretch UGen
-void PV_PlayBufStretch_Dtor(PV_PlayBufStretch *unit);
-
-/// Computes the next FFT frame requested by the PV_PlayBufStretch UGen
-void PV_PlayBufStretch_next(PV_PlayBufStretch *unit, int inNumSamples);
-
-/// Computes a single frame of STFT data for time stretching.
-/// The assumption is that we are positioned exactly at `frame`, and we therefore
-/// just need framePrev to compute the instantaneous frequency. We also do not
-/// need to perform any magnitude or frequency interpolation.
-///
-/// \param frame The current STFT frame
-/// \param framePrev The previous STFT frame
-/// \param [out] outFrame The output STFT frame
-/// \param outFramePrev The previously computed output STFT frame
-/// \param fftSize The FFT size
-/// \param hopSize The hop size
-void Stretch2(
- const SCPolarBuf *frame,
- const SCPolarBuf *framePrev,
- SCPolarBuf *outFrame,
- const SCPolarBuf *outFramePrev,
- size_t fftSize,
- size_t hopSize);
-
-/// Computes a single frame of STFT data for time stretching.
-/// The assumption is that we are positioned exactly at `frame`, and we therefore
-/// just need framePrev to compute the instantaneous frequency. We also do not
-/// need to perform any magnitude or frequency interpolation.
-///
-/// This version uses Miller Puckette's phase locking.
-///
-/// \param frame The current STFT frame
-/// \param framePrev The previous STFT frame
-/// \param [out] outFrame The output STFT frame
-/// \param outFramePrev The previously computed output STFT frame
-/// \param fftSize The FFT size
-/// \param hopSize The hop size
-void Stretch2Puckette(
- const SCPolarBuf *frame,
- const SCPolarBuf *framePrev,
- SCPolarBuf *outFrame,
- const SCPolarBuf *outFramePrev,
- size_t fftSize,
- size_t hopSize);
-
-/// Computes a single frame of STFT data for time stretching,
-/// using the Laroche/Dolson identity phase locking scheme.
-/// The assumption is that we are positioned exactly at `frame`, and we therefore
-/// just need framePrev to compute the instantaneous frequency. We also do not
-/// need to perform any magnitude or frequency interpolation.
-///
-/// \param frame The current STFT frame
-/// \param framePrev The previous STFT frame
-/// \param [out] outFrame The output STFT frame
-/// \param outFramePrev The previously computed output STFT frame
-/// \param peakFinder The PeakFinder instance for determining peak locations in the magnitude spectrum
-/// \param fftSize The FFT size
-/// \param hopSize The hop size
-void Stretch2LarocheDolson(
- const SCPolarBuf *frame,
- const SCPolarBuf *framePrev,
- SCPolarBuf *outFrame,
- const SCPolarBuf *outFramePrev,
- PeakFinder *peakFinder,
- size_t fftSize,
- size_t hopSize);
-
-/// Computes a single frame of STFT data for time stretching.
-/// The assumption is that we are positioned between framePrev1 and frameNext.
-/// This means we will need to interpolate frequency data. So we will need to
-/// compute two frequencies for each bin, and that means we need three STFT frames.
-///
-/// \param frameNext The next STFT frame
-/// \param framePrev1 The previous STFT frame
-/// \param framePrev2 The previous STFT frame before that (required for instantaneous frequency interpolation)
-/// \param [out] outFrame The output STFT frame
-/// \param outFramePrev The previously computed output STFT frame
-/// \param pos The position between framePrev1 and frameNext (0 < pos < 1)
-/// \param fftSize The FFT size
-/// \param hopSize The hop size
-void Stretch3(
- const SCPolarBuf *frameNext,
- const SCPolarBuf *framePrev1,
- const SCPolarBuf *framePrev2,
- SCPolarBuf *outFrame,
- const SCPolarBuf *outFramePrev,
- float pos,
- size_t fftSize,
- size_t hopSize);
-
-/// Computes a single frame of STFT data for time stretching.
-/// The assumption is that we are positioned between framePrev1 and frameNext.
-/// This means we will need to interpolate frequency data. So we will need to
-/// compute two frequencies for each bin, and that means we need three STFT frames.
-///
-/// This version uses Miller Puckette's phase locking.
-///
-/// \param frameNext The next STFT frame
-/// \param framePrev1 The previous STFT frame
-/// \param framePrev2 The previous STFT frame before that (required for instantaneous frequency interpolation)
-/// \param [out] outFrame The output STFT frame
-/// \param outFramePrev The previously computed output STFT frame
-/// \param pos The position between framePrev1 and frameNext (0 < pos < 1)
-/// \param fftSize The FFT size
-/// \param hopSize The hop size
-void Stretch3Puckette(
- const SCPolarBuf *frameNext,
- const SCPolarBuf *framePrev1,
- const SCPolarBuf *framePrev2,
- SCPolarBuf *outFrame,
- const SCPolarBuf *outFramePrev,
- float pos,
- size_t fftSize,
- size_t hopSize);
-
-/// Computes a single frame of STFT data for time stretching,
-/// using the Laroche/Dolson identity phase locking scheme.
-/// The assumption is that we are positioned exactly at `frame`, and we therefore
-/// just need framePrev to compute the instantaneous frequency. We also do not
-/// need to perform any magnitude or frequency interpolation.
-///
-/// \param frameNext The next STFT frame
-/// \param framePrev1 The previous STFT frame
-/// \param framePrev2 The previous STFT frame before that (required for instantaneous frequency interpolation)
-/// \param [out] outFrame The output STFT frame
-/// \param outFramePrev The previously computed output STFT frame
-/// \param peakFinder The PeakFinder instance for determining peak locations in the magnitude spectrum
-/// \param pos The position between framePrev1 and frameNext (0 < pos < 1)
-/// \param fftSize The FFT size
-/// \param hopSize The hop size
-static void Stretch3LarocheDolson(
- const SCPolarBuf *frameNext,
- const SCPolarBuf *framePrev1,
- const SCPolarBuf *framePrev2,
- SCPolarBuf *outFrame,
- const SCPolarBuf *outFramePrev,
- PeakFinder *peakFinder,
- double pos,
- size_t fftSize,
- size_t hopSize);
-
-/// Fills a SCPolarBuf with saved STFT data from a single frame
-///
-/// \param fftBuf The FFT frame from the STFT buffer
-/// \param [out] polarBuf The SCPolarBuf to copy to
-/// \param fftSize The FFT size
-void fillPolarBuf(const float *fftBuf, SCPolarBuf *polarBuf, size_t fftSize);
-
-/// Copies data from one SCPolarBuf to another
-///
-/// \param sourceBuf The source buffer
-/// \param [out] destBuf The destination buffer
-/// \param numbins The number of bins in the SCPolarBuf (fftSize/2-1)
-void copyPolarBuf(const SCPolarBuf *sourceBuf, SCPolarBuf *destBuf, size_t numbins);
\ No newline at end of file
+namespace FlexPlugins {
+ class Peak {
+ public:
+ Peak(size_t peak);
+ Peak(size_t peak, size_t leftValley, size_t rightValley);
+ size_t peak, leftValley, rightValley;
+ };
+
+ class PeakFinder {
+ public:
+ /// Constructs the PeakFinder
+ ///
+ /// \param fftSize The FFT size
+ PeakFinder(size_t fftSize, size_t radius);
+
+ /// Finds peaks in the provided SCPolarBuf. Note that this buffer must correspond
+ /// to the original FFT size provided for the PeakFinder--otherwise memory errors may occur.
+ ///
+ /// \param buf The buffer to analyze
+ void analyze(const SCPolarBuf *buf);
+
+ /// Loads memory from the external SuperCollider allocator. Memory is allocated
+ /// using RTAlloc() and the size is specified by the memSize() method.
+ ///
+ /// \param arr The allocated memory
+ void memLoad(void *arr);
+
+ /// Gets the memory size required for the PeakFinder
+ size_t memSize() const;
+
+ /// Gets the max size of the PeakFinder
+ ///
+ /// \returns The max size
+ size_t maxSize() const;
+
+ /// Gets the current size of the PeakFinder (the number of peaks stored)
+ ///
+ /// \returns The current size
+ size_t size() const;
+
+ /// Clears the PeakFinder
+ void clear();
+
+ /// Gets a pointer to the memory that was allocated for the PeakFinder
+ /// so that it can be deallocated
+ ///
+ /// \return The memory pointer
+ void* memRetrieve();
+
+ Peak *peaks;
+ private:
+ size_t m_maxSize, m_size, m_radius;
+ size_t *m_queueL, *m_queueR;
+ };
+
+ /// Stores the state of a PV_PlayBufStretch UGen instance
+ class PV_PlayBufStretch : public SCUnit {
+ public:
+ PV_PlayBufStretch();
+ ~PV_PlayBufStretch();
+
+ private:
+ void next(int inNumSamples);
+
+ /// Computes a single frame of STFT data for time stretching.
+ /// The assumption is that we are positioned exactly at `frame`, and we therefore
+ /// just need framePrev to compute the instantaneous frequency. We also do not
+ /// need to perform any magnitude or frequency interpolation.
+ ///
+ /// \param frame The current STFT frame
+ /// \param framePrev The previous STFT frame
+ /// \param [out] outFrame The output STFT frame
+ /// \param outFramePrev The previously computed output STFT frame
+ /// \param fftSize The FFT size
+ /// \param hopSize The hop size
+ void Stretch2(
+ const SCPolarBuf *frame,
+ const SCPolarBuf *framePrev,
+ SCPolarBuf *outFrame,
+ const SCPolarBuf *outFramePrev,
+ size_t fftSize,
+ size_t hopSize);
+
+ /// Computes a single frame of STFT data for time stretching.
+ /// The assumption is that we are positioned exactly at `frame`, and we therefore
+ /// just need framePrev to compute the instantaneous frequency. We also do not
+ /// need to perform any magnitude or frequency interpolation.
+ ///
+ /// This version uses Miller Puckette's phase locking.
+ ///
+ /// \param frame The current STFT frame
+ /// \param framePrev The previous STFT frame
+ /// \param [out] outFrame The output STFT frame
+ /// \param outFramePrev The previously computed output STFT frame
+ /// \param fftSize The FFT size
+ /// \param hopSize The hop size
+ void Stretch2Puckette(
+ const SCPolarBuf *frame,
+ const SCPolarBuf *framePrev,
+ SCPolarBuf *outFrame,
+ const SCPolarBuf *outFramePrev,
+ size_t fftSize,
+ size_t hopSize);
+
+ /// Computes a single frame of STFT data for time stretching,
+ /// using the Laroche/Dolson identity phase locking scheme.
+ /// The assumption is that we are positioned exactly at `frame`, and we therefore
+ /// just need framePrev to compute the instantaneous frequency. We also do not
+ /// need to perform any magnitude or frequency interpolation.
+ ///
+ /// \param frame The current STFT frame
+ /// \param framePrev The previous STFT frame
+ /// \param [out] outFrame The output STFT frame
+ /// \param outFramePrev The previously computed output STFT frame
+ /// \param peakFinder The PeakFinder instance for determining peak locations in the magnitude spectrum
+ /// \param fftSize The FFT size
+ /// \param hopSize The hop size
+ void Stretch2LarocheDolson(
+ const SCPolarBuf *frame,
+ const SCPolarBuf *framePrev,
+ SCPolarBuf *outFrame,
+ const SCPolarBuf *outFramePrev,
+ PeakFinder *peakFinder,
+ size_t fftSize,
+ size_t hopSize);
+
+ /// Computes a single frame of STFT data for time stretching.
+ /// The assumption is that we are positioned between framePrev1 and frameNext.
+ /// This means we will need to interpolate frequency data. So we will need to
+ /// compute two frequencies for each bin, and that means we need three STFT frames.
+ ///
+ /// \param frameNext The next STFT frame
+ /// \param framePrev1 The previous STFT frame
+ /// \param framePrev2 The previous STFT frame before that (required for instantaneous frequency interpolation)
+ /// \param [out] outFrame The output STFT frame
+ /// \param outFramePrev The previously computed output STFT frame
+ /// \param pos The position between framePrev1 and frameNext (0 < pos < 1)
+ /// \param fftSize The FFT size
+ /// \param hopSize The hop size
+ void Stretch3(
+ const SCPolarBuf *frameNext,
+ const SCPolarBuf *framePrev1,
+ const SCPolarBuf *framePrev2,
+ SCPolarBuf *outFrame,
+ const SCPolarBuf *outFramePrev,
+ float pos,
+ size_t fftSize,
+ size_t hopSize);
+
+ /// Computes a single frame of STFT data for time stretching.
+ /// The assumption is that we are positioned between framePrev1 and frameNext.
+ /// This means we will need to interpolate frequency data. So we will need to
+ /// compute two frequencies for each bin, and that means we need three STFT frames.
+ ///
+ /// This version uses Miller Puckette's phase locking.
+ ///
+ /// \param frameNext The next STFT frame
+ /// \param framePrev1 The previous STFT frame
+ /// \param framePrev2 The previous STFT frame before that (required for instantaneous frequency interpolation)
+ /// \param [out] outFrame The output STFT frame
+ /// \param outFramePrev The previously computed output STFT frame
+ /// \param pos The position between framePrev1 and frameNext (0 < pos < 1)
+ /// \param fftSize The FFT size
+ /// \param hopSize The hop size
+ void Stretch3Puckette(
+ const SCPolarBuf *frameNext,
+ const SCPolarBuf *framePrev1,
+ const SCPolarBuf *framePrev2,
+ SCPolarBuf *outFrame,
+ const SCPolarBuf *outFramePrev,
+ float pos,
+ size_t fftSize,
+ size_t hopSize);
+
+ /// Computes a single frame of STFT data for time stretching,
+ /// using the Laroche/Dolson identity phase locking scheme.
+ /// The assumption is that we are positioned exactly at `frame`, and we therefore
+ /// just need framePrev to compute the instantaneous frequency. We also do not
+ /// need to perform any magnitude or frequency interpolation.
+ ///
+ /// \param frameNext The next STFT frame
+ /// \param framePrev1 The previous STFT frame
+ /// \param framePrev2 The previous STFT frame before that (required for instantaneous frequency interpolation)
+ /// \param [out] outFrame The output STFT frame
+ /// \param outFramePrev The previously computed output STFT frame
+ /// \param peakFinder The PeakFinder instance for determining peak locations in the magnitude spectrum
+ /// \param pos The position between framePrev1 and frameNext (0 < pos < 1)
+ /// \param fftSize The FFT size
+ /// \param hopSize The hop size
+ static void Stretch3LarocheDolson(
+ const SCPolarBuf *frameNext,
+ const SCPolarBuf *framePrev1,
+ const SCPolarBuf *framePrev2,
+ SCPolarBuf *outFrame,
+ const SCPolarBuf *outFramePrev,
+ PeakFinder *peakFinder,
+ double pos,
+ size_t fftSize,
+ size_t hopSize);
+
+ /// Fills a SCPolarBuf with saved STFT data from a single frame
+ ///
+ /// \param fftBuf The FFT frame from the STFT buffer
+ /// \param [out] polarBuf The SCPolarBuf to copy to
+ /// \param fftSize The FFT size
+ void fillPolarBuf(const float *fftBuf, SCPolarBuf *polarBuf, size_t fftSize);
+
+ /// Copies data from one SCPolarBuf to another
+ ///
+ /// \param sourceBuf The source buffer
+ /// \param [out] destBuf The destination buffer
+ /// \param numbins The number of bins in the SCPolarBuf (fftSize/2-1)
+ void copyPolarBuf(const SCPolarBuf *sourceBuf, SCPolarBuf *destBuf, size_t numbins);
+
+ /// The index of the buffer with STFT data
+ float m_fbufnum;
+
+ /// The buffer with STFT data
+ SndBuf *m_buf;
+
+ /// The most recent output STFT frame
+ SCPolarBuf *m_outFramePrev;
+
+ /// The next STFT frame after the current position
+ SCPolarBuf *m_frameNext;
+
+ /// The STFT frame right before the current position
+ SCPolarBuf *m_framePrev1;
+
+ /// The STFT frame two positions before the current position
+ SCPolarBuf *m_framePrev2;
+
+ /// The peak finding utility for the Laroche/Dolson stretching algorithm
+ PeakFinder *m_peakFinder;
+
+ /// Between 0 and 1; represents the start position of playback.
+ /// If it jumps during playback, playback will be restarted
+ /// at the new m_startPos.
+ float m_startPos;
+
+ /// A fractional STFT frame index. Unlike m_startPos, it corresponds to the
+ /// integer index of the current STFT frame (from 0 to M-1).
+ /// Used for interpolating position.
+ float m_pos;
+
+ /// For the first frame, we need to read phase data directly
+ /// instead of computing it.
+ bool m_firstFrame;
+ };
+}
diff --git a/src/rubberband/ringbuffer.hpp b/src/rubberband/ringbuffer.hpp
index 09f9c7d..eefca00 100644
--- a/src/rubberband/ringbuffer.hpp
+++ b/src/rubberband/ringbuffer.hpp
@@ -21,16 +21,16 @@ class RingBuffer {
void initialize(T* buffer, size_t size);
/// Determines if the buffer is ready to read `length` samples
- bool isReadReady(size_t length);
+ bool isReadReady(size_t length) const;
/// Reads a block of specified length
void readBlock(T* destination, size_t length);
/// Retrieves the size
- size_t size();
+ size_t size() const;
/// Writes a block of specified length
- void writeBlock(T* samples, size_t length);
+ void writeBlock(const T* samples, size_t length);
/// Zeros out the buffer
void zero();
@@ -60,7 +60,7 @@ void RingBuffer::initialize(T* buffer, size_t size) {
}
template
-void RingBuffer::writeBlock(T* samples, size_t length) {
+void RingBuffer::writeBlock(const T* samples, size_t length) {
if (m_buffer && m_size > 0) {
size_t startPos = m_inputPointer;
for (size_t i = 0; i < length; i++) {
@@ -90,7 +90,7 @@ void RingBuffer::readBlock(T* destination, size_t length) {
}
template
-bool RingBuffer::isReadReady(size_t length) {
+bool RingBuffer::isReadReady(size_t length) const {
if (m_newSamples >= length) {
return true;
} else {
@@ -99,7 +99,7 @@ bool RingBuffer::isReadReady(size_t length) {
}
template
-size_t RingBuffer::size() {
+size_t RingBuffer::size() const {
return m_size;
}
diff --git a/src/rubberband/rubberBandPS.cpp b/src/rubberband/rubberBandPS.cpp
index 1c9b23b..3f9c041 100644
--- a/src/rubberband/rubberBandPS.cpp
+++ b/src/rubberband/rubberBandPS.cpp
@@ -23,96 +23,107 @@ along with this program. If not, see .
*/
#include "rubberBandPS.hpp"
-#include "SC_PlugIn.h"
extern InterfaceTable *ft;
-void RubberBandPS_Ctor(RubberBandPS *unit) {
- float pitchRatio = IN0(1);
+FlexPlugins::RubberBandPS::RubberBandPS() {
+ float pitchRatio = in0(1);
// Initialize the shifter
// 0x01000000 // formant preserving
// 0x00000000 // no formant preservation
- unit->m_shifter = (RubberBand::RubberBandLiveShifter*)RTAlloc(unit->mWorld, sizeof(RubberBand::RubberBandLiveShifter));
- new (unit->m_shifter) RubberBand::RubberBandLiveShifter(static_cast(SAMPLERATE), 1, 0x01000000);
- unit->m_shifter->setPitchScale(sc_clip(pitchRatio, 1e-2, 64));
- unit->m_blockSize = BUFLENGTH;
- unit->m_shifterBlockSize = unit->m_shifter->getBlockSize();
+ m_shifter = (RubberBand::RubberBandLiveShifter*)RTAlloc(mWorld, sizeof(RubberBand::RubberBandLiveShifter));
+ new (m_shifter) RubberBand::RubberBandLiveShifter(static_cast(sampleRate()), 1, 0x01000000);
+ m_shifter->setPitchScale(sc_clip(pitchRatio, 1e-2, 64));
+ m_blockSize = fullBufferSize();
+ m_shifterBlockSize = m_shifter->getBlockSize();
// Buffers for holding the samples to feed in and out of the shifter.
// These buffers need to have the block size specified by the RubberBand shifter.
- unit->m_shiftBufferIn = (float*)RTAlloc(unit->mWorld, unit->m_shifter->getBlockSize() * sizeof(float));
- unit->m_shiftBufferOut = (float*)RTAlloc(unit->mWorld, unit->m_shifter->getBlockSize() * sizeof(float));
+ m_shiftBufferIn = (float*)RTAlloc(mWorld, m_shifter->getBlockSize() * sizeof(float));
+ m_shiftBufferOut = (float*)RTAlloc(mWorld, m_shifter->getBlockSize() * sizeof(float));
// Make the ring buffers
- unit->m_sendBuffer = (RingBuffer*)RTAlloc(unit->mWorld, sizeof(RingBuffer));
- new (unit->m_sendBuffer) RingBuffer;
- unit->m_sendBuffer->initialize(
+ m_sendBuffer = (RingBuffer*)RTAlloc(mWorld, sizeof(RingBuffer));
+ new (m_sendBuffer) RingBuffer;
+ m_sendBuffer->initialize(
(float*)RTAlloc(
- unit->mWorld,
- (BUFLENGTH + unit->m_shifter->getBlockSize()) * 3 * sizeof(float)),
- (BUFLENGTH + unit->m_shifter->getBlockSize()) * 3
+ mWorld,
+ (fullBufferSize() + m_shifter->getBlockSize()) * 3 * sizeof(float)),
+ (fullBufferSize() + m_shifter->getBlockSize()) * 3
);
- unit->m_receiveBuffer = (RingBuffer*)RTAlloc(unit->mWorld, sizeof(RingBuffer));
- new (unit->m_receiveBuffer) RingBuffer;
- unit->m_receiveBuffer->initialize(
+ m_receiveBuffer = (RingBuffer*)RTAlloc(mWorld, sizeof(RingBuffer));
+ new (m_receiveBuffer) RingBuffer;
+ m_receiveBuffer->initialize(
(float*)RTAlloc(
- unit->mWorld,
- (BUFLENGTH + unit->m_shifter->getBlockSize()) * 3 * sizeof(float)),
- (BUFLENGTH + unit->m_shifter->getBlockSize()) * 3
+ mWorld,
+ (fullBufferSize() + m_shifter->getBlockSize()) * 3 * sizeof(float)),
+ (fullBufferSize() + m_shifter->getBlockSize()) * 3
);
// Initialize output ring buffer with zeros. If there's trouble, you might need to do this twice.
- for (size_t i = 0; i < unit->m_shifter->getBlockSize(); i++) {
- unit->m_shiftBufferIn[i] = 0.f;
+ for (size_t i = 0; i < m_shifter->getBlockSize(); i++) {
+ m_shiftBufferIn[i] = 0.f;
}
- // Initialize first out sample
- OUT0(0) = 0;
-
- SETCALC(RubberBandPS_next);
+ set_calc_function();
+ next(1);
}
-void RubberBandPS_Dtor(RubberBandPS *unit) {
- RTFree(unit->mWorld, unit->m_sendBuffer->m_buffer);
- RTFree(unit->mWorld, unit->m_receiveBuffer->m_buffer);
- RTFree(unit->mWorld, unit->m_shifter);
- RTFree(unit->mWorld, unit->m_sendBuffer);
- RTFree(unit->mWorld, unit->m_receiveBuffer);
- RTFree(unit->mWorld, unit->m_shiftBufferIn);
- RTFree(unit->mWorld, unit->m_shiftBufferOut);
+FlexPlugins::RubberBandPS::~RubberBandPS() {
+ if (m_sendBuffer) {
+ if (m_sendBuffer->m_buffer) {
+ RTFree(mWorld, m_sendBuffer->m_buffer);
+ }
+ RTFree(mWorld, m_sendBuffer);
+ }
+ if (m_receiveBuffer) {
+ if (m_receiveBuffer->m_buffer) {
+ RTFree(mWorld, m_receiveBuffer->m_buffer);
+ }
+ RTFree(mWorld, m_receiveBuffer);
+ }
+ if (m_shifter) {
+ RTFree(mWorld, m_shifter);
+ }
+ if (m_shiftBufferIn) {
+ RTFree(mWorld, m_shiftBufferIn);
+ }
+ if (m_shiftBufferOut) {
+ RTFree(mWorld, m_shiftBufferOut);
+ }
}
-void RubberBandPS_next(RubberBandPS *unit, int inNumSamples) {
- float pitchRatio = IN0(1);
- float formantRatio = IN0(2);
- float* in = IN(0);
- float* out = OUT(0);
+void FlexPlugins::RubberBandPS::next(int inNumSamples) {
+ float pitchRatio = in0(1);
+ float formantRatio = in0(2);
+ const float* inBuf = in(0);
+ float* outBuf = out(0);
// Prepare the shifter, clipping the pitch and formant ratios for safety
- unit->m_shifter->setPitchScale(sc_clip(pitchRatio, 1e-2, 64));
+ m_shifter->setPitchScale(sc_clip(pitchRatio, 1e-2, 64));
if (formantRatio) {
- unit->m_shifter->setFormantScale(sc_clip(formantRatio, 1e-2, 64));
+ m_shifter->setFormantScale(sc_clip(formantRatio, 1e-2, 64));
} else {
- unit->m_shifter->setFormantScale(0.f);
+ m_shifter->setFormantScale(0.f);
}
// Feed the input into the shifter
- unit->m_sendBuffer->writeBlock(in, inNumSamples);
+ m_sendBuffer->writeBlock(inBuf, inNumSamples);
- if (unit->m_sendBuffer->isReadReady(unit->m_shifterBlockSize)) {
- unit->m_sendBuffer->readBlock(unit->m_shiftBufferIn, unit->m_shifterBlockSize);
- unit->m_shifter->shift(&(unit->m_shiftBufferIn), &(unit->m_shiftBufferOut));
- unit->m_receiveBuffer->writeBlock(unit->m_shiftBufferOut, unit->m_shifterBlockSize);
+ if (m_sendBuffer->isReadReady(m_shifterBlockSize)) {
+ m_sendBuffer->readBlock(m_shiftBufferIn, m_shifterBlockSize);
+ m_shifter->shift(&m_shiftBufferIn, &m_shiftBufferOut);
+ m_receiveBuffer->writeBlock(m_shiftBufferOut, m_shifterBlockSize);
}
// If there is a block of output samples ready, read it. (There should always be a block ready.)
- if (unit->m_receiveBuffer->isReadReady(inNumSamples)) {
- unit->m_receiveBuffer->readBlock(out, inNumSamples);
+ if (m_receiveBuffer->isReadReady(inNumSamples)) {
+ m_receiveBuffer->readBlock(outBuf, inNumSamples);
} else {
// Zero out the output buffer
for (size_t i = 0; i < inNumSamples; i++) {
- out[i] = 0.f;
+ outBuf[i] = 0.f;
}
}
}
\ No newline at end of file
diff --git a/src/rubberband/rubberBandPS.hpp b/src/rubberband/rubberBandPS.hpp
index 82024ac..b4af1ae 100644
--- a/src/rubberband/rubberBandPS.hpp
+++ b/src/rubberband/rubberBandPS.hpp
@@ -23,20 +23,24 @@ along with this program. If not, see .
*/
#pragma once
-#include "SC_Unit.h"
+#include "SC_PlugIn.hpp"
#include "rubberband/RubberBandLiveShifter.h"
#include "ringbuffer.hpp"
-struct RubberBandPS : public Unit {
- RubberBand::RubberBandLiveShifter* m_shifter;
- RingBuffer* m_sendBuffer;
- RingBuffer* m_receiveBuffer;
- float *m_shiftBufferIn;
- float *m_shiftBufferOut;
- size_t m_blockSize;
- size_t m_shifterBlockSize;
-};
-
-void RubberBandPS_Ctor(RubberBandPS *unit);
-void RubberBandPS_Dtor(RubberBandPS *unit);
-void RubberBandPS_next(RubberBandPS *unit, int inNumSamples);
\ No newline at end of file
+namespace FlexPlugins {
+ class RubberBandPS : public SCUnit {
+ public:
+ RubberBandPS();
+ ~RubberBandPS();
+
+ private:
+ void next(int inNumSamples);
+ RubberBand::RubberBandLiveShifter* m_shifter;
+ RingBuffer* m_sendBuffer;
+ RingBuffer* m_receiveBuffer;
+ float *m_shiftBufferIn;
+ float *m_shiftBufferOut;
+ size_t m_blockSize;
+ size_t m_shifterBlockSize;
+ };
+}
diff --git a/src/rubberband/rubberBandStretcher.cpp b/src/rubberband/rubberBandStretcher.cpp
index c9295dd..87019f2 100644
--- a/src/rubberband/rubberBandStretcher.cpp
+++ b/src/rubberband/rubberBandStretcher.cpp
@@ -24,29 +24,28 @@ along with this program. If not, see .
#include "rubberBandStretcher.hpp"
#include
-#include "SC_PlugIn.h"
extern InterfaceTable *ft;
-void RubberBandStretcher_Ctor(RubberBandStretcher *unit) {
- float timeRatio = IN0(1);
- float pitchRatio = IN0(2);
- float formantRatio = IN0(3);
- int transientsMode = static_cast(IN0(4));
- int detector = static_cast(IN0(5));
- int phaseOption = static_cast(IN0(6));
- int pitchQuality = static_cast(IN0(7));
- int windowOption = static_cast(IN0(8));
- int smoothing = static_cast(IN0(9));
- int engine = static_cast(IN0(10));
+FlexPlugins::RubberBandStretcher::RubberBandStretcher() {
+ float timeRatio = in0(1);
+ float pitchRatio = in0(2);
+ float formantRatio = in0(3);
+ int transientsMode = static_cast(in0(4));
+ int detector = static_cast(in0(5));
+ int phaseOption = static_cast(in0(6));
+ int pitchQuality = static_cast(in0(7));
+ int windowOption = static_cast(in0(8));
+ int smoothing = static_cast(in0(9));
+ int engine = static_cast(in0(10));
- unit->m_timeRatio = timeRatio;
- unit->m_pitchRatio = pitchRatio;
- unit->m_formantRatio = formantRatio;
- unit->m_transientsMode = transientsMode;
- unit->m_detectorOption = detector;
- unit->m_phaseOption = phaseOption;
- unit->m_pitchQuality = pitchQuality;
+ m_timeRatio = timeRatio;
+ m_pitchRatio = pitchRatio;
+ m_formantRatio = formantRatio;
+ m_transientsMode = transientsMode;
+ m_detectorOption = detector;
+ m_phaseOption = phaseOption;
+ m_pitchQuality = pitchQuality;
// Set up RubberBandStretcher initial options
int options = 0x01000001; // formant-preserving, real-time options set
@@ -98,130 +97,128 @@ void RubberBandStretcher_Ctor(RubberBandStretcher *unit) {
}
// Allocate the shifter with the given options
- unit->m_stretcher = (RubberBand::RubberBandStretcher*)RTAlloc(unit->mWorld, sizeof(RubberBand::RubberBandStretcher));
- new (unit->m_stretcher) RubberBand::RubberBandStretcher(static_cast(SAMPLERATE), 1, options, timeRatio, pitchRatio);
+ m_stretcher = (RubberBand::RubberBandStretcher*)RTAlloc(mWorld, sizeof(RubberBand::RubberBandStretcher));
+ new (m_stretcher) RubberBand::RubberBandStretcher(static_cast(sampleRate()), 1, options, timeRatio, pitchRatio);
// Initialize the shifter
// The shifter accepts a block size (which must be set before the first process()
// call and not after), which avoids the need to use local RingBuffers.
- unit->m_stretcher->setMaxProcessSize(BUFLENGTH);
- unit->m_stretcher->setTimeRatio(sc_clip(timeRatio, 1.f, std::numeric_limits::infinity()));
- unit->m_stretcher->setPitchScale(sc_clip(pitchRatio, 1e-2, 64));
- unit->m_stretcher->setFormantScale(sc_clip(formantRatio, 1e-2, 64));
+ m_stretcher->setMaxProcessSize(fullBufferSize());
+ m_stretcher->setTimeRatio(sc_clip(timeRatio, 1.f, std::numeric_limits::infinity()));
+ m_stretcher->setPitchScale(sc_clip(pitchRatio, 1e-2, 64));
+ m_stretcher->setFormantScale(sc_clip(formantRatio, 1e-2, 64));
// Feed samples in until the shifter is ready to start producing valid output.
// This is necessary because the shifter isn't ready to produce valid output
// as soon as it is initialized--it requires padded 0s to be fed in for some
// number of samples specified by the shifter.
- float *zeroBuf = (float*)RTAlloc(unit->mWorld, BUFLENGTH * sizeof(float));
- for (size_t i = 0; i < BUFLENGTH; i++) {
+ float *zeroBuf = (float*)RTAlloc(mWorld, fullBufferSize() * sizeof(float));
+ for (size_t i = 0; i < fullBufferSize(); i++) {
zeroBuf[i] = 0.f;
}
// The number of initial zeros required
- size_t startPad = unit->m_stretcher->getPreferredStartPad();
+ size_t startPad = m_stretcher->getPreferredStartPad();
// The number of samples to discard at the beginning of the stretcher output.
// This is handled in the RubberBandStretcher_next() method.
- unit->m_samplesToDiscard = unit->m_stretcher->getStartDelay();
+ m_samplesToDiscard = m_stretcher->getStartDelay();
// Feed in the start pad samples
while (startPad > 0) {
- unit->m_stretcher->process(&zeroBuf, BUFLENGTH, false);
- startPad -= BUFLENGTH;
+ m_stretcher->process(&zeroBuf, fullBufferSize(), false);
+ startPad -= fullBufferSize();
}
- RTFree(unit->mWorld, zeroBuf);
+ RTFree(mWorld, zeroBuf);
- // Initialize first out sample
- OUT0(0) = 0;
-
- SETCALC(RubberBandStretcher_next);
+ set_calc_function();
+ next(1);
}
-void RubberBandStretcher_Dtor(RubberBandStretcher *unit) {
- RTFree(unit->mWorld, unit->m_stretcher);
+FlexPlugins::RubberBandStretcher::~RubberBandStretcher() {
+ if (m_stretcher) RTFree(mWorld, m_stretcher);
}
-void RubberBandStretcher_next(RubberBandStretcher *unit, int inNumSamples) {
- float *in = IN(0);
- float *out = OUT(0);
- float timeRatio = IN0(1);
- float pitchRatio = IN0(2);
- float formantRatio = IN0(3);
- int transientsMode = static_cast(IN0(4));
- int detector = static_cast(IN0(5));
- int phaseOption = static_cast(IN0(6));
- int pitchQuality = static_cast(IN0(7));
+void FlexPlugins::RubberBandStretcher::next(int inNumSamples) {
+ const float *inBuf = in(0);
+ float *outBuf = out(0);
+ float timeRatio = in0(1);
+ float pitchRatio = in0(2);
+ float formantRatio = in0(3);
+ int transientsMode = static_cast(in0(4));
+ int detector = static_cast(in0(5));
+ int phaseOption = static_cast(in0(6));
+ int pitchQuality = static_cast(in0(7));
// Update shifter options only if something has changed
- if (timeRatio != unit->m_timeRatio) {
- unit->m_stretcher->setTimeRatio(sc_clip(timeRatio, 1.f, std::numeric_limits::infinity()));
+ if (timeRatio != m_timeRatio) {
+ m_stretcher->setTimeRatio(sc_clip(timeRatio, 1.f, std::numeric_limits::infinity()));
}
- if (pitchRatio != unit->m_pitchRatio) {
- unit->m_stretcher->setPitchScale(sc_clip(pitchRatio, 1e-2, 64));
+ if (pitchRatio != m_pitchRatio) {
+ m_stretcher->setPitchScale(sc_clip(pitchRatio, 1e-2, 64));
}
- if (formantRatio != unit->m_formantRatio) {
- unit->m_stretcher->setFormantScale(sc_clip(formantRatio, 1e-2, 64));
+ if (formantRatio != m_formantRatio) {
+ m_stretcher->setFormantScale(sc_clip(formantRatio, 1e-2, 64));
}
// QUESTION: Will this method of setting options override all existing options,
// or just the option provided? May need to compute all options from scratch.
- if (transientsMode != unit->m_transientsMode) {
+ if (transientsMode != m_transientsMode) {
switch (transientsMode) {
case 1:
- unit->m_stretcher->setTransientsOption(0x00000100);
+ m_stretcher->setTransientsOption(0x00000100);
break;
case 2:
- unit->m_stretcher->setTransientsOption(0x00000200);
+ m_stretcher->setTransientsOption(0x00000200);
break;
default:
- unit->m_stretcher->setTransientsOption(0x00000000);
+ m_stretcher->setTransientsOption(0x00000000);
}
}
- if (detector != unit->m_detectorOption) {
+ if (detector != m_detectorOption) {
switch (detector) {
case 1:
- unit->m_stretcher->setDetectorOption(0x00000400);
+ m_stretcher->setDetectorOption(0x00000400);
break;
case 2:
- unit->m_stretcher->setDetectorOption(0x00000800);
+ m_stretcher->setDetectorOption(0x00000800);
break;
default:
- unit->m_stretcher->setDetectorOption(0x00000000);
+ m_stretcher->setDetectorOption(0x00000000);
}
}
- if (phaseOption != unit->m_phaseOption) {
+ if (phaseOption != m_phaseOption) {
switch (phaseOption) {
case 1:
- unit->m_stretcher->setPhaseOption(0x00002000);
+ m_stretcher->setPhaseOption(0x00002000);
break;
default:
- unit->m_stretcher->setPhaseOption(0x00000000);
+ m_stretcher->setPhaseOption(0x00000000);
}
}
- if (pitchQuality != unit->m_pitchQuality) {
+ if (pitchQuality != m_pitchQuality) {
switch (pitchQuality) {
case 1:
- unit->m_stretcher->setPitchOption(0x02000000);
+ m_stretcher->setPitchOption(0x02000000);
break;
case 2:
- unit->m_stretcher->setPitchOption(0x04000000);
+ m_stretcher->setPitchOption(0x04000000);
break;
default:
- unit->m_stretcher->setPitchOption(0x00000000);
+ m_stretcher->setPitchOption(0x00000000);
}
}
- unit->m_stretcher->process(&in, BUFLENGTH, false);
+ m_stretcher->process(&inBuf, inNumSamples, false);
// If we can retrieve a full block worth of audio
- if (unit->m_stretcher->available() >= BUFLENGTH) {
- unit->m_stretcher->retrieve(&out, BUFLENGTH);
+ if (m_stretcher->available() >= inNumSamples) {
+ m_stretcher->retrieve(&outBuf, inNumSamples);
// Clear initial samples if necessary
- if (unit->m_samplesToDiscard > 0) {
+ if (m_samplesToDiscard > 0) {
size_t i = 0;
- while (i < BUFLENGTH && unit->m_samplesToDiscard > 0) {
- out[i] = 0.f;
- unit->m_samplesToDiscard--;
+ while (i < inNumSamples && m_samplesToDiscard > 0) {
+ outBuf[i] = 0.f;
+ m_samplesToDiscard--;
i++;
}
}
@@ -229,8 +226,6 @@ void RubberBandStretcher_next(RubberBandStretcher *unit, int inNumSamples) {
// Output zeros if the shifter has no new samples available
else {
- for (size_t i = 0; i < BUFLENGTH; i++) {
- out[i] = 0.f;
- }
+ ClearUnitOutputs(this, inNumSamples);
}
}
diff --git a/src/rubberband/rubberBandStretcher.hpp b/src/rubberband/rubberBandStretcher.hpp
index 31b3302..690ad55 100644
--- a/src/rubberband/rubberBandStretcher.hpp
+++ b/src/rubberband/rubberBandStretcher.hpp
@@ -23,26 +23,31 @@ along with this program. If not, see .
*/
#pragma once
-#include "SC_Unit.h"
+#include "SC_PlugIn.hpp"
#include "rubberband/RubberBandStretcher.h"
-struct RubberBandStretcher : public Unit {
- /// The stretcher
- RubberBand::RubberBandStretcher* m_stretcher;
-
- /// The number of initial output samples to discard
- size_t m_samplesToDiscard;
-
- // A collection of settings for the RubberBand stretcher
- float m_timeRatio;
- float m_pitchRatio;
- float m_formantRatio;
- int m_transientsMode;
- int m_detectorOption;
- int m_phaseOption;
- int m_pitchQuality;
-};
-
-void RubberBandStretcher_Ctor(RubberBandStretcher *unit);
-void RubberBandStretcher_Dtor(RubberBandStretcher *unit);
-void RubberBandStretcher_next(RubberBandStretcher *unit, int inNumSamples);
\ No newline at end of file
+namespace FlexPlugins {
+ class RubberBandStretcher : public SCUnit {
+ public:
+ RubberBandStretcher();
+ ~RubberBandStretcher();
+
+ private:
+ void next(int inNumSamples);
+
+ /// The stretcher
+ RubberBand::RubberBandStretcher* m_stretcher;
+
+ /// The number of initial output samples to discard
+ size_t m_samplesToDiscard;
+
+ // A collection of settings for the RubberBand stretcher
+ float m_timeRatio;
+ float m_pitchRatio;
+ float m_formantRatio;
+ int m_transientsMode;
+ int m_detectorOption;
+ int m_phaseOption;
+ int m_pitchQuality;
+ };
+}
diff --git a/src/rubberband/rubberBandStretcherBuf.cpp b/src/rubberband/rubberBandStretcherBuf.cpp
index 8445966..cabe67c 100644
--- a/src/rubberband/rubberBandStretcherBuf.cpp
+++ b/src/rubberband/rubberBandStretcherBuf.cpp
@@ -24,38 +24,37 @@ along with this program. If not, see .
#include "rubberBandStretcherBuf.hpp"
#include
-#include "SC_PlugIn.h"
extern InterfaceTable *ft;
-void RubberBandStretcherBuf_Ctor(RubberBandStretcherBuf *unit) {
- float timeRatio = IN0(8);
- float pitchRatio = IN0(9);
- float formantRatio = IN0(10);
- int transientsMode = static_cast(IN0(11));
- int detector = static_cast(IN0(12));
- int phaseOption = static_cast(IN0(13));
- int pitchQuality = static_cast(IN0(14));
- int windowOption = static_cast(IN0(15));
- int smoothing = static_cast(IN0(16));
- int engine = static_cast(IN0(17));
+FlexPlugins::RubberBandStretcherBuf::RubberBandStretcherBuf() {
+ float timeRatio = in0(8);
+ float pitchRatio = in0(9);
+ float formantRatio = in0(10);
+ int transientsMode = static_cast(in0(11));
+ int detector = static_cast(in0(12));
+ int phaseOption = static_cast(in0(13));
+ int pitchQuality = static_cast(in0(14));
+ int windowOption = static_cast(in0(15));
+ int smoothing = static_cast(in0(16));
+ int engine = static_cast(in0(17));
- unit->m_timeRatio = timeRatio;
- unit->m_pitchRatio = pitchRatio;
- unit->m_formantRatio = formantRatio;
- unit->m_transientsMode = transientsMode;
- unit->m_detectorOption = detector;
- unit->m_phaseOption = phaseOption;
- unit->m_pitchQuality = pitchQuality;
+ m_timeRatio = timeRatio;
+ m_pitchRatio = pitchRatio;
+ m_formantRatio = formantRatio;
+ m_transientsMode = transientsMode;
+ m_detectorOption = detector;
+ m_phaseOption = phaseOption;
+ m_pitchQuality = pitchQuality;
// Acquire the sound buffer
- float fbufnum = IN0(1);
+ float fbufnum = in0(1);
uint32 bufnum = static_cast(fbufnum);
- if (bufnum >= unit->mWorld->mNumSndBufs) bufnum = 0;
- unit->m_fbufnum = fbufnum;
- unit->m_buf = unit->mWorld->mSndBufs + bufnum;
- unit->m_writePtr = static_cast(IN0(2)); // initial offset
- unit->m_prevTrigger = 0.f;
+ if (bufnum >= mWorld->mNumSndBufs) bufnum = 0;
+ m_fbufnum = fbufnum;
+ m_buf = mWorld->mSndBufs + bufnum;
+ m_writePtr = static_cast(in0(2)); // initial offset
+ m_prevTrigger = 0.f;
// Set up RubberBandStretcher initial options
int options = 0x01000001; // formant-preserving, real-time options set
@@ -107,56 +106,55 @@ void RubberBandStretcherBuf_Ctor(RubberBandStretcherBuf *unit) {
}
// Allocate the shifter with the given options
- unit->m_stretcher = (RubberBand::RubberBandStretcher*)RTAlloc(unit->mWorld, sizeof(RubberBand::RubberBandStretcher));
- new (unit->m_stretcher) RubberBand::RubberBandStretcher(static_cast(SAMPLERATE), 1, options, timeRatio, pitchRatio);
+ m_stretcher = (RubberBand::RubberBandStretcher*)RTAlloc(mWorld, sizeof(RubberBand::RubberBandStretcher));
+ new (m_stretcher) RubberBand::RubberBandStretcher(static_cast(sampleRate()), 1, options, timeRatio, pitchRatio);
// Initialize the shifter
// The shifter accepts a block size (which must be set before the first process()
// call and not after), which avoids the need to use local RingBuffers.
- unit->m_stretcher->setMaxProcessSize(BUFLENGTH);
- unit->m_stretcher->setTimeRatio(sc_clip(timeRatio, 1e-5, 1e5));
- unit->m_stretcher->setPitchScale(sc_clip(pitchRatio, 1e-2, 64));
- unit->m_stretcher->setFormantScale(sc_clip(formantRatio, 1e-2, 64));
+ m_stretcher->setMaxProcessSize(fullBufferSize());
+ m_stretcher->setTimeRatio(sc_clip(timeRatio, 1e-5, 1e5));
+ m_stretcher->setPitchScale(sc_clip(pitchRatio, 1e-2, 64));
+ m_stretcher->setFormantScale(sc_clip(formantRatio, 1e-2, 64));
// Feed samples in until the shifter is ready to start producing valid output.
// This is necessary because the shifter isn't ready to produce valid output
// as soon as it is initialized--it requires padded 0s to be fed in for some
// number of samples specified by the shifter.
- unit->m_localBuf = (float*)RTAlloc(unit->mWorld, BUFLENGTH * sizeof(float));
- for (size_t i = 0; i < BUFLENGTH; i++) {
- unit->m_localBuf[i] = 0.f;
+ m_localBuf = (float*)RTAlloc(mWorld, fullBufferSize() * sizeof(float));
+ for (size_t i = 0; i < fullBufferSize(); i++) {
+ m_localBuf[i] = 0.f;
}
// The number of initial zeros required
- size_t startPad = unit->m_stretcher->getPreferredStartPad();
+ size_t startPad = m_stretcher->getPreferredStartPad();
// The number of samples to discard at the beginning of the stretcher output.
// This is handled in the RubberBandStretcher_next() method.
- unit->m_samplesToDiscard = unit->m_stretcher->getStartDelay();
+ m_samplesToDiscard = m_stretcher->getStartDelay();
// Feed in the start pad samples
while (startPad > 0) {
- unit->m_stretcher->process(&unit->m_localBuf, BUFLENGTH, false);
- startPad -= BUFLENGTH;
+ m_stretcher->process(&m_localBuf, fullBufferSize(), false);
+ startPad -= fullBufferSize();
}
// Initialize first out sample
- OUT0(0) = 0;
-
- SETCALC(RubberBandStretcherBuf_next);
+ set_calc_function();
+ next(1);
}
-void RubberBandStretcherBuf_Dtor(RubberBandStretcherBuf *unit) {
- if (unit->m_stretcher) RTFree(unit->mWorld, unit->m_stretcher);
- if (unit->m_localBuf) RTFree(unit->mWorld, unit->m_localBuf);
+FlexPlugins::RubberBandStretcherBuf::~RubberBandStretcherBuf() {
+ if (m_stretcher) RTFree(mWorld, m_stretcher);
+ if (m_localBuf) RTFree(mWorld, m_localBuf);
}
-void RubberBandStretcherBuf_next(RubberBandStretcherBuf *unit, int inNumSamples) {
+void FlexPlugins::RubberBandStretcherBuf::next(int inNumSamples) {
// Step 1: acquire the sound buffer
- const SndBuf *writeBuf = unit->m_buf;
+ const SndBuf *writeBuf = m_buf;
if (!writeBuf) {
std::cout << "WARNING: The stftBuffer could not be accessed. Aborting.\n";
- ClearUnitOutputs(unit, inNumSamples);
+ ClearUnitOutputs(this, inNumSamples);
return;
}
ACQUIRE_SNDBUF_SHARED(writeBuf);
@@ -168,116 +166,122 @@ void RubberBandStretcherBuf_next(RubberBandStretcherBuf *unit, int inNumSamples)
if (bufChannels != 1) {
std::cout << "WARNING: The buffer has " << bufChannels << " channels, but the " <<
"RubberBandStretcherBuf only supports mono buffers. Aborting.\n";
- ClearUnitOutputs(unit, inNumSamples);
+ ClearUnitOutputs(this, inNumSamples);
RELEASE_SNDBUF_SHARED(writeBuf);
return;
}
// 2. Update unit parameters if required
- float timeRatio = IN0(8);
- float pitchRatio = IN0(9);
- float formantRatio = IN0(10);
- int transientsMode = static_cast(IN0(11));
- int detector = static_cast(IN0(12));
- int phaseOption = static_cast(IN0(13));
- int pitchQuality = static_cast(IN0(14));
+ float timeRatio = in0(8);
+ float pitchRatio = in0(9);
+ float formantRatio = in0(10);
+ int transientsMode = static_cast(in0(11));
+ int detector = static_cast(in0(12));
+ int phaseOption = static_cast(in0(13));
+ int pitchQuality = static_cast(in0(14));
// Update shifter options only if something has changed
- if (timeRatio != unit->m_timeRatio) {
- unit->m_stretcher->setTimeRatio(sc_clip(timeRatio, 1e-5, 1e5));
+ if (timeRatio != m_timeRatio) {
+ m_stretcher->setTimeRatio(sc_clip(timeRatio, 1e-5, 1e5));
}
- if (pitchRatio != unit->m_pitchRatio) {
- unit->m_stretcher->setPitchScale(sc_clip(pitchRatio, 1e-2, 64));
+ if (pitchRatio != m_pitchRatio) {
+ m_stretcher->setPitchScale(sc_clip(pitchRatio, 1e-2, 64));
}
- if (formantRatio != unit->m_formantRatio) {
- unit->m_stretcher->setFormantScale(sc_clip(formantRatio, 1e-2, 64));
+ if (formantRatio != m_formantRatio) {
+ m_stretcher->setFormantScale(sc_clip(formantRatio, 1e-2, 64));
}
// QUESTION: Will this method of setting options override all existing options,
// or just the option provided? May need to compute all options from scratch.
- if (transientsMode != unit->m_transientsMode) {
+ if (transientsMode != m_transientsMode) {
switch (transientsMode) {
case 1:
- unit->m_stretcher->setTransientsOption(0x00000100);
+ m_stretcher->setTransientsOption(0x00000100);
break;
case 2:
- unit->m_stretcher->setTransientsOption(0x00000200);
+ m_stretcher->setTransientsOption(0x00000200);
break;
default:
- unit->m_stretcher->setTransientsOption(0x00000000);
+ m_stretcher->setTransientsOption(0x00000000);
}
}
- if (detector != unit->m_detectorOption) {
+ if (detector != m_detectorOption) {
switch (detector) {
case 1:
- unit->m_stretcher->setDetectorOption(0x00000400);
+ m_stretcher->setDetectorOption(0x00000400);
break;
case 2:
- unit->m_stretcher->setDetectorOption(0x00000800);
+ m_stretcher->setDetectorOption(0x00000800);
break;
default:
- unit->m_stretcher->setDetectorOption(0x00000000);
+ m_stretcher->setDetectorOption(0x00000000);
}
}
- if (phaseOption != unit->m_phaseOption) {
+ if (phaseOption != m_phaseOption) {
switch (phaseOption) {
case 1:
- unit->m_stretcher->setPhaseOption(0x00002000);
+ m_stretcher->setPhaseOption(0x00002000);
break;
default:
- unit->m_stretcher->setPhaseOption(0x00000000);
+ m_stretcher->setPhaseOption(0x00000000);
}
}
- if (pitchQuality != unit->m_pitchQuality) {
+ if (pitchQuality != m_pitchQuality) {
switch (pitchQuality) {
case 1:
- unit->m_stretcher->setPitchOption(0x02000000);
+ m_stretcher->setPitchOption(0x02000000);
break;
case 2:
- unit->m_stretcher->setPitchOption(0x04000000);
+ m_stretcher->setPitchOption(0x04000000);
break;
default:
- unit->m_stretcher->setPitchOption(0x00000000);
+ m_stretcher->setPitchOption(0x00000000);
}
}
// 3. Handle the trigger functionality
- float trigger = IN0(7);
- if (trigger > 0.f && unit->m_prevTrigger <= 0.f) {
- unit->m_writePtr = 0;
+ float trigger = in0(7);
+ if (trigger > 0.f && m_prevTrigger <= 0.f) {
+ m_writePtr = 0;
}
- unit->m_prevTrigger = trigger;
+ m_prevTrigger = trigger;
// 4. Process input audio.
- float *in = IN(0);
- float recLevel = IN0(3);
- float preLevel = IN0(4);
- float loop = IN0(6);
+ const float *inBuf = in(0);
+ float recLevel = in0(3);
+ float preLevel = in0(4);
+ float loop = in0(6);
- unit->m_stretcher->process(&in, BUFLENGTH, false);
+ m_stretcher->process(&inBuf, inNumSamples, false);
- while (unit->m_stretcher->available() > 0) {
- size_t numRetrieve = static_cast(std::min(BUFLENGTH, unit->m_stretcher->available()));
- unit->m_stretcher->retrieve(&unit->m_localBuf, numRetrieve);
+ while (m_stretcher->available() > 0) {
+ size_t numRetrieve = static_cast(std::min(inNumSamples, m_stretcher->available()));
+ m_stretcher->retrieve(&m_localBuf, numRetrieve);
// 5. While we run the audio through the stretcher regardless, we only store it to the buffer if "run" is set.
- if (IN0(5) > 0.f) {
- for (size_t xxi = 0; xxi < numRetrieve; xxi++) {
- if (unit->m_writePtr >= bufSamples) {
+ if (in0(5) > 0.f) {
+ for (size_t i = 0; i < numRetrieve; i++) {
+ if (m_writePtr >= bufSamples) {
if (loop > 0.f) {
- unit->m_writePtr = 0;
+ m_writePtr = 0;
} else {
RELEASE_SNDBUF_SHARED(writeBuf);
- ClearUnitOutputs(unit, inNumSamples);
- DoneAction(static_cast(IN0(18)), unit);
+ ClearUnitOutputs(this, inNumSamples);
+ DoneAction(static_cast(in0(18)), this);
return;
}
}
- bufData[unit->m_writePtr] = preLevel * bufData[unit->m_writePtr] + recLevel * unit->m_localBuf[xxi];
- unit->m_writePtr++;
+ // We need to ignore the initial samples output by the stretcher
+ if (m_samplesToDiscard > 0) {
+ m_samplesToDiscard--;
+ } else {
+ bufData[m_writePtr] = preLevel * bufData[m_writePtr] + recLevel * m_localBuf[i];
+ }
+
+ m_writePtr++;
}
}
}
- ClearUnitOutputs(unit, inNumSamples);
+ ClearUnitOutputs(this, inNumSamples);
RELEASE_SNDBUF_SHARED(writeBuf);
}
\ No newline at end of file
diff --git a/src/rubberband/rubberBandStretcherBuf.hpp b/src/rubberband/rubberBandStretcherBuf.hpp
index 6148b34..909bbd6 100644
--- a/src/rubberband/rubberBandStretcherBuf.hpp
+++ b/src/rubberband/rubberBandStretcherBuf.hpp
@@ -24,41 +24,45 @@ along with this program. If not, see .
#pragma once
-#include "SC_Unit.h"
+#include "SC_PlugIn.hpp"
#include "rubberband/RubberBandStretcher.h"
-struct RubberBandStretcherBuf : public Unit {
- /// The stretcher
- RubberBand::RubberBandStretcher* m_stretcher;
-
- /// A buffer
- float *m_localBuf;
-
- /// The number of initial output samples to discard
- size_t m_samplesToDiscard;
-
- // A collection of settings for the RubberBand stretcher
- float m_timeRatio;
- float m_pitchRatio;
- float m_formantRatio;
- int m_transientsMode;
- int m_detectorOption;
- int m_phaseOption;
- int m_pitchQuality;
-
- /// The index of the buffer with STFT data
- float m_fbufnum;
-
- /// The audio buffer to write the stretched audio to
- SndBuf *m_buf;
-
- /// The next sample to write to
- size_t m_writePtr;
-
- /// The previous trigger
- float m_prevTrigger;
-};
-
-void RubberBandStretcherBuf_Ctor(RubberBandStretcherBuf *unit);
-void RubberBandStretcherBuf_Dtor(RubberBandStretcherBuf *unit);
-void RubberBandStretcherBuf_next(RubberBandStretcherBuf *unit, int inNumSamples);
\ No newline at end of file
+namespace FlexPlugins {
+ class RubberBandStretcherBuf : public SCUnit {
+ public:
+ RubberBandStretcherBuf();
+ ~RubberBandStretcherBuf();
+
+ private:
+ void next(int inNumSamples);
+ /// The stretcher
+ RubberBand::RubberBandStretcher* m_stretcher;
+
+ /// A buffer
+ float *m_localBuf;
+
+ /// The number of initial output samples to discard
+ size_t m_samplesToDiscard;
+
+ // A collection of settings for the RubberBand stretcher
+ float m_timeRatio;
+ float m_pitchRatio;
+ float m_formantRatio;
+ int m_transientsMode;
+ int m_detectorOption;
+ int m_phaseOption;
+ int m_pitchQuality;
+
+ /// The index of the buffer with STFT data
+ float m_fbufnum;
+
+ /// The audio buffer to write the stretched audio to
+ SndBuf *m_buf;
+
+ /// The next sample to write to
+ size_t m_writePtr;
+
+ /// The previous trigger
+ float m_prevTrigger;
+ };
+}
diff --git a/src/rubberband/rubberband.cpp b/src/rubberband/rubberband.cpp
index 51fc551..5ec7b6c 100644
--- a/src/rubberband/rubberband.cpp
+++ b/src/rubberband/rubberband.cpp
@@ -22,7 +22,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-#include "SC_PlugIn.h"
#include "rubberBandPS.hpp"
#include "rubberBandStretcher.hpp"
#include "rubberBandStretcherBuf.hpp"
@@ -31,7 +30,7 @@ InterfaceTable *ft;
PluginLoad(RubberBandPlugins) {
ft = inTable;
- DefineDtorUnit(RubberBandPS);
- DefineDtorUnit(RubberBandStretcher);
- DefineDtorUnit(RubberBandStretcherBuf);
+ registerUnit(ft, "RubberBandPS", false);
+ registerUnit(ft, "RubberBandStretcher", false);
+ registerUnit(ft, "RubberBandStretcherBuf", false);
}