reaper-jsfx-core

SKILL.md

REAPER JSFX Core

Foundation skill for writing JSFX audio plugins in REAPER. This skill covers the EEL2 language, code structure, and performance optimization patterns essential for any JSFX plugin.

Always load this skill when working with JSFX. Other JSFX skills (audio, synth, midi, ui) build upon this foundation.

Rules

Rule Description
language EEL2 syntax, operators, math functions, loops, strings, user-defined functions
sections Code sections (@init, @slider, @block, @sample, @gfx, @serialize) and execution flow
variables Special variables, slider definitions, transport state, PDC, shared memory
performance CPU optimization, denormal handling, branchless patterns, memory efficiency
libraries Creating and using .jsfx-inc include files, namespacing, code organization

Official Documentation

Key Principles

1. Performance First

JSFX runs in real-time audio context. The @sample section executes thousands of times per second (e.g., 44,100 times/sec at 44.1kHz). Every operation matters:

// BAD: Branch in sample loop
@sample
condition ? (
  spl0 *= gain1;
) : (
  spl0 *= gain2;
);

// GOOD: Branchless - compute gain once in @slider
@slider
gain = condition ? gain1 : gain2;

@sample
spl0 *= gain;

2. Precompute in Appropriate Sections

Move calculations to the earliest possible section:

Section Runs Use For
@init Once on load/reset Memory allocation, lookup tables, constants
@slider On parameter change Coefficient calculation, derived values
@block Per audio block (~1-10ms) Tempo sync, MIDI preprocessing
@sample Per sample (44100+/sec) Only essential sample processing

3. Variables Are Global by Default

EEL2 variables don't need declaration and are global. Use meaningful names and conventions:

// Slider-derived values: prefix with slider name
slider1:volume_db=0<-60,12,0.1>Volume (dB)
@slider
volume_db_lin = 10^(volume_db/20);  // Linear gain from dB

// State variables: descriptive names
filter_z1 = 0;  // Filter state (z^-1)
env_current = 0;  // Envelope current value

// Constants: UPPER_CASE or prefix
TWO_PI = 2 * $pi;
MAX_DELAY_SAMPLES = 192000;

4. Use Memory for Buffers, Variables for State

@init
// Buffers in memory (addressable array)
delay_buffer = 0;  // Start at memory offset 0
delay_length = 48000;
freembuf(delay_buffer + delay_length);  // Inform memory manager

// State in named variables (faster access)
delay_write_pos = 0;
delay_read_pos = 0;

@sample
// Memory access for buffer
delay_buffer[delay_write_pos] = spl0;

// Variable access for state
delay_write_pos += 1;
delay_write_pos >= delay_length ? delay_write_pos = 0;

Quick Reference

Task Rule
Understanding EEL2 syntax language
Structuring plugin code sections
Using sliders and special vars variables
Optimizing CPU performance performance
Creating reusable code libraries

Minimal Plugin Template

desc:My Effect
tags:effect utility

slider1:gain_db=0<-24,24,0.1>Gain (dB)

in_pin:left input
in_pin:right input
out_pin:left output
out_pin:right output

@init
// Initialize state here

@slider
// Recalculate coefficients when sliders change
gain_lin = 10^(gain_db/20);

@sample
// Process audio
spl0 *= gain_lin;
spl1 *= gain_lin;
Weekly Installs
3
First Seen
12 days ago
Installed on
opencode3
gemini-cli3
claude-code3
github-copilot3
codex3
kimi-cli3