feat(deck): read wave from the language, and accept the harmonics form - #27
Merged
Conversation
`wave <name> <32 hex nibbles>` originated here, as a fork of the parser, and survived as a registered dialect extension after the fork was undone. It was never GBA-specific though — deck-player registered its own copy too — so it has been adopted into the language proper (spacedevin/deck#16). That deletes the hex validation and nibble unpacking from this crate. The parser resolves both spellings to 32 levels, and all that is left here is packing two levels per byte for wave RAM. The additive sum lands at bake time, which is the only place it can: the device is no_std on ARM7TDMI with no FPU and no libm, so there is no sin() on the far side. Nothing about the ROM changes — still 16 bytes per table, copied verbatim into WAVE_RAM, so a harmonics table costs exactly what a hex one did. The corpus digest is unchanged across all 54 decks, and a new test pins the part that would be invisible otherwise: a harmonics table and the hex literal it resolves to pack to byte-identical wave RAM. Blocked on the deckfile 1.5.0 release; the pin is bumped ahead of it, so CI will not go green until that publishes.
The released crate, in place of the version pinned ahead of it. `wave` is core grammar there, so this is what actually makes the branch build. All 11 tests pass against the published crate, and the corpus digest across all 54 decks is byte-identical to the pre-change baseline.
CI runs `cargo fmt --check` on every crate and `cargo clippy --all-targets -D warnings` on this one; the wave changes passed neither. Formatting was mechanical. Clippy found two needless range loops and one real problem: `assert!(b >> 4 <= 15 && (b & 0x0f) <= 15)` is always true, because a nibble of a u8 cannot exceed 15. The assertion proved nothing. Replaced with the invariant actually worth pinning — that packing is lossless and high-nibble-first. Getting that order wrong still yields 16 plausible bytes, so nothing downstream would catch it; the ROM would just play a scrambled waveform. Tests still 11/11 and the corpus digest is unchanged across all 54 decks.
# Conflicts: # docs/deck.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reads named
wavetables out of the.decklanguage and bakes them, accepting both spellings —the 32-hex-digit form and the
harmonics <a1> ...form, which the parser resolves to the same 32levels.
Commits:
feat: readwavefrom the language, and accept theharmonicsformchore(deps): pin deckfile 1.5.3style: satisfy rustfmt and clippy in the wave bakeNote for review
While building a cross-implementation audio conformance corpus, two divergences turned up between
this bake and
@spacedevin/deck-player's Web Audio voices. One is fixed on the JS side inspacedevin/deck#21 (an unrecognised
waveformwas a sine in the browser and a pulse here). Theother is on this side and is not addressed by this PR:
pcm_tablehas no"square"arm, sosquarefalls through to the_catch-all — which is a pulsethat honours
duty. The browser treatssquareas a fixed 50% wave that ignoresduty. Sogen waveform square duty 25is 50% in the browser and 25% in the ROM, andsquareis a documentedvalue in the chuggie.dev deck docs. Worth an explicit arm here.