Skip to content

feat(drums): import Rock Band / Clone Hero / YARG drum charts - #1091

Open
mattromano wants to merge 1 commit into
got-feedBack:mainfrom
mattromano:feature/1090-drum-chart-import
Open

mattromano wants to merge 1 commit into
got-feedBack:mainfrom
mattromano:feature/1090-drum-chart-import

Conversation

@mattromano

Copy link
Copy Markdown

What

Closes #1090

Adds a Rock Band / Clone Hero / YARG drum chart importer, and an exporter for the other direction.

  • lib/drumchart.py parses a song folder's drums part (notes.mid PART DRUMS or notes.chart, plus song.ini) with rules ported from YARG.Core: tom markers 110–112, 5-lane → 4-lane pro, disco flip, [ENABLE_CHART_DYNAMICS] accents/ghosts, 2x kick (95 / N 32), Easy/Medium/Hard, star power (116 / S 2), fills (120–124 / S 64), solos (103), sections, and the song.ini delay / .chart Offset. It encodes the result as drum_tab.json, using piece-ids from lib/drums.py (midi_to_piece, so it can't drift from the vocabulary the drums plugin renders) and the feedpak 1.20.0 gameplay keys (a, x2, star_power, fills, solos, levels). It also writes song_timeline.json (tempos, time signatures, beats, sections).
  • lib/drumchart_gen.py covers charts that lack gameplay data. It reduces missing lower levels from Expert (rules fitted on 136 authored charts; marked generated), and generates YARG-style activation fills for charts with star power but no fills (SongChart.AutoGeneration).
  • lib/sngfile.py reads .sng packages (SngFileFormat v1) in pure Python. numpy is test-only in core, so I rewrote the unmask as a 256-byte-period big-int XOR. It refuses directory components in member names and skips videos.
  • scripts/ch_to_sloppak.py takes a folder or .sng and writes a pack with feedpak_version: 1.20.0: one type: drums arrangement pointing at drum_tab.json, the song-level drum_tab alias (spec §7.5 "Multiple drum parts"; arrangements may not be empty), song_timeline, the stems (lone song.ogg → full; CH stems → guitar/bass/drums/vocals/piano/other; crowd dropped), and the cover. A single .ogg per stem is copied verbatim; mixing or transcoding uses core's audio._ffmpeg_cmd().
  • scripts/sloppak_to_ch.py loads a pack through sloppak.load_song (zip/dir, drum parts, song_timeline all handled by core) and writes PART DRUMS for the primary part or --part <id>. That includes the tempo map rebuilt from the beat grid (pickup / delay detection), tom markers, dynamics, Easy–Hard from levels, and SP/fill/solo phrase notes, plus EVENTS sections, song.ini and OGG stems.

Licensing: the parsing rules and auto_fills are ports of YARG.Core, which is LGPL-3.0 (not MIT — I checked its LICENSE). Its MoonscraperChartParser files are © Alexander Ong. lib/drumchart.py / lib/drumchart_gen.py carry the attribution and the note that LGPL-3.0 code may be combined into this AGPL-3.0 project. reduce_level and the exporter are original.

No print() in lib/ (the scripts log through logging, like scripts/lift_keys_notation.py). No JS changes.

feedpak surface

  • This PR does not change how the app reads/writes feedpaks (manifest keys, pack files, folder layout)
  • …or it does, and the spec change landed first via the FEP process — FEP / spec PR: got-feedback/feedpak-spec#68 (once it merges, re-run this PR's checks and the gate goes green)

Dependency: stacked on got-feedBack/feedpak-spec#68 (FEP got-feedBack/feedpak-spec#67). The drum_tab keys this writes (hits[].a, hits[].x2, star_power, fills, solos, levels) are defined there. Please merge that first. All manifest keys written (feedpak_version, title, artist, album, year, duration, cover, stems, arrangements with type/drum_tab, drum_tab, song_timeline) already exist in spec main, and the gate only scans top-level manifest keys. So the feedpak-spec CI job passes today against spec main as well as the spec branch (verified locally, all 4 layers). It won't mechanically block. Holding the merge for the spec PR is a process rule, not a CI one. feedpak-spec-exceptions.yml isn't involved and can't be used here: CI fails any PR that adds to it, and there's no in-repo bypass (docs/feedpak-spec-gate.md).

Core reads nothing new. Streaming the gameplay keys over the highway WS to a drums renderer is a follow-up: today drums.hits_to_wire forwards t/p/v/g/f/k only.

Checklist

  • CHANGELOG.md [Unreleased] updated (user-visible changes)
  • Tests added/updated for new behaviour
  • Commits are DCO signed off (git commit -s)

Tests: tests/test_drumchart.py (26) and tests/test_sloppak_to_ch.py (5), with fixtures in tests/drum_fixtures.py. They use synthetic MIDI/.chart/.sng files and stand-in OGG bytes, so no ffmpeg or audio is needed in CI. Coverage: tempo maps, tom markers, dynamics, 5-lane, disco flip, delay/offset, lower levels, encoding (every pad ↔ piece, x2 only at the top level, empty metadata omitted, payload passes drums.validate_drum_tab and hits_to_wire), reduction rules, auto fills, folder → pack → sloppak.load_song (a drum part, a placeholder-only arrangement list so nothing is graded as fretted, timeline loaded), CH stem mapping, .sng input, CLI errors, a CH → pack → CH round trip (hits, levels, SP/fills/solos, sections, beats within 2 ms; second conversion identical), part selection, unknown pieces, pickup handling, and .sng unmask against a byte-wise reference plus path-traversal stripping.

  • pytest tests/test_drumchart.py tests/test_sloppak_to_ch.py plus the existing drums tests (test_drums_lib, test_sloppak_drum_parts, test_sloppak_drumtab_load, test_midi_import_drums, test_spec_gate): 108 passed.
  • Full suite on Windows: 2789 passed, 10 failed. All 10 are the known Windows-only failures (symlink / feedpak_extension scan / tailwind / plugin asset / db-restore); none touch this change.
  • tools/check_spec_conformance.py --spec <feedpak-spec main> and --spec <spec branch>: OK.
  • A converter-produced pack (zip and dir form) validates with the spec branch's tools/validate.py: PASS.

🤖 Generated with Claude Code

🤖 Generated with Claude Code

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>
@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: b7eafbd4-ad1c-4d5d-b99c-0a31ced95ecc
📥 Commits

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

📒 Files selected for processing: 9
  • CHANGELOG.md
  • lib/drumchart.py
  • lib/drumchart_gen.py
  • lib/sngfile.py
  • scripts/ch_to_sloppak.py
  • scripts/sloppak_to_ch.py
  • tests/drum_fixtures.py
  • tests/test_drumchart.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.

Import Rock Band / Clone Hero / YARG drum charts (notes.mid / notes.chart / .sng) as drum packs

1 participant