mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-08-13 12:20:09 +00:00
Stream the rig library to the client
The core rig reader landed its reading half but not its exposing half:
the bindings shipped (`base_rig`, per-change `rig`) while the library
they are references INTO stayed server-side on LoadedSloppak.rigs with
no consumer at all. A client could see that a change binds
"grand-piano" and had no way to learn what that was.
Add a `rigs` WS message carrying the library whole and verbatim, and put
each drum part's resolved `tones` binding on its `song_info.drum_parts`
entry — the drum half had the same gap, since the loader resolved the
binding in P3 and the wire payload was still `{id, name}`.
Sent whenever the pack ships a library, deliberately NOT gated on this
arrangement having tone changes: a pack can bind sound to its drum parts
alone via `drum_tones` and still need the library.
Verbatim matters here. Core selects no realization and applies no
`intent.gm` floor, so the consumer that voices the part needs the whole
block to make that choice — including the unknown `role`/`engine`/`kind`
values and `ext` namespaces §7.9 requires a Reader to preserve.
Client side: `hwState.rigs` / `toneBaseRig`, `getRigs()` /
`getToneBaseRig()`, and `bundle.rigs` / `bundle.toneBaseRig` so
renderers reach them the same way they reach every other chart array,
with both reset paths clearing them between songs.
Packs that bind no rig are byte-identical on the wire — no `rigs`
message, no `base_rig`, no `rig`, no `tones` on a drum part.
Signed-off-by: gionnibgud <gionnibgud@gmail.com>
This commit is contained in:
@@ -684,13 +684,14 @@ The highway WebSocket at `/ws/highway/{filename}?arrangement={index}` streams th
|
||||
| Message | Shape | Description |
|
||||
|---------|-------|-------------|
|
||||
| `loading` | `{ type: 'loading', stage }` | Status/progress message during extraction or conversion |
|
||||
| `song_info` | `{ type, title, artist, arrangement, arrangement_index, arrangements, duration, tuning, capo, centOffset, format, audio_url, audio_error, stems }` | Song metadata. `arrangements` is the full list for the switcher. `audio_url` is `null` when audio is unavailable, in which case `audio_error` is non-null; otherwise `audio_error` is `null`. `stems` is always present — an empty array for non-sloppak songs or sloppak songs with no split stems. `tuning` is an array (6 for guitar, 4 for bass). `centOffset` is a float (cents) from the RS2014 `<centOffset>` field — commonly `-1200.0` for extended-range bass (one octave down), small non-zero values for true-tuned content (e.g. A443 ≈ +11.8 cents), `0.0` when absent. Available via `getSongInfo().centOffset`. |
|
||||
| `song_info` | `{ type, title, artist, arrangement, arrangement_index, arrangements, duration, tuning, capo, centOffset, format, audio_url, audio_error, stems }` | Song metadata. `arrangements` is the full list for the switcher. `audio_url` is `null` when audio is unavailable, in which case `audio_error` is non-null; otherwise `audio_error` is `null`. `stems` is always present — an empty array for non-sloppak songs or sloppak songs with no split stems. `tuning` is an array (6 for guitar, 4 for bass). `centOffset` is a float (cents) from the RS2014 `<centOffset>` field — commonly `-1200.0` for extended-range bass (one octave down), small non-zero values for true-tuned content (e.g. A443 ≈ +11.8 cents), `0.0` when absent. Available via `getSongInfo().centOffset`. `drum_parts` (present for sloppaks, `[]` otherwise) lists the song's drum parts primary-first as `{id, name}`, plus **`tones`** when that part binds a sound (feedpak 1.18.0 §5.1/§5.2 — the entry's own `tones` or the song-level `drum_tones` fallback, already resolved server-side); the key is omitted when the part binds nothing. Resolve its `base_rig`/`rig` ids against the `rigs` message below. |
|
||||
| `beats` | `{ type, data: [{ time, measure }] }` | Beat timestamps with measure numbers |
|
||||
| `sections` | `{ type, data: [{ time, name }] }` | Named sections (Intro, Verse, Chorus, etc.) |
|
||||
| `anchors` | `{ type, data: [{ time, fret, width }] }` | Fret zoom anchors |
|
||||
| `chord_templates` | `{ type, data: [{ name, frets: [6] }] }` | Named chord shapes |
|
||||
| `lyrics` | `{ type, data: [{ w, t, d }], source }` | Syllables: `w`=word, `t`=time, `d`=duration. `-` joins to previous, `+` = line break. `source` is one of `"xml"`, `"whisperx"`, `"user"` — UI can use it to render an "auto-transcribed" badge for `whisperx`. Sloppaks always include `source` (legacy sloppaks without a `lyrics_source` manifest key default to `"xml"` at load time). Loose folders set it based on which extractor matched. Absent only when no lyrics fired the message at all |
|
||||
| `tone_changes` | `{ type: 'tone_changes', base, base_rig?, data: [{ t, name, rig? }] }` | Optional — tone change events relative to the arrangement base tone; only sent if tones were found. Note the time key is **`t`**, not `time` (both the sloppak path and the legacy XML path emit `t`). `base_rig` and each entry's `rig` are the pack's **rig bindings** — ids into [`rigs.json`](https://github.com/got-feedback/feedpak-spec/blob/main/spec/feedpak-v1.md#79-rigsjson) (feedpak §6.9/§7.9), carried through verbatim and **not** resolved by core: selecting a realization and applying the `intent.gm` floor belong to whatever voices the part. Both are **omitted entirely** when the chart binds no rig, so consumers predating the rig model see the payload they always did. |
|
||||
| `rigs` | `{ type: 'rigs', version, data: [ <rig>, ... ] }` | Optional — the pack's **rig library** (`rigs.json`, feedpak §7.9): the engine-agnostic signal chains that `tone_changes`' `base_rig`/`rig` and each drum part's `tones` reference by `id`. Sent whenever the pack ships one, **not** gated on this arrangement having tone changes (a pack can bind sound to its drum parts alone). Rigs are **verbatim** — core selects no realization and applies no `intent.gm` floor, so whatever voices the part reads the whole block, including unknown `role`/`engine`/`kind` values and `ext` namespaces. |
|
||||
| `notes` | `{ type, data: [{ t, s, f, sus, ho, po, sl, bn, ... }] }` | Single notes |
|
||||
| `chords` | `{ type, data: [{ t, notes: [{ s, f, sus, ... }] }] }` | Chord events |
|
||||
| `phrases` | `{ type, data: [{ start_time, end_time, max_difficulty, levels: [{ difficulty, notes, chords, anchors, handshapes }] }], total }` | Optional — per-phrase difficulty ladder for master-difficulty slider (feedBack#48). Only sent when the source chart carries multi-level phrase data (phrase-aware sloppak). Sent in chunks (`data` is a batch, `total` is the full count across messages) to avoid multi-MB single frames. Absent for GP imports and legacy sloppak; consumers must treat missing message as "single fixed difficulty — slider disabled". |
|
||||
|
||||
Reference in New Issue
Block a user