The first real event is a note-off - a status byte plus a note number and a release velocity. Today you parse one, and you give every event a common shape so later kinds slot in beside it.
Parse a note-off event into its channel, note, and velocity.
A note-off tells a synth to release a key. Its status high nibble is 0x8, and
it carries two data bytes: the note number (60 is middle C) and a release
velocity (how fast the key was let up, often ignored). So 0x80 0x3C 0x40 is
“channel 0, release note 60 at velocity 64.”
Because this is the first of a whole family of events, decide its shape now: a
single Event value with a Kind tag, a channel, and the data bytes it needs.
Note-on, control change, and the rest will all reuse this one type, differing only
in the tag and how the data bytes are read - front-loading that shape keeps every
later event a one-line addition instead of a refactor. Pin two channels so the
low-nibble split stays honest.
// a shared shape for every event to cometype Event struct {Kind string // "NoteOff", "NoteOn", ...Channel byteData1 byte // note numberData2 byte // velocity}// 0x8n: read two data bytes as note and velocity