Skip to content

fix(player): run gen_block through the language's dialect dispatch - #22

Merged
spacedevin merged 2 commits into
mainfrom
fix/gen-block-dialect
Sep 1, 2026
Merged

fix(player): run gen_block through the language's dialect dispatch#22
spacedevin merged 2 commits into
mainfrom
fix/gen-block-dialect

Conversation

@spacedevin

Copy link
Copy Markdown
Owner

Apply stored the raw gen_block{ generatorId, lines } — straight onto ch.generatorSpec, so
a dialect registered through registerGenBlockDialect was never consulted. The language already has
the extension point: parseGenBlock dispatches to the registered handler and falls back to a raw
shape when there is none. The player simply wasn't calling it.

The failure is silent. A voice that needs the parsed graph — matrixFm, patch — finds
generatorSpec.graph empty, falls back to a default tone, and plays something that is not the patch
in the file. No error, no substitution recorded. I hit this writing a gen_block matrix_fm supersaw
that rendered as a plain oscillator.

Additive and non-breaking: generatorId and lines stay where they were, kind / tplHeaderId /
version are now populated, and graph appears when a dialect provides one. A host that registers
no dialect sees the shape it always did. 46/46 player tests pass.

Also corrects a comment from #21 that claimed square ignores duty "on both sides". It doesn't —
the GBA bake had no square arm and fell through to a duty-following pulse. That half is fixed in
schlopai/chuggie#27; the comment now states the disagreement instead of asserting parity.

Necessary but not sufficient

This fix only reaches as far as the registry the player can see. deck-player and
@spacedevin/deck-synths each inline their own copy of @spacedevin/deck — the player against the
monorepo working copy, the synths against 1.5.3 from npm — so they hold two separate dialect
registries, and a dialect registered in one is invisible to the other. Deduplicating the language
package is what makes host-registered dialects work across hosts at all.

Why this is a separate PR

These commits were pushed to fix/audio-conformance after #21 had already been squash-merged, so
they were stranded on a closed branch. Same content, re-proposed against current main.

`Apply` stored the raw `gen_block` — `{ generatorId, lines }` — straight onto
`ch.generatorSpec`, so a dialect registered through `registerGenBlockDialect` was never
consulted. The language has the extension point (`parseGenBlock` dispatches to the
registered handler and falls back to a raw shape when there is none); the player just
wasn't calling it.

The effect is silent: a voice that needs the parsed graph, like `matrixFm` or `patch`,
finds `generatorSpec.graph` empty, falls back to a default tone, and plays something
that is not the patch in the file. No error, no substitution recorded.

Additive and non-breaking. `generatorId` and `lines` stay where they were; `kind`,
`tplHeaderId` and `version` are now populated, and `graph` appears when a dialect
provides one. Hosts registering no dialect see the same shape as before.

Note this is necessary but not sufficient. deck-player and @spacedevin/deck-synths each
inline their own copy of @spacedevin/deck — the player against the monorepo working copy,
the synths against 1.5.3 from npm — so they hold two separate dialect registries and a
dialect registered in one is invisible to the other. Deduplicating the language package
is what makes this fix reach across hosts.
The comment added with the waveform fallback fix claimed `square` ignores `duty` "on
both sides". It does not. deckpack.rs `pcm_table` has no `square` arm, so the bake falls
through to pulse and honours `duty` — `gen waveform square duty 25` is 50% in the browser
and 25% in the ROM. Say so rather than asserting a parity that isn't there.
@spacedevin
spacedevin merged commit 23e7106 into main Sep 1, 2026
5 checks passed
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