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
The header defines the parameter enum and plugin class:
#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:
#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
}
Initialize Parameters
Call GetParam(index)->InitDouble() or similar methods to set parameter properties
Create Graphics
Use mMakeGraphicsFunc lambda to instantiate the IGraphics interface
Build UI Layout
Use mLayoutFunc lambda to attach controls to specific screen regions
Parameter Initialization Methods
The InitDouble method accepts these parameters:
Parameter Type Description name const char*Display name for the parameter defaultVal doubleInitial value minVal doubleMinimum value maxVal doubleMaximum value step doubleIncrement step for fine control label const char*Unit label (e.g., ”%”, “dB”, “Hz”)
Audio Processing
The ProcessBlock method implements realtime audio processing:
#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
Get Parameter Value
Retrieve the current gain value using GetParam(kGain)->Value()
Determine Channel Count
Use NOutChansConnected() to handle flexible I/O configurations
Process Samples
Iterate through frames and channels, applying the gain multiplier
Plugin Configuration (config.h)
The config file defines plugin metadata and format settings:
#define PLUG_NAME "IPlugEffect"
#define PLUG_MFR "AcmeInc"
#define PLUG_VERSION_HEX 0x 00010000
#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
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:
Control Purpose Example IVKnobControlRotary knob Gain control ITextControlStatic text Title and version AttachPanelBackgroundBackground color Gray panel AttachCornerResizerResize handle Scale 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
Build the standalone app
Open the appropriate project file for your platform:
macOS : IPlugEffect-macOS.xcodeproj
Windows : IPlugEffect.sln
Linux : Use the included makefiles
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