Skip to main content
iPlug2 includes a collection of optimized DSP building blocks in IPlug/Extras/. These utilities provide essential components for audio synthesis and processing.

Available Components

Oscillator

Sine wave oscillators with fast table lookup

ADSREnvelope

Attack-Decay-Sustain-Release envelopes

SVF

State Variable Filter with multiple modes

LFO

Low-frequency oscillator with tempo sync

Oversampler

HIIR-based oversampling up to 16x

Smoothers

Parameter smoothing utilities

DCBlocker

DC offset removal filter

NoiseGate

Dynamic noise gate

Oscillators

FastSinOscillator

Fast sine wave oscillator using table lookup based on Miller Puckette’s approach from Pure Data:
Using FastSinOscillator
#include "Oscillator.h"

class MyVoice : public SynthVoice
{
public:
  void SetSampleRateAndBlockSize(double sampleRate, int blockSize) override
  {
    mOSC.SetSampleRate(sampleRate);
  }
  
  void ProcessSamplesAccumulating(sample** inputs, sample** outputs, 
                                  int nInputs, int nOutputs, 
                                  int startIdx, int nFrames) override
  {
    double freq = 440.0; // A4
    
    for(int i = startIdx; i < startIdx + nFrames; i++)
    {
      outputs[0][i] += mOSC.Process(freq);
    }
  }

private:
  FastSinOscillator<sample> mOSC;
};
FastSinOscillator uses a 512-sample lookup table with linear interpolation for fast, high-quality sine wave generation.

SinOscillator

Standard sine oscillator using std::sin() - slower but no table memory:
IPlug/Extras/Oscillator.h:66
SinOscillator<sample> mOSC;
mOSC.SetSampleRate(44100.);
mOSC.SetFreqCPS(440.);
sample output = mOSC.Process();

ADSR Envelope

Full-featured ADSR envelope with retriggering and velocity support:
Using ADSREnvelope
#include "ADSREnvelope.h"

class MyVoice : public SynthVoice
{
public:
  MyVoice()
  : mEnv("amp", [this](){ mOSC.Reset(); }) // Reset callback
  {
  }
  
  void Trigger(double level, bool isRetrigger) override
  {
    if(isRetrigger)
      mEnv.Retrigger(level);
    else
      mEnv.Start(level);
  }
  
  void Release() override
  {
    mEnv.Release();
  }
  
  bool GetBusy() const override
  {
    return mEnv.GetBusy();
  }
  
  void ProcessSamplesAccumulating(sample** inputs, sample** outputs,
                                  int nInputs, int nOutputs,
                                  int startIdx, int nFrames) override
  {
    for(int i = startIdx; i < startIdx + nFrames; i++)
    {
      sample envValue = mEnv.Process(mSustainLevel);
      outputs[0][i] += mOSC.Process(440.0) * envValue;
    }
  }
  
  void SetSampleRateAndBlockSize(double sampleRate, int blockSize) override
  {
    mOSC.SetSampleRate(sampleRate);
    mEnv.SetSampleRate(sampleRate);
    mEnv.SetStageTime(ADSREnvelope<sample>::kAttack, 10.0);  // 10ms
    mEnv.SetStageTime(ADSREnvelope<sample>::kDecay, 100.0);  // 100ms
    mEnv.SetStageTime(ADSREnvelope<sample>::kRelease, 500.0); // 500ms
  }

private:
  FastSinOscillator<sample> mOSC;
  ADSREnvelope<sample> mEnv;
  sample mSustainLevel = 0.7;
};

Envelope Features

// Smooth retrigger without clicks
mEnv.Retrigger(newVelocity);
Uses a fast 3ms ramp when stealing voices

State Variable Filter

Multi-mode filter based on Andy Simper’s design:
Using SVF
#include "SVF.h"

// Template params: <sample type, num channels>
SVF<sample, 2> mFilter {SVF<>::kLowPass, 1000.0};

void OnReset() override
{
  mFilter.SetSampleRate(GetSampleRate());
  mFilter.SetFreqCPS(1000.0);
  mFilter.SetQ(0.707);
}

void ProcessBlock(sample** inputs, sample** outputs, int nFrames) override
{
  mFilter.ProcessBlock(inputs, outputs, 2, nFrames);
}

