MIDI panel¶
The MIDI panel shows a falling-keys piano roll for the currently-selected MIDI file. Notes fall from the top of the canvas toward a red playhead line near the bottom. A fixed piano keyboard is drawn below the falling notes for orientation.
Coverage¶
- Pitch range: MIDI 21 (A0) to 108 (C8) — the full 88-key piano.
- Keyboard strip is 40 px tall at the bottom of the canvas.
- Playhead line sits at 97 % of the canvas height (just above the keyboard).
Note colouring¶
Notes are coloured by velocity, interpolated across four stops:
| Velocity | Colour |
|---|---|
| 0 | soft blue |
| 64 | green |
| 100 | yellow |
| 127 | loud red |
Hovering a note overlays a 2 px white outline. Hover is cleared when the mouse leaves the panel.
Time axis¶
- Notes fall from top (future) to bottom (past); the playhead is at
97 %from the top. - Grid lines appear every 0.5 s by default. At wider zooms the interval widens:
- viewport > 10 s → 1 s grid.
- viewport > 20 s → 2 s grid.
- Tick labels (e.g.
12.5s) are drawn in the top-left corner of each grid line.
Zoom¶
Mouse wheel zooms the time axis:
- Wheel up → factor
0.8(zoom in — fewer seconds visible). - Wheel down → factor
1.25(zoom out). - Clamped to [0.5 s, 60 s] seconds-per-viewport.
Emits user_interacted, so scrolling also activates the MIDI panel for arrow-key navigation.
Scrub (drag)¶
Left-mouse press and drag vertically to scrub:
- Dragging down moves forward in time (notes fall, playhead advances).
- Dragging up moves backward.
- The drag uses the live pixels-per-second derived from the current zoom, so the scrub speed scales naturally.
Dragging emits user_interacted once at press time and position_changed as the time updates.
Double-click a note¶
Left double-clicking on a note snaps the playhead to that note's start time. The drag state from the preceding press is cancelled so a tiny jitter before release can't move the playhead back. Double-click on empty space has no effect.
Info label¶
Below the canvas, a centered label shows:
Time: 12.456s / 187.4s | Tick: 23913
Where Time is the current playhead position and MIDI file duration, and Tick is the current position expressed in ticks (derived via current_time × sample_rate, rounded).
When no MIDI is loaded, the label reads No MIDI loaded and the canvas paints No MIDI loaded as well.
Keyboard strip¶
- White keys are drawn first as light rectangles with faint grey outlines.
- Black keys are drawn on top as narrower (70 % key width) dark rectangles covering the upper 65 % of the keyboard strip.
- C-octave labels (
C1,C2, ...,C8) are drawn in the keyboard strip at each C.
The keyboard is purely informational — clicks on it do not trigger anything.
Arrow-key stepping (driven from Level 2)¶
When the MIDI panel is the active panel (see §5.3 for how activation works), the following shortcuts apply:
- Left / Right — step 1 tick (
time_resolutionseconds, typically ~0.5 ms at 240 bpm / 480 tpb). - Shift+Left / Shift+Right — step 100 ticks.
Both step amounts are rounded against the MIDI file's duration (set_position clamps to [0, duration]).
Out-of-range display¶
In Locked mode, when the camera drives the MIDI and the resulting MIDI time falls outside the MIDI file's range, the canvas is hidden and the info label changes to a plain message ("MIDI file starts in X.XX s" or "MIDI file ended X.XX s ago"). Navigating MIDI directly (e.g. a drag) restores the normal canvas display.
Signals emitted¶
| Signal | When |
|---|---|
position_changed(float) |
Any time the playhead moves (via drag, arrow keys, double-click, or set_position) |
user_interacted() |
On left-mouse press or wheel (not on programmatic updates like arrow keys driven from Level 2) |