Skip to content

feat(drums): stream drum gameplay metadata on the highway WS - #1105

Open
mattromano wants to merge 2 commits into
got-feedBack:mainfrom
mattromano:feature/1104-stream-drum-gameplay-metadata
Open

mattromano wants to merge 2 commits into
got-feedBack:mainfrom
mattromano:feature/1104-stream-drum-gameplay-metadata

Conversation

@mattromano

Copy link
Copy Markdown

Stacked on #1091 (drum chart import), which writes these keys; spec: got-feedBack/feedpak-spec#68 (FEP #67, feedpak 1.20.0). Review/merge after both — until then this PR's diff includes #1091's commit.

What

Closes #1104

The highway WebSocket now delivers the feedpak 1.20.0 drum gameplay metadata so a drums renderer can read it from bundle.drumTab:

  • lib/drums.py: hit_to_wire keeps a (accent) and x2 (double kick). Sanitised like the other keys: a hit is never sent both accented and ghosted (spec forbids the pair; the ghost wins), and x2 only appears on a kick in the top-level hits[] (top=False for level hits, per spec). New ranges_to_wire (star_power / fills / solos → sorted {start_time, end_time}, malformed / reversed ranges dropped) and levels_to_wire (closed id list easy/medium/hard, unknown ids ignored, empty levels dropped).
  • lib/routers/ws_highway.py: the drum_tab frame carries the non-empty range lists and a levels index {id: {total, generated}}; each level's hits follow the top-level drum_hits as drum_level_hits chunks ({level, data, total}, 500 per frame, like drum_hits), so a long level stays under frame limits. Works per drum part (the selected part's tab is streamed).
  • static/highway.js: the drum_tab case copies star_power / fills / solos and builds levels.<id> = {hits: [], generated}; a new drum_level_hits case appends to the announced level only (unknown ids, including __proto__, are ignored).

Strictly additive: a tab without the keys produces exactly the old frames (tested), and a client predating this ignores the new frame type and keeps playing hits[] (the full part, x2 kicks included — the spec's intended fallback). The drums plugin PRs (feedBack-plugin-drums feature/ISSUE-yarg-scoring-engine and its stack) consume this.

feedpak surface

Checklist

  • CHANGELOG.md [Unreleased] updated (user-visible changes)
  • Tests added/updated for new behaviour
    • tests/test_drums_lib.py (+5): a/x2 on the wire, accent+ghost, x2 only on top-level kicks, range sanitising, level sanitising.
    • tests/test_highway_ws_drum_metadata.py (new, 3): real app over a temp DLC — metadata frames, level chunk order/contents/totals, unchanged frames for a pre-1.20.0 tab, 500-per-frame chunking.
    • tests/js/drum_tab_metadata.test.js (new, 3): the highway.js cases in a vm sandbox.
    • Results: drum-related suites 65 passed; full pytest 2797 passed, 10 failed — all pre-existing Windows-only failures (symlink / tailwind / feedpak_extension / plugin_asset / settings-export), none touched here; node --test tests/js/drum_tab_metadata.test.js 3/3; npx eslint static/highway.js tests/js/drum_tab_metadata.test.js clean (only the existing max-lines warning on highway.js).
    • Manual: a pack built with scripts/ch_to_sloppak.py from a synthetic chart (5 SP phrases, 3 fills, a solo, 3 levels) played in the drums plugin; the difficulty menu offered Easy..Expert+ and star-power notes rendered — see the plugin PR screenshots.
  • Commits are DCO signed off (git commit -s)

🤖 Generated with Claude Code

mattromano and others added 2 commits October 9, 2026 17:08
Rhythm-game drum charts are the largest pool of authored drum parts, but
core had no way to bring one in. Add a converter for CH/YARG song folders
(notes.mid PART DRUMS or notes.chart, song.ini, audio) and .sng packages,
and an exporter back to a CH folder.

- lib/drumchart.py parses the drums part with rules ported from
  YARG.Core (LGPL-3.0, attributed): tom markers, 5-lane -> pro, disco
  flip, dynamics, 2x kick, song.ini delay, all four difficulties, star
  power / fills / solos / sections. It encodes to drum_tab.json via
  lib/drums.py piece-ids and the feedpak 1.20.0 drum gameplay metadata
  (a, x2, star_power, fills, solos, levels), and to song_timeline.json.
- lib/drumchart_gen.py reduces missing lower levels from Expert (marked
  generated) and generates YARG-style activation fills.
- lib/sngfile.py reads .sng packages (no numpy: lib must not need it).
- scripts/ch_to_sloppak.py writes a type: drums arrangement with the
  song-level drum_tab alias and a song_timeline; scripts/sloppak_to_ch.py
  exports a pack's drum part (via sloppak.load_song) as notes.mid.

Depends on the feedpak-spec 1.20.0 drum gameplay metadata PR for the
drum_tab keys; every manifest key written is already in the spec, so the
feedpak-spec gate passes against spec main and the spec branch alike.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: mattromano <42412983+mattromano@users.noreply.github.com>
The drum_tab stream now carries the feedpak 1.20.0 gameplay keys the
chart importer writes, so a drums renderer can score a chart the way a
rhythm game does: drum_hits keep the accent (a) and double-kick (x2)
flags, the drum_tab frame carries star_power / fills / solos and a
levels index, and each easier level's hits follow as chunked
drum_level_hits frames. highway.js keeps all of it on bundle.drumTab.

Everything is sanitised like the hits already are and strictly
additive: a tab without the keys streams the exact frames it did
before, and older clients ignore the new frame type and play hits[].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: mattromano <42412983+mattromano@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 35 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 06843b71-857f-4550-badc-7e31e08f9287
📥 Commits

Reviewing files that changed from the base of the PR and between eef58c8 and f060eb6.

📒 Files selected for processing: 15
  • CHANGELOG.md
  • lib/drumchart.py
  • lib/drumchart_gen.py
  • lib/drums.py
  • lib/routers/ws_highway.py
  • lib/sngfile.py
  • scripts/ch_to_sloppak.py
  • scripts/sloppak_to_ch.py
  • static/highway.js
  • tests/drum_fixtures.py
  • tests/js/drum_tab_metadata.test.js
  • tests/test_drumchart.py
  • tests/test_drums_lib.py
  • tests/test_highway_ws_drum_metadata.py
  • tests/test_sloppak_to_ch.py
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mattromano

Copy link
Copy Markdown
Author

Marking ready: this is part of the drum gameplay metadata chain (feedpak-spec#68 → feedBack#1105 streams it → feedBack#1091 imports it) that got-feedBack/feedBack-plugin-drums#25 uses for star power, fills, solos and per-difficulty levels.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stream drum gameplay metadata (feedpak 1.20.0) on the highway WebSocket

1 participant