Filter Modes

IPlug/Extras/SVF.h:32
enum EMode
{
  kLowPass,
  kHighPass,
  kBandPass,
  kNotch,
  kPeak,
  kBell,        // Parametric EQ
  kLowPassShelf,
  kHighPassShelf
};

LFO

Tempo-syncable LFO with multiple waveforms:
Using LFO
#include "LFO.h"

LFO<sample> mLFO;
sample mLFODepth = 0.5;

void OnReset() override
{
  mLFO.SetSampleRate(GetSampleRate());
  mLFO.SetShape(LFO<>::kSine);
  mLFO.SetFreqCPS(2.0); // 2 Hz
  mLFO.SetPolarity(true); // Bipolar (-1 to 1)
}

void ProcessBlock(sample** inputs, sample** outputs, int nFrames) override
{
  sample lfoBuffer[nFrames];
  
  // Process LFO with tempo sync
  mLFO.ProcessBlock(lfoBuffer, nFrames, 
                    mTimeInfo.mPPQPos, 
                    mTimeInfo.mTransportIsRunning, 
                    mTimeInfo.mTempo);
  
  for(int s = 0; s < nFrames; s++)
  {
    sample modAmount = lfoBuffer[s] * mLFODepth;
    // Use modAmount to modulate filter, pitch, etc.
  }
}

LFO Shapes

IPlug/Extras/LFO.h:50
enum EShape
{
  kTriangle,
  kSquare,
  kRampUp,
  kRampDown,
  kSine
};

Tempo Sync

// Set tempo division
mLFO.SetQNScalarFromDivision(LFO<>::k8th); // 1/8 note
mLFO.SetRateMode(true); // Enable sync

Oversampler

HIIR-based oversampling for nonlinear processing:
Using Oversampler
#include "Oversampler.h"

class MyPlugin : public Plugin
{
public:
  MyPlugin(const InstanceInfo& info)
  : Plugin(info, MakeConfig(kNumParams, kNumPresets))
  , mOversampler(k4x, true, 2, 2) // 4x, block mode, 2 in, 2 out
  {
  }
  
  void ProcessBlock(sample** inputs, sample** outputs, int nFrames) override
  {
    // Process with 4x oversampling
    mOversampler.ProcessBlock(inputs, outputs, nFrames, 2, 2, 
      [&](sample** osInputs, sample** osOutputs, int osNFrames)
      {
        // This lambda runs at 4x sample rate
        for(int s = 0; s < osNFrames; s++)
        {
          for(int c = 0; c < 2; c++)
          {
            // Nonlinear processing (distortion, waveshaping, etc.)
            osOutputs[c][s] = std::tanh(osInputs[c][s] * 10.0);
          }
        }
      });
  }
  
  void OnReset() override
  {
    mOversampler.Reset(GetBlockSize());
  }

private:
  OverSampler<sample> mOversampler;
};
Oversampling multiplies CPU usage. Use only when necessary (e.g., for distortion/saturation that produces aliasing).

Parameter Smoothing

Avoid zipper noise with logarithmic parameter smoothing:
Using LogParamSmooth
#include "Smoothers.h"

LogParamSmooth<sample> mGainSmoother {5.0}; // 5ms smoothing

void OnReset() override
{
  mGainSmoother.SetSmoothTime(5.0, GetSampleRate());
}

void ProcessBlock(sample** inputs, sample** outputs, int nFrames) override
{
  sample targetGain = GetParam(kParamGain)->Value() / 100.0;
  
  for(int s = 0; s < nFrames; s++)
  {
    sample smoothedGain = mGainSmoother.Process(targetGain);
    
    for(int c = 0; c < 2; c++)
    {
      outputs[c][s] = inputs[c][s] * smoothedGain;
    }
  }
}

DC Blocker

Remove DC offset from audio:
IPlug/Extras/DCBlocker.h:51
DCBlocker<sample, 2> mDCBlocker; // 2 channels

void ProcessBlock(sample** inputs, sample** outputs, int nFrames) override
{
  // Process audio...
  
  // Remove DC offset
  mDCBlocker.ProcessBlock(inputs, outputs, 2, nFrames);
}

See Also

All DSP utilities are header-only templates, so there’s no linking required. Just #include and use.