Skip to content

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 { … }.

neuroscript
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.

neuroscript
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.

neuroscript
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.

neuroscript
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.

neuroscript
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.

neuroscript
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.

neuroscript
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.

Neurode MIDI for macOS, iPhone, and iPad