K

MIDI

Read and emit MIDI with the typed message layer.

A device reads MIDI when it declares a midiIn("MIDI") port and emits when it declares a midiOut("MIDI") port. See Ports. Prefer the typed surface below over hand-decoding status bytes.

Reading

CallReturns
ctx.midiInCount()Number of MIDI-in events this block.
ctx.midiEvent(e)A typed MidiMsg for event e (see below).
ctx.midiInOffset(e)Sample offset of event e within the block.
ctx.midiInByte(e, b)Raw status/data byte b (0..3) of event e.
for (let e = 0; e < ctx.midiInCount(); e++) {
  const m = ctx.midiEvent(e);
  if (m.isNoteOn()) alloc.noteOn(m.note);
  else if (m.isNoteOff()) alloc.noteOff(m.note);
}

Warning

ctx.midiEvent returns the SAME MidiMsg instance every call (its fields are overwritten). Copy out anything you need to keep, and don't hold two events at once.

MidiMsg

FieldMeaning
kindA MidiKind (note-on/off, CC, etc).
channelChannel 0..15.
offsetSample offset within the block.
noteNote number (note and poly-aftertouch messages).
velocityVelocity (note-on; 0 for a normalized note-off).
controllerController number (control change).
valueCC value, program number, or pressure amount.
bendCentered pitch bend, -8192..8191 (0 = no bend).
MethodReturns
isNoteOn() / isNoteOff()Note-on / note-off.
isNote()Either note-on or note-off.
isControlChange() / isPitchBend()Control change / pitch bend.
bendNorm()Pitch bend normalized to -1..1.

A note-on with velocity 0 reads back as a note-off (isNoteOff() is true, kind is NoteOff), matching MIDI's running-status convention.

MidiKind

NoteOn, NoteOff, PolyAftertouch, ControlChange, ProgramChange, ChannelPressure, PitchBend, Other.

Emitting

Each helper takes a sample offset within the block. ch defaults to 0. Out-of-range data bytes pin to the edge (0..127) rather than wrapping. Each is a no-op if the device declared no midiOut() port, or the per-block capacity (256 events) is exceeded.

CallEmits
ctx.noteOn(offset, note, vel, ch?)Note-on. vel <= 0 emits a note-off instead.
ctx.noteOff(offset, note, ch?)Note-off.
ctx.cc(offset, controller, value, ch?)Control change (controller, value are 0..127).
ctx.pitchBend(offset, centered, ch?)Pitch bend (centered is -8192..8191, 0 = no bend).
ctx.programChange(offset, program, ch?)Program change (program 0..127).
ctx.channelPressure(offset, pressure, ch?)Channel pressure (0..127).
ctx.polyAftertouch(offset, note, pressure, ch?)Polyphonic key pressure.
ctx.noteOn(0, 60, 100); // middle C, velocity 100, at the block start
ctx.noteOff(64, 60); // release it 64 samples later

Raw emit

For messages the typed helpers don't cover, write the status byte yourself.

ctx.emitMidi(offset, status, d1, d2);

status is the full status byte (0x90 | ch for note-on, 0x80 | ch for note-off, 0xB0 | ch for control change), d1/d2 the data bytes. Use 0 for unused data bytes.

Constants

PITCH_BEND_CENTER is 8192. Common controller numbers read better than literals: CC_MOD_WHEEL, CC_BREATH, CC_FOOT, CC_PORTAMENTO_TIME, CC_VOLUME, CC_BALANCE, CC_PAN, CC_EXPRESSION, CC_SUSTAIN, CC_PORTAMENTO, CC_SOSTENUTO, CC_SOFT_PEDAL, CC_RESONANCE, CC_RELEASE_TIME, CC_ATTACK_TIME, CC_BRIGHTNESS, CC_ALL_SOUND_OFF, CC_RESET_ALL_CONTROLLERS, CC_ALL_NOTES_OFF.

To sync emitted MIDI to the host timeline, read ctx.ppqPosition(), ctx.isPlaying(), and ctx.tempo() from the device API. For note allocation, arps, and chords, see Harmony and sequencing and Synth blocks.