The effects module provides various DSP utilities for modulation, oversampling, parameter smoothing, and convolution reverb.
LFO
Low Frequency Oscillator with tempo synchronization and multiple waveform shapes.
Template Parameters
Sample type (typically double or float)
Constructor
Inherits from IOscillator<T>. Use inherited methods SetFreqCPS() and SetSampleRate().
LFO Shapes
EShape
kTriangle
Triangle wave - smooth linear rise and fall
kSquare
Square wave - instant transitions
kRampUp
Ramp up - linear rise from 0 to 1
kRampDown
Ramp down - linear fall from 1 to 0
kSine
Sine wave - smooth harmonic oscillation
Shape String List
#define LFO_SHAPE_VALIST "Triangle", "Square", "Ramp Up", "Ramp Down", "Sine"
LFO Tempo Division
ETempoDivison
Musical time divisions for tempo sync:
Tempo Division String List
#define LFO_TEMPODIV_VALIST "1/64", "1/32", "1/16T", "1/16", "1/16D", "1/8T", "1/8", "1/8D", "1/4", "1/4D", "1/2", "1/1", "2/1", "4/1", "8/1"
LFO Methods
Process
inline T Process(double freqHz) override
Generate the next LFO sample with per-sample frequency modulation.
Returns: LFO output value
ProcessBlock
void ProcessBlock(T* pOutput, int nFrames,
double qnPos = 0.,
bool transportIsRunning = false,
double tempo = 120.)
Process a block of samples with optional tempo sync.
Number of samples to generate
Current position in quarter notes from the DAW
Whether the DAW transport is playing
SetShape
void SetShape(int lfoShape)
Set the LFO waveform shape.
SetPolarity
void SetPolarity(bool bipolar)
Set output range.
If true, output is -1.0 to 1.0. If false, output is 0.0 to 1.0.
SetScalar
Set amplitude scaling factor.
Multiplier for output values
SetQNScalarFromDivision
void SetQNScalarFromDivision(int division)
Set tempo division for sync mode.
Division index (see ETempoDivison)
SetRateMode
void SetRateMode(bool sync)
Switch between free-running and tempo-synced modes.
If true, use tempo sync. If false, use Hz frequency.
GetQNScalar (static)
static T GetQNScalar(ETempoDivison division)
Get the scalar for a tempo division.
Returns: Multiplication factor for quarter note position
GetQNDisplay (static)
static const char* GetQNDisplay(ETempoDivison division)
Get display string for a tempo division.
Returns: String like “1/4” or “1/8D”
OverSampler
High-quality oversampling processor using HIIR (Highly Interpolated IIR) filters.
Template Parameters
Constructor
OverSampler(EFactor factor = kNone,
bool blockProcessing = true,
int nInChannels = 1,
int nOutChannels = 1)
Oversampling factor: kNone, k2x, k4x, k8x, or k16x
If true, process blocks. If false, process per-sample.
Number of output channels
Oversampling Factors
enum EFactor {
kNone = 0, // No oversampling (1x)
k2x, // 2x oversampling
k4x, // 4x oversampling
k8x, // 8x oversampling
k16x // 16x oversampling
};
Factor String List
#define OVERSAMPLING_FACTORS_VA_LIST "None", "2x", "4x", "8x", "16x"
OverSampler Methods
ProcessBlock
void ProcessBlock(T** inputs, T** outputs, int nFrames,
int nInChans, int nOutChans,
BlockProcessFunc func)
Oversample a block of audio with a processing function.
Input buffers (non-interleaved)
Output buffers (non-interleaved)
Number of samples per channel at base sample rate
Number of input channels to process
Number of output channels to process
Function to process audio at higher sample rate: std::function<void(T**, T**, int)>
Don’t capture variables by reference in the lambda if they could cause allocations. std::function can malloc if captures are too large.
Process
T Process(T input, std::function<T(T)> func)
Oversample a single sample with a processing function.
Function to process the oversampled audio
Returns: Processed and downsampled output
ProcessGen
T ProcessGen(std::function<T()> genFunc)
Oversample a synthesis function (no input).
Function that generates audio samples
Returns: Downsampled output
SetOverSampling
void SetOverSampling(EFactor factor)
Change the oversampling factor.
Reset
void Reset(int blockSize = DEFAULT_BLOCK_SIZE)
Reset internal buffers and clear filter state.
blockSize
int
default:"DEFAULT_BLOCK_SIZE"
Maximum block size to support
GetRate
Returns: Current oversampling rate (1, 2, 4, 8, or 16)
Parameter Smoothers
Classes for smoothing parameter changes to avoid discontinuities.
LogParamSmooth
Logarithmic parameter smoother using a one-pole IIR filter.
Template Parameters
Constructor
LogParamSmooth(double timeMs = 5., T initialValue = 0.)
Smoothing time constant in milliseconds
Methods
Process
inline T Process(T input)
Smooth a single value (only works for NC=1).
Returns: Smoothed output
ProcessBlock
void ProcessBlock(T inputs[NC], T** outputs, int nFrames, int channelOffset = 0)
Smooth multiple channels over a block.
SetValue
inline void SetValue(T value)
Instantly set the output value (all channels).
SetSmoothTime
void SetSmoothTime(double timeMs, double sampleRate)
Change the smoothing time constant.
SmoothedGain
Convenience class for smoothing gain values.
Template Parameters
Constructor
SmoothedGain(double smoothingTime = 5.0)
Smoothing time in milliseconds
Methods
ProcessBlock
void ProcessBlock(T** inputs, T** outputs, int nChans, int nFrames, double gainValue)
Apply smoothed gain to audio.
Target gain value (linear, not dB)
Convolution Engine
Fast convolution for reverb and impulse response processing.
WDL_ImpulseBuffer
Container for impulse response data.
Methods
GetLength
Returns: Length of impulse in samples
SetLength
int SetLength(int samples)
Resize/clear all channels.
Returns: Actual size set (0 if error)
SetNumChannels
void SetNumChannels(int usench, bool duplicateExisting = true)
Set number of channels.
GetNumChannels
Returns: Number of channels
Members
Sample rate of the impulse
Container with impulse buffers. Access via impulses[channel].
WDL_ConvolutionEngine
High-performance convolution processor.
Methods
SetImpulse
int SetImpulse(WDL_ImpulseBuffer* impulse,
int fft_size = -1,
int impulse_sample_offset = 0,
int max_imp_size = 0,
bool forceBrute = false)
Load an impulse response.
Offset into impulse to start
Maximum impulse size to use (0 = all)
Force brute-force convolution (for small impulses)
Returns: 0 on success
GetLatency
Returns: Latency in samples (FFT size / 2)
Reset
Clear internal state.
Add
void Add(WDL_FFT_REAL** bufs, int len, int nch)
Add input samples for processing.
Avail
int Avail(int wantSamples)
Check how many samples are available.
Returns: Number of samples ready
Get
Returns: Pointer to output buffers
Advance
Consume output samples.
Usage Examples
LFO with Tempo Sync
LFO<double> lfo;
lfo.SetSampleRate(44100.0);
lfo.SetShape(LFO<double>::kSine);
lfo.SetPolarity(true); // Bipolar
lfo.SetQNScalarFromDivision(LFO<double>::k4th); // 1/4 notes
lfo.SetRateMode(true); // Tempo sync on
void ProcessBlock(double** inputs, double** outputs, int nFrames,
double qnPos, bool isPlaying, double tempo) {
double lfoOut[512];
lfo.ProcessBlock(lfoOut, nFrames, qnPos, isPlaying, tempo);
for (int i = 0; i < nFrames; i++) {
double modAmount = lfoOut[i] * 500.0; // ±500 Hz
filter.SetFreqCPS(1000.0 + modAmount);
// ... process audio
}
}
Oversampled Distortion
OverSampler<double> oversampler(k4x, true, 2, 2);
void ProcessBlock(double** inputs, double** outputs, int nFrames) {
oversampler.ProcessBlock(inputs, outputs, nFrames, 2, 2,
[&](double** ins, double** outs, int frames) {
for (int c = 0; c < 2; c++) {
for (int i = 0; i < frames; i++) {
// Nonlinear processing at 4x sample rate
outs[c][i] = std::tanh(ins[c][i] * 5.0);
}
}
});
}
Parameter Smoothing
LogParamSmooth<double, 1> freqSmoother(10.0); // 10ms smoothing
freqSmoother.SetSmoothTime(10.0, 44100.0);
void OnParamChange(int paramIdx) {
// Don't smooth here, just get the value
}
void ProcessBlock(double** inputs, double** outputs, int nFrames) {
double targetFreq = GetParam(kFreq)->Value();
for (int i = 0; i < nFrames; i++) {
double smoothedFreq = freqSmoother.Process(targetFreq);
filter.SetFreqCPS(smoothedFreq);
// ... process
}
}
Convolution Reverb
WDL_ImpulseBuffer impulse;
WDL_ConvolutionEngine_Div convolver;
void LoadIR(const char* filename) {
// Load impulse response into impulse buffer
// ... (load audio file into impulse.impulses[0])
impulse.SetLength(irLength);
impulse.SetNumChannels(2);
impulse.samplerate = 44100.0;
convolver.SetImpulse(&impulse, 8192, 0, 0, 0, 2048);
}
void ProcessBlock(WDL_FFT_REAL** inputs, WDL_FFT_REAL** outputs,
int nFrames, int nChans) {
convolver.Add(inputs, nFrames, nChans);
if (convolver.Avail(nFrames) >= nFrames) {
WDL_FFT_REAL** wetSignal = convolver.Get();
// Mix wet and dry
for (int c = 0; c < nChans; c++) {
for (int i = 0; i < nFrames; i++) {
outputs[c][i] = inputs[c][i] * 0.7 + wetSignal[c][i] * 0.3;
}
}
convolver.Advance(nFrames);
}
}
Code Locations
- LFO:
IPlug/Extras/LFO.h:1
- OverSampler:
IPlug/Extras/Oversampler.h:1
- Smoothers:
IPlug/Extras/Smoothers.h:1
- Convolution:
WDL/convoengine.h:1
See Also