Skip to content

Commit 576be34

Browse files
authored
feat: adopt wave into the language, with a generative harmonics form (#16)
* feat: adopt `wave` into the language, with a generative `harmonics` form `wave <name> <32 hex nibbles>` was never part of the grammar. It was a host-registered top-level statement, absent from DECK_GRAMMAR.md and from Highlight's TOP_KEYS, and every host that needed it registered its own copy — tish-gba (which it came from), and deck-player. Parser.tish already named the consequence: the hook exists because, without it, "the GBA implementation ended up a separate grammar rather than a subset". A statement every host implements is a language feature living in the wrong place. The corpus that exists to stop that drift never saw a `wave` line, since conformance parses with no host registrations. So `wave` is core now, and profiles.json no longer carries it as a GBA extension. On top of that, the hex is a poor way to say what a table is: timbre is harmonic content, and the digits had to be computed somewhere else and pasted in. `wave <name> harmonics <a1> …` takes amplitudes — fundamental first — and sums them into the same 32 levels, normalized so only the ratios matter. Expanded at parse time, exactly as `steps euclid` is, and for the same reason: a host reads `levels` and never learns which spelling produced it. The source form is kept alongside so an emitter can write `harmonics` back rather than flattening it to hex. 013-wave pins that the two spellings resolve to identical levels, in JS, in the Tish VM, and in the generated Rust crate. The clamps in the additive path are gone rather than covered: normalizing by the peak lands every sample in 0..15 by construction. What is guarded instead is the case that was actually reachable — a non-finite amplitude, which would have put NaN in the table. * docs: cover wavetables, timbre and basicOsc in the examples The examples page was eight blocks, every one of them a Game Boy chip song, and not one of them used a `wave` table — so the page never showed the feature this branch just adopted, and read as if the language were GBA-only. Five sections added: wavetables (both spellings, side by side, so you can hear they are one sound), designing a timbre from harmonics, instrument voices, and `basicOsc` for when you want the language without the console. Plus mix and fx, which no example demonstrated at all despite the channel strip applying to every generator. Everything stays inside the three generators this player synthesizes faithfully. Deckard's other thirty parse fine and then get substituted for a plain oscillator, which on a page where every block has a Play button would be a demo that lies about what you are hearing. The intro now says so. test/examples.mjs is what keeps that true: it parses every block on the page and fails on a substitution or an ignored feature, not just on a parse error.
1 parent becde52 commit 576be34

33 files changed

Lines changed: 968 additions & 64 deletions

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ audio-free; everything that list excludes lives in `packages/player/`, which has
2424
clamping, no defaults, no range checks. Those are host policy and the hosts genuinely differ.
2525
- Format helpers (`formatTplBeat`, `formatTplFloat`)
2626
- Scale root/mode vocabulary
27-
- Bar selectors + Euclidean step fill
27+
- Bar selectors + Euclidean step fill + wavetables (`wave`, including the `harmonics` fill)
2828
- Empty registries: generator id aliases, param key aliases, macros, gen_block dialects, body-line
2929
dialects, host top-level statements
3030
- Highlight classification (`classifyLine` / keyword sets)

conformance/001-comments-and-sharps.expected.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"scaleMode": "minor",
4747
"deckMix": null,
4848
"directives": [],
49+
"waves": [],
4950
"hostStatements": {},
5051
"errors": []
5152
},

conformance/002-track-header.expected.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
"scaleMode": null,
154154
"deckMix": null,
155155
"directives": [],
156+
"waves": [],
156157
"hostStatements": {},
157158
"errors": []
158159
},

conformance/003-steps-and-locks.expected.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@
211211
"scaleMode": null,
212212
"deckMix": null,
213213
"directives": [],
214+
"waves": [],
214215
"hostStatements": {},
215216
"errors": []
216217
},

conformance/004-notes.expected.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@
123123
"scaleMode": null,
124124
"deckMix": null,
125125
"directives": [],
126+
"waves": [],
126127
"hostStatements": {},
127128
"errors": []
128129
},

conformance/005-mix-fx-voice-deck.expected.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
"scaleMode": null,
134134
"deckMix": null,
135135
"directives": [],
136+
"waves": [],
136137
"hostStatements": {},
137138
"errors": []
138139
},

conformance/006-globals.expected.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
}
5555
},
5656
"directives": [],
57+
"waves": [],
5758
"hostStatements": {},
5859
"errors": []
5960
},

conformance/007-session-song-follow.expected.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@
148148
"scaleMode": null,
149149
"deckMix": null,
150150
"directives": [],
151+
"waves": [],
151152
"hostStatements": {},
152153
"errors": []
153154
},

conformance/008-macros-genblock.expected.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
"scaleMode": null,
9191
"deckMix": null,
9292
"directives": [],
93+
"waves": [],
9394
"hostStatements": {},
9495
"errors": []
9596
},

conformance/009-directives.expected.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
]
8484
}
8585
],
86+
"waves": [],
8687
"hostStatements": {},
8788
"errors": []
8889
},

0 commit comments

Comments
 (0)