Conversation
94150e6 to
0b9abba
Compare
0b9abba to
252dddd
Compare
| events.push((n.start_tick, true, n.pitch, n.velocity as f32 / 127.0)); | ||
| events.push((n.end_tick, false, n.pitch, 0.0)); | ||
| } | ||
| events.sort_by_key(|e| (e.0, !e.1)); // note-offs before note-ons at same tick |
There was a problem hiding this comment.
Inverted sort order: note-ons sorted before note-offs
Medium Severity
The sort key (e.0, !e.1) produces the opposite of the intended order. Since e.1 is is_on: bool and Rust orders false < true, negating it with ! causes note-ons (!true = false) to sort before note-offs (!false = true) at the same tick. The comment says "note-offs before note-ons at same tick" but the code does the reverse. The fix is to use (e.0, e.1) instead of (e.0, !e.1). This causes the is_note_off check in the playback loop to miss transition boundaries where one note ends and another begins at the same tick, potentially delaying track switches.
| current_time, | ||
| ); | ||
| pending_track_switch = None; | ||
| } |
There was a problem hiding this comment.
scheduled_time not reset on track switch causes drift
Medium Severity
When a track switch occurs (binding swap, section boundary note-off, or track exhaustion), command_index is repositioned via find_commands_at_time but scheduled_time is not reset to match the new track's cumulative timeline. Subsequent commands add their wait_before to the stale scheduled_time, producing a persistent timing offset equal to scheduled_time minus the new track's cumulative time at the new index, which can be up to one command's wait_before duration.


Note
Medium Risk
Substantial refactor of core MIDI parsing and playback coordination (new part normalization, scoring, and planned track assignment), which could change timing/selection behavior and introduce playback regressions across varied MIDI files.
Overview
Refactors MIDI handling from track-based, runtime re-ranking to part-based normalization and precomputed planning: MIDI is normalized into
(channel, program)Parts (handling program changes), scored to pick primary/secondary candidates, converted into rumble tracks, and assigned via a skyline-basedPlaybackPlanrather than the removedTrackMergeController/ranking thread.Playback now supports runtime keyboard controls (
Sswap L/R,1/2cycle candidates,Qquit) viacrossterm, and updates scheduling/HID output (scheduled-time sleeps, same-tick command coalescing, write throttling).Adds developer tooling: a Rust devcontainer with Bluetooth/DBus dependencies, a
scripts/pair-joycons.shhelper for Bluetooth pairing, and.gitattributesenforcing LF for*.sh; also adds thecrosstermdependency and expands the public prelude exports.Written by Cursor Bugbot for commit 252dddd. This will update automatically on new commits. Configure here.