Skip to content

Event Types

Event types are not strings. Each type is an opaque Lua light userdata value. To compare against a type you read it from the global sys_event_types table:

if event.type == sys_event_types.noteOn then
-- handle note on
end

The full set of keys in sys_event_types:

sys_event_types = {
none, -- sentinel / untyped
noteOn,
noteOff,
controller,
timer,
script,
}

Never compare against string literals — always use sys_event_types.


Every event sub-table has these two fields regardless of type:

FieldTypeDescription
idopaqueUnique event handle; passed to all manipulate/dispose functions
typeopaqueEvent type; compare against sys_event_types
offsetnumberPosition of the event within the current render block (seconds)

Fired when a key is pressed or a note is triggered programmatically.

FieldTypeDescription
channelnumberMIDI channel (1–16)
notenumberMIDI note number (0–127)
velocitynumberNote velocity (0–127)
function onProcessEvents(blockLen, events)
for i, event in ipairs(events) do
if event.type == sys_event_types.noteOn then
local ch = event.channel
local nn = event.note
local vel = event.velocity
end
end
end

Fired when a key is released.

FieldTypeDescription
channelnumberMIDI channel (1–16)
notenumberMIDI note number (0–127)
velocitynumberRelease velocity (0–127)

Represents an instantaneous controller state change: a CC message, pitch bend, or aftertouch.

FieldTypeDescription
channelnumberMIDI channel (1–16)
controllernumberController number (CC number, or system-defined index)
valuenumberController value

A timer event is generated by the script itself, not from incoming MIDI. It carries no additional fields beyond type and offset. The ID of the event is the same handle used to create and cancel the timer.

Timer creation and management are covered in Timers and Envelopes.


A script event is created by an upstream script to carry an arbitrary payload to downstream processors. It travels through the event queue like any other event.

FieldTypeDescription
dataanyThe payload passed to sys_create_script_event
-- Upstream script: tag the stream with articulation context
sys_create_script_event(event.offset, { isLegato = true })
-- Downstream script: read the payload
if event.type == sys_event_types.script then
local payload = event.data
end

See Script Events for the full usage pattern.


onProcessEvents receives a sequence table (indices 1..n). Each entry is an event sub-table that includes an id field carrying the event’s unique handle. The id is the argument used by all functions that manipulate or emit events. Iterate with ipairs:

function onProcessEvents(blockLen, events)
for i, event in ipairs(events) do
-- event.id : unique event handle
-- event.type : compare against sys_event_types
-- event.offset: block-relative time (seconds)
-- ...type-specific fields
end
end

A noteOn and its matching noteOff carry the same event.id because they refer to the same underlying engine event. This is intentional — it is the mechanism used to finalize a note’s length when the release arrives (see Your First Script for a worked example).