diff --git a/README.md b/README.md
index 45c662c..0d17d69 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,9 @@ A phase vocoder pitch shifter and time stretcher using the [RubberBand library](
### RubberBandStretcherBuf
A phase vocoder pitch shifter and time stretcher using the [RubberBand library](https://breakfastquay.com/rubberband/). This version writes the stretched audio to a buffer rather than outputting it directly.
+### FIR
+A flexible FIR filter that allows you to provide an arbitrary number of coefficients directly (as opposed to loading them in a buffer with Convolution3).
+
### ImpulseDropout
A modified version of Impulse that randomly drops a percentage of impulses, producing a stuttering effect.
diff --git a/src/filters/FIR.schelp b/src/filters/FIR.schelp
index 0e25110..b794d16 100644
--- a/src/filters/FIR.schelp
+++ b/src/filters/FIR.schelp
@@ -4,18 +4,26 @@ related:: Classes/Convolution3, Classes/FOS, Classes/SOS, Classes/OneZero
categories:: Libraries>FlexUGens, UGens>Filters>Linear
Description::
-A no-nonsense FIR filter where you provide your own coefficients. FIR duplicates the functionality
+A flexible time-domain FIR filter where you provide your own coefficients. FIR duplicates the functionality
of link::Classes/Convolution3::. The difference is that FIR does not require you to load your
filter coefficients into a link::Classes/Buffer::. Instead, you can provide them directly as a
link::Classes/Ref:: in the same way as is done in link::Classes/DynKlank::.
+FIR internally limits the number of coefficients to 32. This is because time-domain convolution only makes sense for
+very short impulse responses--Frank Wefers writes that "the
+theoretical break-even point where FFT-based convolution becomes
+faster is between 16-32 samples."footnote::Frank Wefers, "Partitioned convolution algorithms
+for real-time auralization," Logos Verlag Berlin (2015), 224.:: One potential use of this UGen is
+to perform Savitsky-Golay filtering for control signal smoothing
+(see link::https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter:: for coefficient tables).
+
classmethods::
-method::ar
+method::ar, kr
argument::coefs
A link::Classes/Ref:: to a list of FIR filter coefficients. The number of coefficients can change
-over time, but can never exceed the server block size (if it does, extra coefficients will be truncated).
+over time, but can never exceed 32 (if it does, extra coefficients will be truncated).
argument::in
The input signal to filter
diff --git a/src/filters/filters.sc b/src/filters/filters.sc
index d0038bc..dcd0de5 100644
--- a/src/filters/filters.sc
+++ b/src/filters/filters.sc
@@ -20,6 +20,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+// A flexible FIR filter
FIR : UGen {
*ar {
arg coefs, in, mul=1, add=0;
diff --git a/src/filters/fir.cpp b/src/filters/fir.cpp
index 73f5a0c..a0cd847 100644
--- a/src/filters/fir.cpp
+++ b/src/filters/fir.cpp
@@ -3,7 +3,7 @@ File: fir.cpp
Author: Jeff Martin
Description:
-A raw FIR filter
+A flexible FIR filter
Copyright © 2026 by Jeffrey Martin. All rights reserved.
Website: https://www.jeffreymartincomposer.com
@@ -26,8 +26,8 @@ along with this program. If not, see .
extern InterfaceTable *ft;
FlexPlugins::FIR::FIR() {
- m_z = static_cast(RTAlloc(mWorld, fullBufferSize() * sizeof(float)));
- for (size_t i = 0; i < fullBufferSize(); i++) {
+ m_z = static_cast(RTAlloc(mWorld, MAX_COEFS * sizeof(float)));
+ for (size_t i = 0; i < MAX_COEFS; i++) {
m_z[i] = 0.f;
}
set_calc_function();
@@ -40,13 +40,13 @@ FlexPlugins::FIR::~FIR() {
void FlexPlugins::FIR::next(int inNumSamples) {
size_t numCoefs = static_cast(mNumInputs - 1);
- numCoefs = sc_clip(numCoefs, 0, static_cast(fullBufferSize()));
+ numCoefs = sc_clip(numCoefs, 0, static_cast(MAX_COEFS));
const float *inBuf = in(0);
float *outBuf = out(0);
for (size_t i = 0; i < inNumSamples; i++) {
float convResult = 0.f;
// unit delay
- for (size_t j = fullBufferSize() - 1; j > 0; j--) {
+ for (size_t j = MAX_COEFS - 1; j > 0; j--) {
m_z[j] = m_z[j-1];
}
m_z[0] = inBuf[i];
diff --git a/src/filters/fir.hpp b/src/filters/fir.hpp
index 552caef..e32d5f6 100644
--- a/src/filters/fir.hpp
+++ b/src/filters/fir.hpp
@@ -3,7 +3,7 @@ File: fir.hpp
Author: Jeff Martin
Description:
-A raw FIR filter
+A flexible FIR filter
Copyright © 2026 by Jeffrey Martin. All rights reserved.
Website: https://www.jeffreymartincomposer.com
@@ -26,6 +26,8 @@ along with this program. If not, see .
#include "SC_PlugIn.hpp"
+#define MAX_COEFS 32
+
namespace FlexPlugins {
class FIR : public SCUnit {
public:
diff --git a/src/generators/ImpulseJitter.schelp b/src/generators/ImpulseJitter.schelp
index e1ad49e..891b5d8 100644
--- a/src/generators/ImpulseJitter.schelp
+++ b/src/generators/ImpulseJitter.schelp
@@ -32,17 +32,19 @@ This value will be added to the output.
Examples::
+Generating audio:
code::
-(
-SynthDef(\jitter, {
- arg freq, jitterFrac, amp;
- var sig;
- sig = ImpulseJitter.ar(freq, 0.0, jitterFrac, amp);
- sig = LPF.ar(sig, freq);
- sig = LeakDC.ar(sig);
- Out.ar(0, sig);
-}).add;
-
-Synth(\jitter, [\freq, 440.0, \jitterFrac, 0.1, \amp, -12.dbamp]);
-)
+{
+ var sig;
+ sig = ImpulseJitter.ar(440, 0, XLine.kr(1, 2, 5)-1);
+ Pan2.ar(sig);
+}.play;
+::
+
+An increasingly noisy impulse train as a control signal:
+code::
+{
+ var sig;
+ sig = ImpulseJitter.kr(10, 0, XLine.kr(1, 2, 2) - 1);
+}.plot(2);
::
\ No newline at end of file
diff --git a/src/generators/arrayheap.cpp b/src/generators/arrayheap.cpp
index 4c337e0..67ed397 100644
--- a/src/generators/arrayheap.cpp
+++ b/src/generators/arrayheap.cpp
@@ -25,7 +25,7 @@ along with this program. If not, see .
#include "arrayheap.hpp"
// Inserts into the heap
-int heapInsert(IntMinHeap* heap, int data) {
+int FlexPlugins::heapInsert(IntMinHeap* heap, int data) {
if (heap->size == heap->maxSize) {
return 0;
} else {
@@ -54,7 +54,7 @@ int heapInsert(IntMinHeap* heap, int data) {
}
// Removes from the heap and returns the value popped. Returns 0 if the heap is empty.
-int heapPop(IntMinHeap* heap) {
+int FlexPlugins::heapPop(IntMinHeap* heap) {
if (heap->size > 1) {
int val = heap->heap[1];
heap->heap[1] = heap->heap[heap->size-1];
@@ -97,7 +97,7 @@ int heapPop(IntMinHeap* heap) {
}
// Safe peek at the top of the heap
-int heapPeek(IntMinHeap* heap) {
+int FlexPlugins::heapPeek(IntMinHeap* heap) {
if (heap->size > 1) {
return heap->heap[1];
} else {
diff --git a/src/generators/arrayheap.hpp b/src/generators/arrayheap.hpp
index c21d879..632d698 100644
--- a/src/generators/arrayheap.hpp
+++ b/src/generators/arrayheap.hpp
@@ -25,18 +25,20 @@ along with this program. If not, see .
#pragma once
#include
-/// A min heap for ints.
-typedef struct {
- int* heap;
- size_t size;
- size_t maxSize;
-} IntMinHeap;
-
-/// Inserts into the heap
-int heapInsert(IntMinHeap* heap, int data);
-
-/// Removes from the heap and returns the value popped. Returns 0 if the heap is empty.
-int heapPop(IntMinHeap* heap);
-
-/// Safe peek at the top of the heap
-int heapPeek(IntMinHeap* heap);
\ No newline at end of file
+namespace FlexPlugins {
+ /// A min heap for ints.
+ typedef struct {
+ int* heap;
+ size_t size;
+ size_t maxSize;
+ } IntMinHeap;
+
+ /// Inserts into the heap
+ int heapInsert(IntMinHeap* heap, int data);
+
+ /// Removes from the heap and returns the value popped. Returns 0 if the heap is empty.
+ int heapPop(IntMinHeap* heap);
+
+ /// Safe peek at the top of the heap
+ int heapPeek(IntMinHeap* heap);
+}
diff --git a/src/pv/pvCFreeze.cpp b/src/pv/pvCFreeze.cpp
index 1458c15..be84c86 100644
--- a/src/pv/pvCFreeze.cpp
+++ b/src/pv/pvCFreeze.cpp
@@ -63,22 +63,22 @@ void FlexPlugins::PV_CFreeze::next(int inNumSamples) {
// Pull random DC and nyquist magnitudes
p->dc = mDc[rgen.irand(mNumFrames)];
p->nyq = mNyq[rgen.irand(mNumFrames)];
- for (int xxn = 0; xxn < mNumBins; xxn++) {
+ for (int k = 0; k < mNumBins; k++) {
// For each bin, grab a random magnitude and phase diff pair
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];
+ idx = idx * mNumBins + k;
+ p->bin[k].mag = mMags[idx];
+ mPhase[k] = sc_wrap(mPhase[k] + mPhaseDiffs[idx], 0.f, static_cast(twopi));
+ p->bin[k].phase = mPhase[k];
}
} else {
// We're writing to a circular buffer, so pull the current magnitude and phase diff arrays
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 - mPhase[xxn], 0.f, static_cast(twopi));
- mPhase[xxn] = p->bin[xxn].phase;
+ for (int k = 0; k < numbins; k++) {
+ currentMagArr[k] = p->bin[k].mag;
+ currentPhaseDiffArr[k] = sc_wrap(p->bin[k].phase - mPhase[k], 0.f, static_cast(twopi));
+ mPhase[k] = p->bin[k].phase;
}
mDc[mWritePtr] = p->dc;
mNyq[mWritePtr] = p->nyq;
diff --git a/src/pv/pvStretch.cpp b/src/pv/pvStretch.cpp
index f994baa..74ea4e1 100644
--- a/src/pv/pvStretch.cpp
+++ b/src/pv/pvStretch.cpp
@@ -354,18 +354,18 @@ void FlexPlugins::PV_PlayBufStretch::Stretch2(
size_t hopSize) {
outFrame->dc = frame->dc;
outFrame->nyq = frame->nyq;
- for (size_t xxk = 0; xxk < fftSize/2-1; xxk++) {
- outFrame->bin[xxk].mag = frame->bin[xxk].mag;
+ for (size_t k = 0; k < fftSize/2-1; k++) {
+ outFrame->bin[k].mag = frame->bin[k].mag;
// Compute the instantaneous frequency
- float omegaK = twopi * (xxk+1) / fftSize;
- float phaseInc = frame->bin[xxk].phase - framePrev->bin[xxk].phase - hopSize * omegaK;
+ float omegaK = twopi * (k+1) / fftSize;
+ float phaseInc = frame->bin[k].phase - framePrev->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
float instantaneousFreq = omegaK + phaseInc/hopSize;
// Compute the new phase
- outFrame->bin[xxk].phase = sc_wrap(
- outFramePrev->bin[xxk].phase + static_cast(hopSize * instantaneousFreq),
+ outFrame->bin[k].phase = sc_wrap(
+ outFramePrev->bin[k].phase + static_cast(hopSize * instantaneousFreq),
0.f,
static_cast(twopi));
}
@@ -393,31 +393,31 @@ void FlexPlugins::PV_PlayBufStretch::Stretch2Puckette(
size_t hopSize) {
outFrame->dc = frame->dc;
outFrame->nyq = frame->nyq;
- for (size_t xxk = 0; xxk < fftSize/2-1; xxk++) {
- outFrame->bin[xxk].mag = frame->bin[xxk].mag;
+ for (size_t k = 0; k < fftSize/2-1; k++) {
+ outFrame->bin[k].mag = frame->bin[k].mag;
// Compute the instantaneous frequency
- float omegaK = twopi * (xxk+1) / fftSize;
- float phaseInc = frame->bin[xxk].phase - framePrev->bin[xxk].phase - hopSize * omegaK;
+ float omegaK = twopi * (k+1) / fftSize;
+ float phaseInc = frame->bin[k].phase - framePrev->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
float instantaneousFreq = omegaK + phaseInc/hopSize;
// In Puckette-style phase locking, we make a substitution for the previous phase,
// in order to "lock" phases of adjacent bins together.
float prevPhase = 0.0;
- if (xxk == 0) {
- prevPhase = outFramePrev->bin[xxk].phase;
- } else if (xxk == fftSize/2-2) {
- prevPhase = outFramePrev->bin[xxk].phase;
+ if (k == 0) {
+ prevPhase = outFramePrev->bin[k].phase;
+ } else if (k == fftSize/2-2) {
+ prevPhase = outFramePrev->bin[k].phase;
} else {
- std::complex prevBinKMinus1 = std::polar(outFramePrev->bin[xxk-1].mag, outFramePrev->bin[xxk-1].phase);
- std::complex prevBinK = std::polar(outFramePrev->bin[xxk].mag, outFramePrev->bin[xxk].phase);
- std::complex prevBinKPlus1 = std::polar(outFramePrev->bin[xxk+1].mag, outFramePrev->bin[xxk+1].phase);
+ std::complex prevBinKMinus1 = std::polar(outFramePrev->bin[k-1].mag, outFramePrev->bin[k-1].phase);
+ std::complex prevBinK = std::polar(outFramePrev->bin[k].mag, outFramePrev->bin[k].phase);
+ std::complex prevBinKPlus1 = std::polar(outFramePrev->bin[k+1].mag, outFramePrev->bin[k+1].phase);
prevPhase = std::arg(prevBinK - prevBinKMinus1 - prevBinKPlus1);
}
// Compute the new phase
- outFrame->bin[xxk].phase = sc_wrap(
+ outFrame->bin[k].phase = sc_wrap(
prevPhase + static_cast(hopSize * instantaneousFreq),
0.f,
static_cast(twopi));
@@ -453,60 +453,60 @@ void FlexPlugins::PV_PlayBufStretch::Stretch2LarocheDolson(
if (peakFinder->size() == 0) {
// No phase locking if no peaks were acquired
- for (size_t xxk = 0; xxk < fftSize/2-1; xxk++) {
- outFrame->bin[xxk].mag = frame->bin[xxk].mag;
+ for (size_t k = 0; k < fftSize/2-1; k++) {
+ outFrame->bin[k].mag = frame->bin[k].mag;
// Compute the instantaneous frequency
- double omegaK = twopi * (xxk+1) / fftSize;
- double phaseInc = frame->bin[xxk].phase - framePrev->bin[xxk].phase - hopSize * omegaK;
+ double omegaK = twopi * (k+1) / fftSize;
+ double phaseInc = frame->bin[k].phase - framePrev->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
double instantaneousFreq = omegaK + phaseInc/hopSize;
// Compute the phase
- outFrame->bin[xxk].phase = sc_wrap(
- outFramePrev->bin[xxk].phase + static_cast(hopSize * instantaneousFreq),
+ outFrame->bin[k].phase = sc_wrap(
+ outFramePrev->bin[k].phase + static_cast(hopSize * instantaneousFreq),
0.f,
static_cast(twopi));
}
} else {
// Update any bins that occur below the lowest peak's region of influence
- for (size_t xxk = 0; xxk < peakFinder->peaks[0].leftValley; xxk++) {
- outFrame->bin[xxk].mag = frame->bin[xxk].mag;
+ for (size_t k = 0; k < peakFinder->peaks[0].leftValley; k++) {
+ outFrame->bin[k].mag = frame->bin[k].mag;
// Compute the instantaneous frequency
- double omegaK = twopi * (xxk+1) / fftSize;
- double phaseInc = frame->bin[xxk].phase - framePrev->bin[xxk].phase - hopSize * omegaK;
+ double omegaK = twopi * (k+1) / fftSize;
+ double phaseInc = frame->bin[k].phase - framePrev->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
double instantaneousFreq = omegaK + phaseInc/hopSize;
// Compute the phase
- outFrame->bin[xxk].phase = sc_wrap(
- outFramePrev->bin[xxk].phase + static_cast(hopSize * instantaneousFreq),
+ outFrame->bin[k].phase = sc_wrap(
+ outFramePrev->bin[k].phase + static_cast(hopSize * instantaneousFreq),
0.f,
static_cast(twopi));
}
// Update any bins that occur above the highest peak's region of influence
- for (size_t xxk = peakFinder->peaks[peakFinder->size()-1].rightValley + 1; xxk < fftSize / 2 - 1; xxk++) {
- outFrame->bin[xxk].mag = frame->bin[xxk].mag;
+ for (size_t k = peakFinder->peaks[peakFinder->size()-1].rightValley + 1; k < fftSize / 2 - 1; k++) {
+ outFrame->bin[k].mag = frame->bin[k].mag;
// Compute the instantaneous frequency
- double omegaK = twopi * (xxk+1) / fftSize;
- double phaseInc = frame->bin[xxk].phase - framePrev->bin[xxk].phase - hopSize * omegaK;
+ double omegaK = twopi * (k+1) / fftSize;
+ double phaseInc = frame->bin[k].phase - framePrev->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
double instantaneousFreq = omegaK + phaseInc/hopSize;
// Compute the phase
- outFrame->bin[xxk].phase = sc_wrap(
- outFramePrev->bin[xxk].phase + static_cast(hopSize * instantaneousFreq),
+ outFrame->bin[k].phase = sc_wrap(
+ outFramePrev->bin[k].phase + static_cast(hopSize * instantaneousFreq),
0.f,
static_cast(twopi));
}
// Update all other peaks
- for (size_t xxn = 0; xxn < peakFinder->size(); xxn++) {
+ for (size_t n = 0; n < peakFinder->size(); n++) {
// First we compute the new phase for the peak bin as usual
- Peak peak = peakFinder->peaks[xxn];
+ Peak peak = peakFinder->peaks[n];
outFrame->bin[peak.peak].mag = frame->bin[peak.peak].mag;
// Compute the instantaneous frequency
@@ -522,17 +522,17 @@ void FlexPlugins::PV_PlayBufStretch::Stretch2LarocheDolson(
static_cast(twopi));
// Then we update the phases of all other peaks
- for (size_t xxo = peak.leftValley; xxo < peak.peak; xxo++) {
- outFrame->bin[xxo].mag = frame->bin[xxo].mag;
- outFrame->bin[xxo].phase = sc_wrap(
- outFrame->bin[peak.peak].phase + frame->bin[xxo].phase - frame->bin[peak.peak].phase,
+ for (size_t o = peak.leftValley; o < peak.peak; o++) {
+ outFrame->bin[o].mag = frame->bin[o].mag;
+ outFrame->bin[o].phase = sc_wrap(
+ outFrame->bin[peak.peak].phase + frame->bin[o].phase - frame->bin[peak.peak].phase,
0.f,
static_cast(twopi));
}
- for (size_t xxo = peak.peak + 1; xxo <= peak.rightValley; xxo++) {
- outFrame->bin[xxo].mag = frame->bin[xxo].mag;
- outFrame->bin[xxo].phase = sc_wrap(
- outFrame->bin[peak.peak].phase + frame->bin[xxo].phase - frame->bin[peak.peak].phase,
+ for (size_t o = peak.peak + 1; o <= peak.rightValley; o++) {
+ outFrame->bin[o].mag = frame->bin[o].mag;
+ outFrame->bin[o].phase = sc_wrap(
+ outFrame->bin[peak.peak].phase + frame->bin[o].phase - frame->bin[peak.peak].phase,
0.f,
static_cast(twopi));
}
@@ -564,18 +564,18 @@ void FlexPlugins::PV_PlayBufStretch::Stretch3(
size_t hopSize) {
outFrame->dc = INTERP(framePrev1->dc, frameNext->dc, pos);
outFrame->nyq = INTERP(framePrev1->nyq, frameNext->nyq, pos);
- for (size_t xxk = 0; xxk < fftSize/2-1; xxk++) {
- outFrame->bin[xxk].mag = INTERP(framePrev1->bin[xxk].mag, frameNext->bin[xxk].mag, pos);
+ for (size_t k = 0; k < fftSize/2-1; k++) {
+ outFrame->bin[k].mag = INTERP(framePrev1->bin[k].mag, frameNext->bin[k].mag, pos);
- float omegaK = twopi * (xxk+1) / fftSize;
+ float omegaK = twopi * (k+1) / fftSize;
// Compute the next instantaneous frequency
- float phaseInc = frameNext->bin[xxk].phase - framePrev1->bin[xxk].phase - hopSize * omegaK;
+ float phaseInc = frameNext->bin[k].phase - framePrev1->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
float instantaneousFreqNext = omegaK + phaseInc/hopSize;
// Compute the previous instantaneous frequency
- phaseInc = framePrev1->bin[xxk].phase - framePrev2->bin[xxk].phase - hopSize * omegaK;
+ phaseInc = framePrev1->bin[k].phase - framePrev2->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
float instantaneousFreqPrev = omegaK + phaseInc/hopSize;
@@ -583,8 +583,8 @@ void FlexPlugins::PV_PlayBufStretch::Stretch3(
float instantaneousFreq = INTERP(instantaneousFreqPrev, instantaneousFreqNext, pos);
// Compute the new phase
- outFrame->bin[xxk].phase = sc_wrap(
- outFramePrev->bin[xxk].phase + static_cast(hopSize * instantaneousFreq),
+ outFrame->bin[k].phase = sc_wrap(
+ outFramePrev->bin[k].phase + static_cast(hopSize * instantaneousFreq),
0.f,
static_cast(twopi));
}
@@ -616,18 +616,18 @@ void FlexPlugins::PV_PlayBufStretch::Stretch3Puckette(
size_t hopSize) {
outFrame->dc = INTERP(framePrev1->dc, frameNext->dc, pos);
outFrame->nyq = INTERP(framePrev1->nyq, frameNext->nyq, pos);
- for (size_t xxk = 0; xxk < fftSize/2-1; xxk++) {
- outFrame->bin[xxk].mag = INTERP(framePrev1->bin[xxk].mag, frameNext->bin[xxk].mag, pos);
+ for (size_t k = 0; k < fftSize/2-1; k++) {
+ outFrame->bin[k].mag = INTERP(framePrev1->bin[k].mag, frameNext->bin[k].mag, pos);
- float omegaK = twopi * (xxk+1) / fftSize;
+ float omegaK = twopi * (k+1) / fftSize;
// Compute the next instantaneous frequency
- float phaseInc = frameNext->bin[xxk].phase - framePrev1->bin[xxk].phase - hopSize * omegaK;
+ float phaseInc = frameNext->bin[k].phase - framePrev1->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
float instantaneousFreqNext = omegaK + phaseInc/hopSize;
// Compute the previous instantaneous frequency
- phaseInc = framePrev1->bin[xxk].phase - framePrev2->bin[xxk].phase - hopSize * omegaK;
+ phaseInc = framePrev1->bin[k].phase - framePrev2->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
float instantaneousFreqPrev = omegaK + phaseInc/hopSize;
@@ -637,19 +637,19 @@ void FlexPlugins::PV_PlayBufStretch::Stretch3Puckette(
// In Puckette-style phase locking, we make a substitution for the previous phase,
// in order to "lock" phases of adjacent bins together.
float prevPhase = 0.0;
- if (xxk == 0) {
- prevPhase = outFramePrev->bin[xxk].phase;
- } else if (xxk == fftSize/2-2) {
- prevPhase = outFramePrev->bin[xxk].phase;
+ if (k == 0) {
+ prevPhase = outFramePrev->bin[k].phase;
+ } else if (k == fftSize/2-2) {
+ prevPhase = outFramePrev->bin[k].phase;
} else {
- std::complex prevBinKMinus1 = std::polar(outFramePrev->bin[xxk-1].mag, outFramePrev->bin[xxk-1].phase);
- std::complex prevBinK = std::polar(outFramePrev->bin[xxk].mag, outFramePrev->bin[xxk].phase);
- std::complex prevBinKPlus1 = std::polar(outFramePrev->bin[xxk+1].mag, outFramePrev->bin[xxk+1].phase);
+ std::complex prevBinKMinus1 = std::polar(outFramePrev->bin[k-1].mag, outFramePrev->bin[k-1].phase);
+ std::complex prevBinK = std::polar(outFramePrev->bin[k].mag, outFramePrev->bin[k].phase);
+ std::complex prevBinKPlus1 = std::polar(outFramePrev->bin[k+1].mag, outFramePrev->bin[k+1].phase);
prevPhase = std::arg(prevBinK - prevBinKMinus1 - prevBinKPlus1);
}
// Compute the new phase
- outFrame->bin[xxk].phase = sc_wrap(
+ outFrame->bin[k].phase = sc_wrap(
prevPhase + static_cast(hopSize * instantaneousFreq),
0.f,
static_cast(twopi));
@@ -697,18 +697,18 @@ void FlexPlugins::PV_PlayBufStretch::Stretch3LarocheDolson(
if (peakFinder->size() == 0) {
// No phase locking if no peaks were acquired
- for (size_t xxk = 0; xxk < fftSize/2-1; xxk++) {
- outFrame->bin[xxk].mag = INTERP(framePrev1->bin[xxk].mag, frameNext->bin[xxk].mag, pos);
+ for (size_t k = 0; k < fftSize/2-1; k++) {
+ outFrame->bin[k].mag = INTERP(framePrev1->bin[k].mag, frameNext->bin[k].mag, pos);
- double omegaK = twopi * (xxk+1) / fftSize;
+ double omegaK = twopi * (k+1) / fftSize;
// Compute the next instantaneous frequency
- double phaseInc = frameNext->bin[xxk].phase - framePrev1->bin[xxk].phase - hopSize * omegaK;
+ double phaseInc = frameNext->bin[k].phase - framePrev1->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
double instantaneousFreqNext = omegaK + phaseInc/hopSize;
// Compute the previous instantaneous frequency
- phaseInc = framePrev1->bin[xxk].phase - framePrev2->bin[xxk].phase - hopSize * omegaK;
+ phaseInc = framePrev1->bin[k].phase - framePrev2->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
double instantaneousFreqPrev = omegaK + phaseInc/hopSize;
@@ -716,25 +716,25 @@ void FlexPlugins::PV_PlayBufStretch::Stretch3LarocheDolson(
double instantaneousFreq = INTERP(instantaneousFreqPrev, instantaneousFreqNext, pos);
// Compute the new phase
- outFrame->bin[xxk].phase = sc_wrap(
- outFramePrev->bin[xxk].phase + static_cast(hopSize * instantaneousFreq),
+ outFrame->bin[k].phase = sc_wrap(
+ outFramePrev->bin[k].phase + static_cast(hopSize * instantaneousFreq),
0.f,
static_cast(twopi));
}
} else {
// Update any bins that occur below the lowest peak's region of influence
- for (size_t xxk = 0; xxk < peakFinder->peaks[0].leftValley; xxk++) {
- outFrame->bin[xxk].mag = INTERP(framePrev1->bin[xxk].mag, frameNext->bin[xxk].mag, pos);
+ for (size_t k = 0; k < peakFinder->peaks[0].leftValley; k++) {
+ outFrame->bin[k].mag = INTERP(framePrev1->bin[k].mag, frameNext->bin[k].mag, pos);
// Compute the instantaneous frequency
- double omegaK = twopi * (xxk+1) / fftSize;
+ double omegaK = twopi * (k+1) / fftSize;
- double phaseInc = frameNext->bin[xxk].phase - framePrev1->bin[xxk].phase - hopSize * omegaK;
+ double phaseInc = frameNext->bin[k].phase - framePrev1->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
double instantaneousFreqNext = omegaK + phaseInc/hopSize;
// Compute the previous instantaneous frequency
- phaseInc = framePrev1->bin[xxk].phase - framePrev2->bin[xxk].phase - hopSize * omegaK;
+ phaseInc = framePrev1->bin[k].phase - framePrev2->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
double instantaneousFreqPrev = omegaK + phaseInc/hopSize;
@@ -742,25 +742,25 @@ void FlexPlugins::PV_PlayBufStretch::Stretch3LarocheDolson(
double instantaneousFreq = INTERP(instantaneousFreqPrev, instantaneousFreqNext, pos);
// Compute the phase
- outFrame->bin[xxk].phase = sc_wrap(
- outFramePrev->bin[xxk].phase + static_cast(hopSize * instantaneousFreq),
+ outFrame->bin[k].phase = sc_wrap(
+ outFramePrev->bin[k].phase + static_cast(hopSize * instantaneousFreq),
0.f,
static_cast(twopi));
}
// Update any bins that occur above the highest peak's region of influence
- for (size_t xxk = peakFinder->peaks[peakFinder->size()-1].rightValley + 1; xxk < fftSize / 2 - 1; xxk++) {
- outFrame->bin[xxk].mag = INTERP(framePrev1->bin[xxk].mag, frameNext->bin[xxk].mag, pos);
+ for (size_t k = peakFinder->peaks[peakFinder->size()-1].rightValley + 1; k < fftSize / 2 - 1; k++) {
+ outFrame->bin[k].mag = INTERP(framePrev1->bin[k].mag, frameNext->bin[k].mag, pos);
// Compute the instantaneous frequency
- double omegaK = twopi * (xxk+1) / fftSize;
+ double omegaK = twopi * (k+1) / fftSize;
- double phaseInc = frameNext->bin[xxk].phase - framePrev1->bin[xxk].phase - hopSize * omegaK;
+ double phaseInc = frameNext->bin[k].phase - framePrev1->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
double instantaneousFreqNext = omegaK + phaseInc/hopSize;
// Compute the previous instantaneous frequency
- phaseInc = framePrev1->bin[xxk].phase - framePrev2->bin[xxk].phase - hopSize * omegaK;
+ phaseInc = framePrev1->bin[k].phase - framePrev2->bin[k].phase - hopSize * omegaK;
phaseInc = std::fmod(phaseInc + pi, twopi) - pi;
double instantaneousFreqPrev = omegaK + phaseInc/hopSize;
@@ -768,15 +768,15 @@ void FlexPlugins::PV_PlayBufStretch::Stretch3LarocheDolson(
double instantaneousFreq = INTERP(instantaneousFreqPrev, instantaneousFreqNext, pos);
// Compute the phase
- outFrame->bin[xxk].phase = sc_wrap(
- outFramePrev->bin[xxk].phase + static_cast(hopSize * instantaneousFreq),
+ outFrame->bin[k].phase = sc_wrap(
+ outFramePrev->bin[k].phase + static_cast(hopSize * instantaneousFreq),
0.f,
static_cast(twopi));
}
- for (size_t xxn = 0; xxn < peakFinder->size(); xxn++) {
+ for (size_t n = 0; n < peakFinder->size(); n++) {
// First we compute the new phase for the peak bin as usual
- Peak peak = peakFinder->peaks[xxn];
+ Peak peak = peakFinder->peaks[n];
outFrame->bin[peak.peak].mag = INTERP(framePrev1->bin[peak.peak].mag, frameNext->bin[peak.peak].mag, pos);
// Compute the instantaneous frequency
@@ -801,17 +801,17 @@ void FlexPlugins::PV_PlayBufStretch::Stretch3LarocheDolson(
static_cast(twopi));
// Then we update all bins in the region of influence
- for (size_t xxo = peak.leftValley; xxo < peak.peak; xxo++) {
- outFrame->bin[xxo].mag = INTERP(framePrev1->bin[xxo].mag, frameNext->bin[xxo].mag, pos);
- outFrame->bin[xxo].phase = sc_wrap(
- outFrame->bin[peak.peak].phase + cframe->bin[xxo].phase - cframe->bin[peak.peak].phase,
+ for (size_t o = peak.leftValley; o < peak.peak; o++) {
+ outFrame->bin[o].mag = INTERP(framePrev1->bin[o].mag, frameNext->bin[o].mag, pos);
+ outFrame->bin[o].phase = sc_wrap(
+ outFrame->bin[peak.peak].phase + cframe->bin[o].phase - cframe->bin[peak.peak].phase,
0.f,
static_cast(twopi));
}
- for (size_t xxo = peak.peak + 1; xxo <= peak.rightValley; xxo++) {
- outFrame->bin[xxo].mag = INTERP(framePrev1->bin[xxo].mag, frameNext->bin[xxo].mag, pos);
- outFrame->bin[xxo].phase = sc_wrap(
- outFrame->bin[peak.peak].phase + cframe->bin[xxo].phase - cframe->bin[peak.peak].phase,
+ for (size_t o = peak.peak + 1; o <= peak.rightValley; o++) {
+ outFrame->bin[o].mag = INTERP(framePrev1->bin[o].mag, frameNext->bin[o].mag, pos);
+ outFrame->bin[o].phase = sc_wrap(
+ outFrame->bin[peak.peak].phase + cframe->bin[o].phase - cframe->bin[peak.peak].phase,
0.f,
static_cast(twopi));
}
@@ -827,11 +827,11 @@ void FlexPlugins::PV_PlayBufStretch::Stretch3LarocheDolson(
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++) {
+ for (size_t n = 2, k = 0; n < fftSize; n+=2, k++) {
// For some reason the phase is stored first, then the magnitude.
// This prevents a direct cast to SCPolarBuf, unfortunately.
- polarBuf->bin[xxk].phase = fftBuf[xxn];
- polarBuf->bin[xxk].mag = fftBuf[xxn+1];
+ polarBuf->bin[k].phase = fftBuf[n];
+ polarBuf->bin[k].mag = fftBuf[n+1];
}
}
@@ -843,9 +843,9 @@ void FlexPlugins::PV_PlayBufStretch::fillPolarBuf(const float *fftBuf, SCPolarBu
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++) {
- destBuf->bin[xxn].mag = sourceBuf->bin[xxn].mag;
- destBuf->bin[xxn].phase = sourceBuf->bin[xxn].phase;
+ for (size_t n = 0; n < numbins; n++) {
+ destBuf->bin[n].mag = sourceBuf->bin[n].mag;
+ destBuf->bin[n].phase = sourceBuf->bin[n].phase;
}
}
@@ -893,27 +893,27 @@ void FlexPlugins::PeakFinder::analyze(const SCPolarBuf *buf) {
if (m_queueL && m_maxSize > m_radius * 2 + 1) {
m_size = 0; // clear any existing data
- size_t xxi = m_radius;
- while (xxi < m_maxSize - m_radius) {
+ size_t i = m_radius;
+ while (i < m_maxSize - m_radius) {
bool isMax = true;
- for (size_t xxj = xxi - m_radius; xxj < xxi; xxj++) {
- if (buf->bin[xxj].mag >= buf->bin[xxi].mag) {
+ for (size_t j = i - m_radius; j < i; j++) {
+ if (buf->bin[j].mag >= buf->bin[i].mag) {
isMax = false;
break;
}
}
- for (size_t xxj = xxi + 1; xxj <= xxi + m_radius; xxj++) {
- if (buf->bin[xxj].mag >= buf->bin[xxi].mag) {
+ for (size_t j = i + 1; j <= i + m_radius; j++) {
+ if (buf->bin[j].mag >= buf->bin[i].mag) {
isMax = false;
break;
}
}
if (isMax) {
- peaks[m_size] = Peak(xxi);
+ peaks[m_size] = Peak(i);
m_size++;
- xxi += m_radius + 1;
+ i += m_radius + 1;
} else {
- xxi++;
+ i++;
}
}
@@ -922,21 +922,21 @@ void FlexPlugins::PeakFinder::analyze(const SCPolarBuf *buf) {
if (m_size > 0) {
float min = buf->bin[0].mag;
size_t argmin = 0;
- size_t xxk = 1;
- for (; xxk < peaks[0].peak; xxk++) {
- if (buf->bin[xxk].mag < min) {
- min = buf->bin[xxk].mag;
- argmin = xxk;
+ size_t k = 1;
+ for (; k < peaks[0].peak; k++) {
+ if (buf->bin[k].mag < min) {
+ min = buf->bin[k].mag;
+ argmin = k;
}
}
peaks[0].leftValley = argmin;
- xxk = peaks[m_size-1].peak + 1;
- min = buf->bin[xxk].mag;
- argmin = xxk;
- for (xxk++; xxk < m_maxSize; xxk++) {
- if (buf->bin[xxk].mag < min) {
- min = buf->bin[xxk].mag;
- argmin = xxk;
+ k = peaks[m_size-1].peak + 1;
+ min = buf->bin[k].mag;
+ argmin = k;
+ for (k++; k < m_maxSize; k++) {
+ if (buf->bin[k].mag < min) {
+ min = buf->bin[k].mag;
+ argmin = k;
}
}
peaks[m_size-1].rightValley = argmin;
@@ -944,18 +944,18 @@ void FlexPlugins::PeakFinder::analyze(const SCPolarBuf *buf) {
// Find the remaining left and right valleys
if (m_size > 1) {
- for (size_t xxj = 0; xxj < m_size-1; xxj++) {
- size_t xxk = peaks[xxj].peak + 1;
- float min = buf->bin[xxk].mag;
- size_t argmin = xxk;
- for (xxk++; xxk < peaks[xxj+1].peak; xxk++) {
- if (buf->bin[xxk].mag < min) {
- min = buf->bin[xxk].mag;
- argmin = xxk;
+ for (size_t j = 0; j < m_size-1; j++) {
+ size_t k = peaks[j].peak + 1;
+ float min = buf->bin[k].mag;
+ size_t argmin = k;
+ for (k++; k < peaks[j+1].peak; k++) {
+ if (buf->bin[k].mag < min) {
+ min = buf->bin[k].mag;
+ argmin = k;
}
}
- peaks[xxj].rightValley = argmin - 1;
- peaks[xxj+1].leftValley = argmin;
+ peaks[j].rightValley = argmin - 1;
+ peaks[j+1].leftValley = argmin;
}
}
}
diff --git a/src/rubberband/RubberBandPS.schelp b/src/rubberband/RubberBandPS.schelp
index 037d5ff..82bc7db 100644
--- a/src/rubberband/RubberBandPS.schelp
+++ b/src/rubberband/RubberBandPS.schelp
@@ -21,7 +21,6 @@ For more information about the RubberBand library, visit link::https://breakfast
note::
This UGen uses quite a bit of CPU resources, which could be a problem on a less powerful computer.
-You should also consider increasing the strong::memSize:: option for the server from the default 128MB.
::
classmethods::
diff --git a/src/rubberband/RubberBandStretcher.schelp b/src/rubberband/RubberBandStretcher.schelp
index 5beb61e..91bf7fd 100644
--- a/src/rubberband/RubberBandStretcher.schelp
+++ b/src/rubberband/RubberBandStretcher.schelp
@@ -23,7 +23,6 @@ For more information about the RubberBand library, visit link::https://breakfast
note::
This UGen uses quite a bit of CPU resources, which could be a problem on a less powerful computer.
-You should also consider increasing the strong::memSize:: option for the server from the default 128MB.
::
classmethods::
diff --git a/src/rubberband/RubberBandStretcherBuf.schelp b/src/rubberband/RubberBandStretcherBuf.schelp
index d07350e..a04dd34 100644
--- a/src/rubberband/RubberBandStretcherBuf.schelp
+++ b/src/rubberband/RubberBandStretcherBuf.schelp
@@ -19,7 +19,6 @@ For more information about the RubberBand library, visit link::https://breakfast
note::
This UGen uses quite a bit of CPU resources, which could be a problem on a less powerful computer.
-You should also consider increasing the strong::memSize:: option for the server from the default 128MB.
::
classmethods::
diff --git a/src/rubberband/ringbuffer.hpp b/src/rubberband/ringbuffer.hpp
index eefca00..ec5adb5 100644
--- a/src/rubberband/ringbuffer.hpp
+++ b/src/rubberband/ringbuffer.hpp
@@ -10,42 +10,44 @@
#pragma once
#include
-template
-class TestRingBuffer;
+namespace FlexPlugins {
+ template
+ class TestRingBuffer;
-template
-class RingBuffer {
-public:
- RingBuffer();
- /// Given an initialized buffer, associates it with the RingBuffer
- void initialize(T* buffer, size_t size);
-
- /// Determines if the buffer is ready to read `length` samples
- bool isReadReady(size_t length) const;
+ template
+ class RingBuffer {
+ public:
+ RingBuffer();
+ /// Given an initialized buffer, associates it with the RingBuffer
+ void initialize(T* buffer, size_t size);
+
+ /// Determines if the buffer is ready to read `length` samples
+ 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() const;
+ /// Reads a block of specified length
+ void readBlock(T* destination, size_t length);
+
+ /// Retrieves the size
+ size_t size() const;
- /// Writes a block of specified length
- void writeBlock(const T* samples, size_t length);
-
- /// Zeros out the buffer
- void zero();
- T* m_buffer;
-private:
- size_t m_size; // size of buffer overall
- size_t m_inputPointer; // input write pointer
- size_t m_outputPointer; // output read pointer
- int m_newSamples; // number of new samples accumulated since last read
- template
- friend class TestRingBuffer;
-};
+ /// Writes a block of specified length
+ void writeBlock(const T* samples, size_t length);
+
+ /// Zeros out the buffer
+ void zero();
+ T* m_buffer;
+ private:
+ size_t m_size; // size of buffer overall
+ size_t m_inputPointer; // input write pointer
+ size_t m_outputPointer; // output read pointer
+ int m_newSamples; // number of new samples accumulated since last read
+ template
+ friend class TestRingBuffer;
+ };
+}
template
-RingBuffer::RingBuffer() {
+FlexPlugins::RingBuffer::RingBuffer() {
m_buffer = nullptr;
m_size = 0;
m_newSamples = 0;
@@ -54,13 +56,13 @@ RingBuffer::RingBuffer() {
}
template
-void RingBuffer::initialize(T* buffer, size_t size) {
+void FlexPlugins::RingBuffer::initialize(T* buffer, size_t size) {
m_buffer = buffer;
m_size = size;
}
template
-void RingBuffer::writeBlock(const T* samples, size_t length) {
+void FlexPlugins::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++) {
@@ -75,7 +77,7 @@ void RingBuffer::writeBlock(const T* samples, size_t length) {
}
template
-void RingBuffer::readBlock(T* destination, size_t length) {
+void FlexPlugins::RingBuffer::readBlock(T* destination, size_t length) {
if (m_buffer && m_size > 0) {
for (size_t i = 0; i < length; i++) {
destination[i] = m_buffer[m_outputPointer];
@@ -90,7 +92,7 @@ void RingBuffer::readBlock(T* destination, size_t length) {
}
template
-bool RingBuffer::isReadReady(size_t length) const {
+bool FlexPlugins::RingBuffer::isReadReady(size_t length) const {
if (m_newSamples >= length) {
return true;
} else {
@@ -99,12 +101,12 @@ bool RingBuffer::isReadReady(size_t length) const {
}
template
-size_t RingBuffer::size() const {
+size_t FlexPlugins::RingBuffer::size() const {
return m_size;
}
template
-void RingBuffer::zero() {
+void FlexPlugins::RingBuffer::zero() {
for (size_t i = 0; i < m_size; i++)
m_buffer[i] = 0;
}
\ No newline at end of file