Skip to content

Plugins

Resonon supports CLAP and VST3 audio plugins for effects processing and virtual instruments. Most built-in effects (delay, filters, overdrive) are native DSP — no plugins needed. Two reverb plugins are bundled; third-party plugins require a scan step.

Resonon ships with two built-in reverb plugins. These are embedded in the binary and auto-extracted on first use — no scan required.

Plugin NameFilenamePlugin ID
RESONON Reverbresonon-reverbcom.resonon.reverb
RESONON Plate Reverbresonon-reverb-platecom.resonon.reverb-plate
// Bundled plugins load instantly -- no plugin_scan() needed
let reverb = Effect("resonon-reverb");
let plate = Effect("resonon-reverb-plate");

Scan standard CLAP and VST3 directories for installed third-party plugins and cache the results. Returns a PluginList — a wrapper with .length(), .filter(name), .get(index), and .data (the raw array of dicts). Each entry has name, id, vendor, and format keys:

let plugins = plugin_scan();
show(plugins.length()); // e.g. 42
PRINT plugins; // formatted table
// Filter by name substring
let reverbs = plugins.filter("reverb");
PRINT reverbs;
// Access raw data
show(plugins.data); // [{name: "Surge XT", id: "org.surge-synth-team...", ...}, ...]

The scan searches OS-specific directories in priority order:

OSFormatSearch Paths (highest priority first)
macOSCLAP/Library/Audio/Plug-Ins/CLAP, ~/Library/Audio/Plug-Ins/CLAP, ~/.clap
macOSVST3/Library/Audio/Plug-Ins/VST3, ~/Library/Audio/Plug-Ins/VST3
LinuxCLAP/usr/lib/clap, /usr/local/lib/clap, ~/.clap
LinuxVST3/usr/lib/vst3, /usr/local/lib/vst3, ~/.vst3
WindowsCLAPC:\Program Files\Common Files\CLAP, C:\Program Files (x86)\Common Files\CLAP
WindowsVST3C:\Program Files\Common Files\VST3, C:\Program Files (x86)\Common Files\VST3

Results are written to a JSON cache file so that name-based loading is fast.

Load an effect plugin (CLAP or VST3). The format is auto-detected — by default CLAP is tried first, then VST3. You can override this globally or per-plugin in config.toml. The name argument is resolved in this order:

  1. Full path — if the name ends in .clap/.vst3 or points to an existing file
  2. Filename — search OS plugin directories for a matching .clap or .vst3 file
  3. Registry name — look up by display name in the scan cache
  4. Error with suggestions — list available plugins
let reverb = Effect("resonon-reverb"); // By filename (bundled)
let shimmer = Effect("Valhalla Shimmer"); // By display name (after scan)
let fx = Effect("/path/to/plugin.clap"); // By full path
let room = Effect("ValhallaRoom"); // Auto-detects CLAP or VST3

For plugins that contain multiple effect types in a single bundle, specify the plugin ID as the second argument:

let chorus = Effect("Multi-FX", "com.vendor.multi-fx.chorus");

If you omit the plugin ID for a multi-plugin bundle, Resonon lists the available IDs.

Instrument(name) / Instrument(name, plugin_id)

Section titled “Instrument(name) / Instrument(name, plugin_id)”

Load an instrument plugin (CLAP or VST3). Format auto-detection, name resolution, and config-based preference follow the same rules as Effect():

let synth = Instrument("Surge XT");
let lead = AudioTrack("lead");
lead.load_instrument(synth);
lead << [C4 E4 G4 C5];

When a plugin cannot be found, Resonon shows which paths were searched and lists available plugins:

Plugin not found: 'Surge'
Searched locations:
- /Library/Audio/Plug-Ins/CLAP/Surge.clap
- ~/Library/Audio/Plug-Ins/CLAP/Surge.clap
- /Library/Audio/Plug-Ins/VST3/Surge.vst3
- ~/Library/Audio/Plug-Ins/VST3/Surge.vst3
Available plugins:
- resonon-reverb
- resonon-reverb-plate
...
Tip: Run plugin_scan() to discover installed plugins.

If multiple plugins share the same display name, Resonon asks you to disambiguate with a plugin ID:

// Specify the exact plugin ID
let delay = Effect("Delay", "com.resonon.delay");
MethodArgsReturnsDescription
.name()StringPlugin display name
.params()NulPrint all parameters as a table
.params(filter)StringNulPrint parameters matching the filter substring
.param(path)StringParamRefGet a parameter reference with .get(), .set(), .set_norm()
.param_get(path)StringNumberRead a parameter’s current value
.param_set(path, value)String, NumberSelfSet a parameter value (chainable)
.param_set_norm(path, value)String, NumberSelfSet a parameter using normalized 0–1 value (chainable)
.supports_gui()BooleanWhether the plugin has a GUI
.show_gui()NulOpen the plugin GUI window
.hide_gui()NulClose the plugin GUI window
.save_state(path)StringSelfSave full plugin state to a file (chainable)
.load_state(path)StringSelfLoad plugin state from a file (chainable)

