Skip to main content
IPlugEffect is the simplest iPlug2 example - a volume control effect that demonstrates the core concepts of parameter handling, audio processing, and UI construction.

What You’ll Learn

Parameter Definition

How to declare and initialize plugin parameters

Audio Processing

Implementing realtime-safe ProcessBlock method

UI Construction

Building a simple interface with IGraphics

Plugin Configuration

Setting up plugin metadata and formats

Project Structure

The IPlugEffect example consists of three core files:
Examples/IPlugEffect/
├── IPlugEffect.h         # Plugin class and parameter declarations
├── IPlugEffect.cpp       # Implementation and UI layout
├── config.h              # Plugin metadata and settings
└── resources/            # Fonts and assets

Plugin Header (IPlugEffect.h)

The header defines the parameter enum and plugin class:
IPlugEffect.h
#pragma once

#include "IPlug_include_in_plug_hdr.h"

const int kNumPresets = 1;

enum EParams
{
  kGain = 0,
  kNumParams
};

using namespace iplug;
using namespace igraphics;

class IPlugEffect final : public Plugin
{
public:
  IPlugEffect(const InstanceInfo& info);

#if IPLUG_DSP
  void ProcessBlock(sample** inputs, sample** outputs, int nFrames) override;
#endif
};
Parameters are defined as an enum starting at 0. The kNumParams entry automatically counts the total number of parameters.

Plugin Implementation

Constructor and Parameter Initialization

The constructor initializes parameters and builds the UI:
IPlugEffect.cpp
#include "IPlugEffect.h"
#include "IPlug_include_in_plug_src.h"
#include "IControls.h"

IPlugEffect::IPlugEffect(const InstanceInfo& info)
: iplug::Plugin(info, MakeConfig(kNumParams, kNumPresets))
{
  // Initialize the gain parameter
  GetParam(kGain)->InitDouble("Gain", 0., 0., 100.0, 0.01, "%");

#if IPLUG_EDITOR
  mMakeGraphicsFunc = [&]() {
    return MakeGraphics(*this, PLUG_WIDTH, PLUG_HEIGHT, PLUG_FPS, 
                        GetScaleForScreen(PLUG_WIDTH, PLUG_HEIGHT));
  };
  
  mLayoutFunc = [&](IGraphics* pGraphics) {
    pGraphics->AttachCornerResizer(EUIResizerMode::Scale, false);
    pGraphics->AttachPanelBackground(COLOR_GRAY);
    pGraphics->LoadFont("Roboto-Regular", ROBOTO_FN);
    
    const IRECT bounds = pGraphics->GetBounds();
    const IRECT innerBounds = bounds.GetPadded(-10.f);
    
    // Title text
    pGraphics->AttachControl(new ITextControl(
      innerBounds.GetMidVPadded(50), 
      "Hello iPlug 2!", 
      IText(50)
    ));
    
    // Gain knob
    pGraphics->AttachControl(new IVKnobControl(
      innerBounds.GetCentredInside(100).GetVShifted(-100), 
      kGain
    ));
    
    // Version info
    const IRECT versionBounds = innerBounds.GetFromTRHC(300, 20);
    WDL_String buildInfoStr;
    GetBuildInfoStr(buildInfoStr, __DATE__, __TIME__);
    pGraphics->AttachControl(new ITextControl(
      versionBounds, 
      buildInfoStr.Get(), 
      DEFAULT_TEXT.WithAlign(EAlign::Far)
    ));
  };
#endif
}
1

Initialize Parameters

Call GetParam(index)->InitDouble() or similar methods to set parameter properties
2

Create Graphics

Use mMakeGraphicsFunc lambda to instantiate the IGraphics interface
3

Build UI Layout

Use mLayoutFunc lambda to attach controls to specific screen regions

Parameter Initialization Methods

The InitDouble method accepts these parameters:
ParameterTypeDescription
nameconst char*Display name for the parameter
defaultValdoubleInitial value
minValdoubleMinimum value
maxValdoubleMaximum value
stepdoubleIncrement step for fine control
labelconst char*Unit label (e.g., ”%”, “dB”, “Hz”)

Audio Processing

The ProcessBlock method implements realtime audio processing:
IPlugEffect.cpp
#if IPLUG_DSP
void IPlugEffect::ProcessBlock(sample** inputs, sample** outputs, int nFrames)
{
  // Get the current parameter value (0-100)
  const double gain = GetParam(kGain)->Value() / 100.;
  const int nChans = NOutChansConnected();
  
  // Process each sample
  for (int s = 0; s < nFrames; s++) {
    for (int c = 0; c < nChans; c++) {
      outputs[c][s] = inputs[c][s] * gain;
    }
  }
}
#endif
ProcessBlock must be realtime-safe:
  • No memory allocations
  • No mutex locks
  • No file I/O
  • No system calls

