NeuroScript Language Reference
NeuroScript changes MIDI events on a route. Top-level statements run once for each incoming event. An event passes through unchanged unless a rule changes, emits, or drops it.
Match events
Use when <condition> { … }, optionally followed by else { … }.
when is note and channel == 1 and velocity > 110 {
velocity = 110
}Specific event kinds include note_on, note_off, cc, program, bend, poly_pressure, channel_pressure, clock, start, continue, stop, active_sensing, reset, and sysex. Families include note, aftertouch, channel_voice, realtime, transport, system, and any.
when is [note, cc] { channel = 1 }
when is note and note in C3..C4 { transpose(+12) }
when is cc and controller in [1, 74] { drop }Use ==, !=, <, <=, >, >=, and, or, and not in conditions.
Event fields
Scripts can read kind, channel, note, velocity, controller, value, program, bend, and pressure. kind is read-only. Other fields can be assigned when they apply to the current event.
when is note {
note = clamp(note + 12, 0, 127)
velocity = clamp(velocity + 10, 1, 127)
channel = 2
}Emit and drop
drop discards the current event. emit current emits a snapshot of the current event. Event builders use named arguments and the current event's channel.
when is cc and controller == 1 {
emit cc(controller: 74, value: value)
}
when is note and velocity > 100 {
emit note_on(note: note + 12, velocity: velocity / 2) after 1/8 note
}Available builders include cc, cc14, note_on, note_off, bend, program, bank, aftertouch, poly_pressure, channel_pressure, nrpn, and sysex.
An emitted event does not automatically suppress the incoming event. Add drop when only the emitted event should continue.
Bindings and state
Use let for an immutable value calculated during one event.
when is note {
let semitones = clamp(cc(1) / 11, 0, 12)
note = clamp(note + semitones, 0, 127)
}Use route or channel state when logic must retain a value between events.
state route pedal: Bool = false
state channel hits: Int = 0
when is cc and controller == 64 {
state.pedal = value >= 64
}Supported state types are Int, Bool, Note, Ratio, Duration, Kind, and Policy.
Common helpers
- Pitch:
transpose,transpose_or_drop,octave,octave_or_drop,note_clamp,note_wrap - Velocity and channel:
velocity_scale,velocity_curve,channel_map - Math:
clamp,scale,wrap,min,max,abs,lerp,quantize,deadzone,clamp7,clamp14 - Current route values:
cc(number),cc14(number),note_velocity(note),held_notes()
Timing
Scheduled emits accept durations such as 120ms, 2 beats, or 1/8 note. Timing follows the route's available clock context.
when is note_on {
emit current after 120ms
drop
}Validate and test
Select Validate in the route editor before saving. Use the simulator for isolated events, then test the script with the actual source and destination.
See Musical recipes for additional examples.
