📜 OmniScript Scripting Language
[!TIP]
OmniScript is an integrated scripting language compiled to a safe virtual machine bytecode (no allocation, no panicking), allowing you to write custom MIDI processors, modulators, and simple DSP effects without compiling external plugins. You can find ready-to-use examples in omni_engine/examples/scripts/*.omfx.
💡 1. Three Types of Scripts (.omfx)
An .omfx file declares its type in the header via @mode:, which determines where the script is available and what built-in variables it can see:
@mode: audio— a simple DSP effect inserted into an insert chain (e.g., gain, bitcrusher, filter).@mode: midi— a generative MIDI processor (arpeggiator, chord generator, humanizer, scale quantizer).@mode: modulator— a custom modulator in the modulation rack (see/docs/modulators).
A script does not define its own entry function like fn process_note(). Instead, the host directly calls standardized sections of the file if they are present:
| Section | When it is called |
| :--- | :--- |
| @init | Once, upon loading/resetting the script. |
| @block | Once per audio buffer. |
| @sample | Once per sample (sample-accurate). |
| @midi_note_on / @midi_note_off | Upon every incoming MIDI event (only @mode: midi). |
| @modulate | Older, single entry point for a modulator — replaced by @block/@sample writing to the output variable. |
💻 2. Real Examples
Example A: Simple DSP Effect (fx_simple_gain.omfx)
@name: Simple Gain
@desc: Volume control
@mode: audio
@param[0] name="Gain" min=0.0 max=2.0 default=1.0 unit="x"
@sample
spl0 = spl0 * param[0];
spl1 = spl1 * param[0];
Example B: Modulator with Custom Function (mod_step_lfo.omfx)
@name: Step LFO
@mode: modulator
@param[0] name="Rate" min=0.1 max=20.0 default=2.0 unit="Hz"
@param[1] name="Steps" min=2 max=16 default=8
fn saw_wave(p) {
return p * 2.0 - 1.0;
}
@init
phase = 0.0;
@block
n_steps = floor(param[1] + 0.5);
@sample
phase = phase + param[0] / sample_rate;
if phase >= 1.0 { phase = phase - 1.0; }
output = saw_wave(phase);
Syntax note: OmniScript does not have a let keyword — the first assignment to a name automatically declares it (name = expression;). for loops use a Rust-like range syntax: for i in 0..8 { ... }, rather than a classic C-style for(;;).
🛠️ 3. Built-in Variables
All variables in OmniScript are floating-point numbers (f64) — there are no separate u8/f32 types visible from the script (e.g., note/velocity are simply numbers 0–127).
| Variable | Available in mode | Description |
| :--- | :--- | :--- |
| sample_rate | all | The audio engine's sample rate. |
| tempo | all | The current project tempo in BPM. |
| beat_pos | all | The current playback position in the bar. |
| frames | all | The size of the current audio buffer (number of samples). |
| play_state | all | 1.0 when transport is playing, 0.0 when stopped. |
| param[0]…param[63] | all | Parameter values defined by @param[n] in the file header — for reading and writing. |
| spl0 / spl1 | audio only | Audio signal sample, left/right channel. |
| note | midi only | Pitch of the processed MIDI note (0–127). |
| velocity | midi only | Dynamics of the processed MIDI note (0–127). |
| sample_offset | midi only | The offset of the MIDI event in samples relative to the start of the buffer. |
| output | modulator only | The modulation value written by the script, read by the modulation rack. |
⚙️ 4. Built-in Functions
| Function | Description |
| :--- | :--- |
| sin(x), cos(x), tan(x), atan(x), atan2(y, x) | Trigonometric functions. |
| sqrt(x), abs(x), floor(x), ceil(x) | Basic mathematical functions. |
| exp(x), log(x), pow(x, y) | Exponential, natural logarithm, power. |
| min(a, b), max(a, b), clamp(val, min, max) | Value clamping. |
| rand() | Pseudorandom number from the range [0.0, 1.0). |
| emit_note(note, velocity, offset) | Emits a MIDI note with a given pitch and velocity, offset is the sample offset within the current buffer (only @mode: midi). |
| emit_note_off(note, offset) | Emits a note-off message, offset as above (only @mode: midi). |
Additionally, there are constants PI, TWO_PI, E, boolean literals true/false (1.0/0.0), as well as custom user functions declared via fn name(arguments) { ... return expression; }.
⚡ 5. Real-Time Smoothness
OmniScript code is compiled to bytecode and executed by a built-in virtual machine (not an interpreter walking an abstract syntax tree), with limits on operation counts, stack depth, and loop iterations to guarantee audio thread safety. The @sample section is executed once for every sample, ensuring Sample-Accurate Timing.
A guide to running plugins in Omni DAW: In-Process mode with Circuit Breaker protection and full out-of-process Sandbox IPC.
Practical step-by-step guides: Creating your first drum beat, bassline, recording melodies with Scale Fold, chaotic modulation, and track export.