.params() prints all parameters with their ranges, defaults, and current values:

let reverb = Effect("resonon-reverb");
reverb.params();

Output is a formatted table:

Parameter Range Default Value
─────────────────────────────────────────────────
Room [0.0-1.0] 0.5 0.5
Damp [0.0-1.0] 0.5 0.5
Width [0.0-1.0] 1.0 1.0
Mix [0.0-1.0] 0.33 0.33

.params(filter) accepts a substring to narrow results. This is useful for plugins with many parameters:

let synth = Instrument("Surge XT");
synth.params("osc"); // Only show oscillator-related parameters
synth.params("filter"); // Only show filter parameters

.param_get(path) returns a parameter’s current value. .param(path) returns a parameter reference with .get(), .set(), .set_norm() methods:

show(delay.param_get("Time")); // 0.25
show(filter.param("Cutoff").get()); // 1000.0

.param_set(path, value) sets a parameter and returns the plugin for chaining:

delay.param_set("Time", 0.3)
.param_set("Feedback", 0.6)
.param_set("Mix", 0.8);

.param_set_norm(path, value) sets a parameter using a normalized 0–1 value. The value is mapped to the parameter’s actual range (including non-linear curves for VST3 plugins):

delay.param_set_norm("Time", 0.5) // midpoint of the Time range
.param_set_norm("Mix", 1.0); // maximum mix

Use .param() with << for a concise syntax:

filter.param("Cutoff") << 2000;
filter.param("Resonance") << 3.0;

This shorthand also accepts signals for continuous modulation:

filter.param("Cutoff") << Sine(2).range_exp(400, 4000);
filter.param("Resonance") << Tri(0.5).range(0.5, 4.0);

See Signals & Automation for the full set of signal generators.

.name() returns the plugin’s display name:

let reverb = Effect("resonon-reverb");
show(reverb.name()); // "RESONON Reverb"

Some CLAP and VST3 plugins provide a graphical interface for editing parameters.

let synth = Instrument("Surge XT");
show(synth.supports_gui()); // true or false
synth.show_gui(); // Open the plugin window
synth.hide_gui(); // Close it
plugin_scan();
let synth = Instrument("Surge XT");
let lead = AudioTrack("lead");
lead.load_instrument(synth);
// Open the GUI to design a sound
if synth.supports_gui() {
synth.show_gui();
}
// Save the preset for later
synth.save_state("presets/lead_patch.preset");
lead << [C4 E4 G4 C5];
PLAY;

Save the full plugin state (all parameters and internal state) to a file. Returns the plugin for chaining:

delay.save_state("presets/my_delay.preset");

Load a previously saved state into a plugin instance. Returns the plugin for chaining:

let reverb2 = Effect("resonon-reverb");
reverb2.load_state("presets/my_reverb.preset");

If the preset was saved by a different plugin, a warning is printed but the state is still loaded:

warning: preset 'presets/my_delay.preset' was saved for 'RESONON Delay', loading into 'RESONON Filter'

Both methods are chainable:

let reverb = Effect("resonon-reverb");
reverb.param_set("Room", 0.8)
.save_state("presets/big_room.preset")
.param_set("Room", 0.3);
drums.load_effect(delay);
drums.load_effect(filter);

Effects chain in the order they are loaded. See Effects for the full effect management API.

let synth = Instrument("Surge XT");
let lead = AudioTrack("lead");
lead.load_instrument(synth);

Drums through a filter and delay (native DSP) into a reverb (bundled plugin):

use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");
drums.load_instrument(Sampler(Kit("CR-78")));
drums << [bd sd [bd bd] sd];
// Native DSP effects
let lp = Lowpass(3000, 2.0);
let echo = Delay(0.2, 0.4);
// Bundled reverb plugin
let verb = Reverb(0.6, 0.4, 1.0, 0.3);
drums.load_effect(lp);
drums.load_effect(echo);
drums.load_effect(verb);
PLAY;

Scan for plugins, load an external synth, and configure it:

plugin_scan();
let synth = Instrument("Surge XT");
let lead = AudioTrack("lead");
lead.load_instrument(synth);
// Discover parameters
synth.params("osc");
// Set parameters
synth.param_set("osc/type", 1)
.param_set("osc/pitch", 0);
lead << [C4 _ E4 _ | G4 _ C5 _ | E5 _ G5 _ | C6 _ _ _];
PLAY;

Design a sound with the plugin GUI, save it, and recall it later:

plugin_scan();
let synth = Instrument("Surge XT");
let lead = AudioTrack("lead");
lead.load_instrument(synth);
// Open GUI to design the patch
if synth.supports_gui() {
synth.show_gui();
}
// Play a pattern while tweaking
lead << [C4 E4 G4 C5];
PLAY;
// Save the result
synth.save_state("presets/my_lead.preset");
// Later, in another script:
let synth2 = Instrument("Surge XT");
synth2.load_state("presets/my_lead.preset");