Skip to content

feat(sloppak): project a synthetic Vocals arrangement from vocal_pitch#1031

Open
ChrisBeWithYou wants to merge 1 commit into
mainfrom
core-vocals-arrangement
Open

feat(sloppak): project a synthetic Vocals arrangement from vocal_pitch#1031
ChrisBeWithYou wants to merge 1 commit into
mainfrom
core-vocals-arrangement

Conversation

@ChrisBeWithYou

Copy link
Copy Markdown
Contributor

What

A sloppak carrying a sung-melody sidecar (vocal_pitch, feedpak-spec §7.2) now projects a synthetic, chartless "Vocals" arrangement (type: "vocals") wherever arrangements are enumerated — mirroring the drum-only placeholder contract:

  • load_song(): the melody becomes selectable in the player and visualization plugins can auto-match it via matchesArrangement. The entry carries no notes — the melody itself stays in the sidecar, which vocal visualizers fetch directly. Melody-only paks (no fretted arrangements) now load, deriving song length from the last sung note when the manifest omits a duration; the sidecar read is path-confined and fully permissive (a malformed file only costs the duration fallback, never the load).
  • extract_meta(): the metadata mirror, so the library index and the /api/stats arrangement-count validation agree with the player's arrangement list.

Both sides suppress the projection when the pak already ships an explicit vocal arrangement (editor-authored type, or a vocal-ish name). A chartless vocal-NAMED manifest entry suppresses only the metadata side (it is already counted there) while load_song projects its playable counterpart — counts stay in step.

Why

Without an arrangement identity, a sung run has no honest place to record stats: posting against the selected fretted arrangement index corrupts that arrangement's best_accuracy/best_score and credits progression to the wrong instrument, while posting an out-of-range index is rejected with a 400. instrument_for_arrangement() already maps the name to "vocals", so career/progression attribution works with no further changes once the arrangement exists.

Context

This is the keystone of the vocal highway effort (a new vocal pitch visualizer plugin, feedback-plugin-vocal-highway, currently in development): the plugin renders the vocal_pitch melody with live mic pitch tracking, keys its auto-select on an explicitly vocal arrangement name, and gates ALL of its scoring on this projection existing — precisely so vocal runs can never contaminate fretted-arrangement records. The projection also lights up the existing vocalist POV in the venue scene (resolveVenueInstrumentPov already maps vocal-ish arrangement names).

No spec change: vocal_pitch is an existing feedpak key (§7.2); this PR only derives an arrangement from it. Producers already in the wild: the lyrics-karaoke plugin''s generate flow (and, planned, import-time auto-extraction + editor-authored charts).

Tests

12 new in tests/test_sloppak_vocals_arrangement.py: projection on both sides, dedupe by type and by name, melody-only duration fallback, malformed/path-escaping sidecar permissiveness, load/meta count parity, instrument attribution. Wider sloppak/stats/progression/arrangement/drum slice: 459 passed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EJ6BDHb3K4ZHUDDAHMtKCV

A sloppak carrying a sung-melody sidecar (`vocal_pitch`, feedpak-spec
7.2) previously had no vocal arrangement identity: the melody was not
selectable in the player, visualizers had nothing to auto-match, and -
critically - a sung run had no honest place to record stats. Posting
against the selected fretted arrangement index would corrupt that
arrangement's best_accuracy/best_score and credit progression to the
wrong instrument; posting an out-of-range index is rejected outright.

Fix: project a synthetic chartless "Vocals" arrangement (type "vocals")
wherever arrangements are enumerated, mirroring the drum-only
placeholder contract:

- load_song(): appended after the arrangement loop so the melody is
  selectable and `matchesArrangement` auto-select can key on it. The
  entry carries no notes - the melody itself stays in the sidecar,
  which vocal visualizers fetch directly. Melody-only paks (no fretted
  arrangements) now load, deriving song length from the last sung
  note's end when the manifest omits a duration; the sidecar read is
  path-confined and fully permissive (a malformed file only costs the
  duration fallback, never the load).
- extract_meta(): the metadata mirror, so the library index and the
  /api/stats arrangement-count validation agree with the player's
  arrangement list.

Both sides suppress the projection when the pak already ships an
explicit vocal arrangement (editor-authored `type`, or a vocal-ish
name); a chartless vocal-NAMED manifest entry suppresses only the
metadata side (it is already counted there) while load_song projects
its playable counterpart, keeping the counts in step.

instrument_for_arrangement() already maps the name to "vocals", so
career/progression attribution works with no further changes.

Tests: 12 new (projection both sides, dedupe by type and by name,
melody-only duration fallback, malformed/escaping sidecar permissive-
ness, count parity load_song vs extract_meta, instrument attribution);
sloppak/stats/progression/arrangement/drum slice green (459 passed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EJ6BDHb3K4ZHUDDAHMtKCV
Signed-off-by: ChrisBeWithYou <chris@rifflarr.local>
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@ChrisBeWithYou, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 14 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9a1969e1-20a0-4130-90c9-ed85692bb5e8

📥 Commits

Reviewing files that changed from the base of the PR and between 0e3522c and 1784765.

📒 Files selected for processing (2)
  • lib/sloppak.py
  • tests/test_sloppak_vocals_arrangement.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch core-vocals-arrangement

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