Skip to main content
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

T
typename
default:"double"
Sample type (typically double or float)

Constructor

LFO()
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:

k64th

1/64 note

k32nd

1/32 note

k16thT

1/16 triplet

k16th

1/16 note

k16thD

Dotted 1/16

k8thT

1/8 triplet

k8th

1/8 note

k8thD

Dotted 1/8

k4th

1/4 note

k4thD

Dotted 1/4

k2th

1/2 note

k1

1 bar (4/4)

k2

2 bars

k4

4 bars

k8

8 bars

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.
freqHz
double
Frequency in Hz
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.
pOutput
T*
Output buffer to fill
nFrames
int
Number of samples to generate
qnPos
double
default:"0.0"
Current position in quarter notes from the DAW
transportIsRunning
bool
default:"false"
Whether the DAW transport is playing
tempo
double
default:"120.0"
Current tempo in BPM

SetShape

void SetShape(int lfoShape)
Set the LFO waveform shape.
lfoShape
int
Shape index (see EShape)

SetPolarity

void SetPolarity(bool bipolar)
Set output range.
bipolar
bool
If true, output is -1.0 to 1.0. If false, output is 0.0 to 1.0.

SetScalar

void SetScalar(T scalar)
Set amplitude scaling factor.
scalar
T
Multiplier for output values

SetQNScalarFromDivision

void SetQNScalarFromDivision(int division)
Set tempo division for sync mode.
division
int
Division index (see ETempoDivison)

SetRateMode

void SetRateMode(bool sync)
Switch between free-running and tempo-synced modes.
sync
bool
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

T
typename
default:"double"
Sample type

Constructor

OverSampler(EFactor factor = kNone, 
           bool blockProcessing = true,
           int nInChannels = 1, 
           int nOutChannels = 1)
factor
EFactor
default:"kNone"
Oversampling factor: kNone, k2x, k4x, k8x, or k16x
blockProcessing
bool
default:"true"
If true, process blocks. If false, process per-sample.
nInChannels
int
default:"1"
Number of input channels
nOutChannels
int
default:"1"
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.
inputs
T**
Input buffers (non-interleaved)
outputs
T**
Output buffers (non-interleaved)
nFrames
int
Number of samples per channel at base sample rate
nInChans
int
Number of input channels to process
nOutChans
int
Number of output channels to process
func
BlockProcessFunc
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.
input
T
Input sample
func
std::function<T(T)>
Function to process the oversampled audio
Returns: Processed and downsampled output

ProcessGen

T ProcessGen(std::function<T()> genFunc)
Oversample a synthesis function (no input).
genFunc
std::function<T()>
Function that generates audio samples
Returns: Downsampled output

SetOverSampling

void SetOverSampling(EFactor factor)
Change the oversampling factor.
factor
EFactor
New 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

int GetRate() const
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

T
typename
Sample type
NC
int
default:"1"
Number of channels

Constructor

LogParamSmooth(double timeMs = 5., T initialValue = 0.)
timeMs
double
default:"5.0"
Smoothing time constant in milliseconds
initialValue
T
default:"0.0"
Initial output value

Methods

Process
inline T Process(T input)
Smooth a single value (only works for NC=1).
input
T
Target value
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

T
typename
Sample type

Constructor

SmoothedGain(double smoothingTime = 5.0)
smoothingTime
double
default:"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.
inputs
T**
Input buffers
outputs
T**
Output buffers
nChans
int
Number of channels
nFrames
int
Number of samples
gainValue
double
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
int 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
int GetNumChannels()
Returns: Number of channels

Members

samplerate
double
Sample rate of the impulse
impulses
struct
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.
impulse
WDL_ImpulseBuffer*
Impulse buffer to use
fft_size
int
default:"-1"
FFT size (-1 for auto)
impulse_sample_offset
int
default:"0"
Offset into impulse to start
max_imp_size
int
default:"0"
Maximum impulse size to use (0 = all)
forceBrute
bool
default:"false"
Force brute-force convolution (for small impulses)
Returns: 0 on success
GetLatency
int GetLatency()
Returns: Latency in samples (FFT size / 2)
Reset
void 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
WDL_FFT_REAL** Get()
Returns: Pointer to output buffers
Advance
void Advance(int len)
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