cue:midi — MIDI Note Output

midi(...) sends a MIDI note-on (and optional note-off) when triggered.

It is event-based, not continuous. It turns drawn objects into discrete MIDI note events, delivered via a virtual MIDI port (or a chosen hardware port) that any DAW, synthesiser, or MIDI-capable application can receive.

It works especially well with propagate() — a scatter of shapes in Inkscape becomes a chord or melodic phrase with pitch derived from each element's Y position.


BASIC FORM

midi(ch:, pitch:y, vel:size)

Parameters:

Key Meaning


ch MIDI channel 1–16 (default 1) pitch Pitch source: y maps Y position to note range (see below) vel Velocity source: size maps element size to 1–127 dur Duration in seconds — triggers note-off after this delay lo Lowest MIDI note for pitch:y mapping (default 36 = C2) hi Highest MIDI note for pitch:y mapping (default 84 = C6)


MIDI OUTPUT

Oscilla opens a virtual MIDI port named Oscilla on startup.

Connect any DAW, synth plugin host, or hardware bridge to this port:

To target a hardware port instead of the virtual port:

node server.js --midi-port-index 0

Run node server.js once to see available port indices in the console.


PITCH MAPPING

pitch:y — position-to-note

Y position is mapped linearly to a MIDI note range. Use lo: and hi: to set the range:

midi(ch:1, pitch:y, vel:size) # default lo:36 hi:84 midi(ch:1, pitch:y, lo:48, hi:96, vel:size) # C3–C7 midi(ch:1, pitch:y, lo:60, hi:72, vel:size) # C4–C5 (one octave)

Top of viewport = highest note. Bottom = lowest note.

Fixed note

midi(ch:1, note:60, vel:size) # always middle C


VELOCITY MAPPING

vel:size element visual size → 1–127 vel:64 fixed velocity (integer value, 1–127)


NOTE DURATION

Without dur:, only a note-on is sent. The receiving instrument sustains until it receives its own note-off (or you handle release externally).

With dur:, a note-off is sent automatically after the given time:

midi(ch:1, pitch:y, vel:size, dur:0.5)


TRIGGERS

Key Meaning


trig:auto Send immediately (default) trig:playhead Fire when playhead crosses the element trig:click Fire on user click


USE WITH propagate()

propagate() expands one cue template to every child element in a group, sampling each element's visual properties independently at trigger time.

propagate( midi(ch:1, pitch:y, vel:size, dur:0.3, trig:playhead) )

A cluster of circles becomes a chord. A diagonal scatter becomes a melodic phrase. Vertical position controls pitch; element size controls velocity.

Multiple channels

propagate(midi(ch:1, pitch:y, vel:size, dur:4, trig:playhead)) propagate(midi(ch:2, pitch:y, lo:24, hi:48, vel:size, dur:4, trig:playhead))

Use different channels to route to separate instruments in your DAW.


CLICK BUTTONS

midi(ch:10, note:36, vel:100, trig:click) # kick on ch10

Combined with a visible SVG rectangle, this creates a clickable pad that fires a MIDI note on demand.


MIDI MESSAGE FORMAT

Each trigger sends one or two raw MIDI messages:

Note-on: [0x90 | (ch-1), note, velocity] Note-off: [0x80 | (ch-1), note, 0] (only when dur: is set)

Note and velocity are clamped to 0–127.


SERVER FLAGS

Flag Default Description
--midi-port-index <n> Open hardware port by index instead of virtual
MIDI_PORT_NAME env var Oscilla Name of the virtual port

SUMMARY

midi() converts visual positions into MIDI note events, routing through a virtual port that any DAW or instrument can receive — with pitch from Y position and velocity from element size.

Tip: use ← → or ↑ ↓ to navigate the docs