Skip to content

feat(gp2rs): emit lyrics + vocal_pitch sidecars from GP vocal tracks#1037

Open
ChrisBeWithYou wants to merge 1 commit into
mainfrom
gp-vocal-sidecar-wire
Open

feat(gp2rs): emit lyrics + vocal_pitch sidecars from GP vocal tracks#1037
ChrisBeWithYou wants to merge 1 commit into
mainfrom
gp-vocal-sidecar-wire

Conversation

@ChrisBeWithYou

@ChrisBeWithYou ChrisBeWithYou commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

What

GP imports currently drop the vocal melody: the vocal-track detector and the pitch-sidecar converter both exist, but convert_file() never calls the converter, so a GP file with a charted vocal part yields only the legacy vocals arrangement XML and no karaoke-ready sidecars.

This wires the orphaned path in, mirroring the keys-notation sidecar pattern one-for-one:

  • convert_file() vocal branch now emits <stem>.lyrics.json (spec §7.1) and <stem>.vocal_pitch.json (spec §7.2) next to the vocals XML, best-effort (a sidecar failure never breaks the XML conversion).
  • Lyrics are projected from the just-built vocals XML so sidecar timing is guaranteed in lockstep with the arrangement (same tie extension, same rounding).
  • Suffix-semantics trap handled: the vocals-XML lyric convention uses trailing + = join to next token, while feedpak §7.1 uses trailing + = end of line. A passthrough would turn every joined word into a line break, so XML + maps to §7.1 - (both mean join). Line-end + is never emitted — GP stores lyrics per beat with no derivable line structure.
  • convert_vocal_track_to_pitch_sidecar() gains opt-in require_lyric=False, used only for vocal tracks with zero lyric text (pitch sidecar only). With lyrics present, alignment behavior is unchanged.
  • New attach_vocal_sidecars_to_sloppak() — the assembly-step companion to attach_notation_to_sloppak(): writes both sidecars into a directory-form pak, sets manifest lyrics / lyrics_source: "authored" / vocal_pitch, validates shapes, and never clobbers an existing key or file. (The editor plugin's pak save needs a small follow-up PR to call it, exactly as it did for notation — tracked on the org board.)
  • lib/gp2rs_gpx.py registered in tools/check_spec_conformance.py READERS (the spec gate's self-check requires it; all keys touched are spec-declared).

Tests

  • 9 new tests: require_lyric=False, XML→lyrics projection (shape/suffix/bad-XML), convert_file end-to-end (vocal+lyrics → both sidecars; guitar-only → none; lyric-less vocal → pitch only), attach helper (writes+manifest, no-clobber, rejects bad payloads).
  • tests/test_gp2rs_gpx.py: 99 passed. GP-adjacent suites (gp2notation/gp2rs/drums/xml-encoding/autosync): 175 passed.
  • Full suite: 2756 passed; the 10 remaining failures reproduce identically on pristine main in this environment (env-dependent: tailwind/plugin-loader/startup).

Notes for review

  • Provenance: GP-derived lyrics use lyrics_source: "authored" (from an authored chart); the lyric_transcription/pitch_extraction blocks are reserved for automated engines and are deliberately not written (asserted in tests).
  • §7.2 frames vocal_pitch as lyric-aligned; the lyric-less-track case (pitch-only sidecar) is slightly ahead of that framing — flagged for a reviewer sanity-check. The upcoming unified vocal-track FEP formalizes this case.
  • Scope: GPIF (.gp/.gpx) only — the GP3/4/5 binary path has no vocal converter today.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Vocal tracks now generate karaoke lyrics and vocal pitch sidecar files.
    • Lyric-less vocal melodies can generate pitch data without lyric text.
    • Sidecars can be added to sloppak packages with manifest metadata and source information.
  • Bug Fixes
    • Sidecar generation errors no longer prevent vocals XML output.
    • Existing lyric content is preserved when attaching sidecars.
  • Validation
    • Added coverage for lyric conversion, malformed tokens, vocal-only output, and invalid sidecar data.

GP files with a vocal track previously produced only the legacy vocals
arrangement XML; the melody sidecar converter existed but was never
wired, so imported paks had no karaoke-ready pitch data.

- convert_file() now calls _emit_vocal_sidecars() after writing the
  vocals XML (best-effort: a sidecar failure never breaks conversion,
  matching the notation-sidecar posture)
- lyrics sidecar is projected from the just-built vocals XML so timing
  stays in lockstep; the XML lyric convention's trailing '+' (join) is
  mapped to the spec 7.1 '-' (join) - a passthrough would have turned
  every joined word into a line break
- convert_vocal_track_to_pitch_sidecar() gains require_lyric=False for
  lyric-less melody tracks (pitch sidecar only)
- attach_vocal_sidecars_to_sloppak() added as the assembly-step helper
  (companion to attach_notation_to_sloppak): writes the sidecars into a
  directory-form pak and sets manifest lyrics/lyrics_source/vocal_pitch
  with no-clobber guards
- gp2rs_gpx registered in the spec-conformance READERS list

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: ChrisBeWithYou <chris@rifflarr.local>
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 202947b7-0871-4418-bf00-33520c00a1d3

📥 Commits

Reviewing files that changed from the base of the PR and between 8297afc and 30f10c8.

📒 Files selected for processing (3)
  • lib/gp2rs_gpx.py
  • tests/test_gp2rs_gpx.py
  • tools/check_spec_conformance.py

📝 Walkthrough

Walkthrough

GPX vocal conversion now supports lyric-less pitch notes, emits lyrics and vocal pitch sidecars, and attaches validated sidecars to sloppak directories and manifests with provenance metadata.

Changes

Vocal karaoke sidecars

Layer / File(s) Summary
Lyric-less pitch conversion
lib/gp2rs_gpx.py, tests/test_gp2rs_gpx.py
convert_vocal_track_to_pitch_sidecar() conditionally accepts lyric-less beats and retains its default lyric requirement.
Sidecar generation and conversion
lib/gp2rs_gpx.py, tests/test_gp2rs_gpx.py
Vocal XML is converted to feedpak lyric payloads, pitch and lyric JSON files are emitted for vocal tracks, and sidecar failures do not prevent vocals XML output.
Sloppak manifest attachment
lib/gp2rs_gpx.py, tests/test_gp2rs_gpx.py, tools/check_spec_conformance.py
Validated sidecars are attached without overwriting claimed lyrics, manifest provenance keys are updated, and the conformance reader allowlist includes the new manifest writer.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GPX_converter
  participant vocals_XML
  participant sidecar_writer
  participant sloppak_manifest
  GPX_converter->>vocals_XML: write vocal track XML
  GPX_converter->>sidecar_writer: generate lyric and pitch payloads
  sidecar_writer->>sloppak_manifest: attach sidecars and manifest keys
  sloppak_manifest-->>GPX_converter: preserve existing claimed lyrics
Loading

Possibly related issues

  • got-feedBack/feedBack issue 220 — Extends vocal pitch conversion with lyric-less support and vocal_pitch.json integration.

Suggested reviewers: byrongamatos

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.62% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: emitting lyrics and vocal_pitch sidecars from GP vocal tracks.
Description check ✅ Passed It covers the change, the feedpak impact, and tests; the template’s checklist items are missing, but the core required info is present.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch gp-vocal-sidecar-wire

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.

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.

1 participant