Understanding the Processing Loop

1

Get Parameter Value

Retrieve the current gain value using GetParam(kGain)->Value()
2

Determine Channel Count

Use NOutChansConnected() to handle flexible I/O configurations
3

Process Samples

Iterate through frames and channels, applying the gain multiplier

Plugin Configuration (config.h)

The config file defines plugin metadata and format settings:
config.h
#define PLUG_NAME "IPlugEffect"
#define PLUG_MFR "AcmeInc"
#define PLUG_VERSION_HEX 0x00010000
#define PLUG_VERSION_STR "1.0.0"
#define PLUG_UNIQUE_ID 'Ipef'
#define PLUG_MFR_ID 'Acme'
#define PLUG_URL_STR "https://iplug2.github.io"
#define PLUG_EMAIL_STR "spam@me.com"
#define PLUG_COPYRIGHT_STR "Copyright 2025 Acme Inc"
#define PLUG_CLASS_NAME IPlugEffect

#define BUNDLE_NAME "IPlugEffect"
#define BUNDLE_MFR "AcmeInc"
#define BUNDLE_DOMAIN "com"

// Audio I/O configuration
#define PLUG_CHANNEL_IO "1-1 2-2"  // Mono->Mono, Stereo->Stereo

// Plugin characteristics
#define PLUG_LATENCY 0
#define PLUG_TYPE 0                 // 0=Effect, 1=Instrument
#define PLUG_DOES_MIDI_IN 0
#define PLUG_DOES_MIDI_OUT 0
#define PLUG_DOES_MPE 0
#define PLUG_DOES_STATE_CHUNKS 0
#define PLUG_HAS_UI 1
#define PLUG_WIDTH 600
#define PLUG_HEIGHT 600
#define PLUG_FPS 60
#define PLUG_SHARED_RESOURCES 0
#define PLUG_HOST_RESIZE 0

// VST3 specific
#define VST3_SUBCATEGORY "Fx"

// CLAP specific
#define CLAP_DESCRIPTION "A simple audio effect for modifying gain"
#define CLAP_FEATURES "audio-effect"

#define ROBOTO_FN "Roboto-Regular.ttf"
Change PLUG_UNIQUE_ID and PLUG_MFR_ID to unique 4-character codes for your own plugins. These must be registered with Apple for AudioUnit distribution.

Key Configuration Options

Channel I/O Format

The PLUG_CHANNEL_IO string defines supported configurations:
"1-1 2-2"      // Mono or Stereo
"2-2"          // Stereo only
"0-2"          // Generator (no input)
"1-1 2-2 4-4"  // Mono, Stereo, or Quad

Plugin Type

#define PLUG_TYPE 0  // Effect
#define PLUG_TYPE 1  // Instrument

Building the UI

Common IGraphics Controls

The example uses several standard controls:
ControlPurposeExample
IVKnobControlRotary knobGain control
ITextControlStatic textTitle and version
AttachPanelBackgroundBackground colorGray panel
AttachCornerResizerResize handleScale UI

IRECT Layout System

iPlug2 uses IRECT for positioning controls:
const IRECT bounds = pGraphics->GetBounds();           // Full window
const IRECT padded = bounds.GetPadded(-10.f);          // Inset 10px
const IRECT centered = padded.GetCentredInside(100);   // 100x100 center
const IRECT shifted = centered.GetVShifted(-100);      // Move up 100px

GetBounds()

Returns the full control area

GetPadded(px)

Insets by specified pixels (negative values)

GetCentredInside(w, h)

Creates centered rectangle of given size

GetVShifted(dy)

Moves vertically by dy pixels

Running the Example

1

Navigate to the example

cd Examples/IPlugEffect
2

Build the standalone app

Open the appropriate project file for your platform:
  • macOS: IPlugEffect-macOS.xcodeproj
  • Windows: IPlugEffect.sln
  • Linux: Use the included makefiles
3

Run and test

Build and launch the standalone app. Adjust the gain knob to hear the effect on generated audio or input signals.

Customization Ideas

Add More Parameters

Add pan, mix, or filter parameters to the EParams enum

Different Processing

Implement EQ, delay, or distortion in ProcessBlock

Enhanced UI

Add meters, graphs, or custom graphics

Stereo Processing

Implement stereo-specific effects like width control

Next Steps

IPlugInstrument

Build a synthesizer with MIDI input

IPlugControls

Explore all available UI controls

API Reference

Dive into the Plugin class documentation