From 82596ffd660552f4be2545aaf4e1140c1743c09f Mon Sep 17 00:00:00 2001 From: spacedevin Date: Mon, 31 Aug 2026 18:22:08 -0700 Subject: [PATCH] fix(player): an unrecognised waveform is a pulse, not a sine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `gen waveform bogus` produced a sine in the browser and a pulse in the ROM: the JS table's catch-all branch was `Math.sin`, while the GBA bake's catch-all arm in deckpack.rs `pcm_table` is a pulse. `pulse` is already the default for an *absent* waveform on both sides, so the sine was inconsistent with the language's own default as well as with the bake. Adds an explicit `sine` arm first, so `waveform sine` keeps working — the bake has one, and without it this change would have silently removed sine support. `square` still ignores `duty` here, which the bake does not; that half of the divergence is fixed on the Rust side. --- packages/player/src/generators/GbaDirectSound.tish | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/player/src/generators/GbaDirectSound.tish b/packages/player/src/generators/GbaDirectSound.tish index 40961ff..5644da5 100644 --- a/packages/player/src/generators/GbaDirectSound.tish +++ b/packages/player/src/generators/GbaDirectSound.tish @@ -68,9 +68,15 @@ fn getGbaBuffer(ctx, shape, duty) { } else if (shape === "triangle") { v = phase < 0.5 ? (phase * 4.0 - 1.0) : (3.0 - phase * 4.0) } else if (shape === "square") { + // `square` names a 50% wave, so it ignores `duty` on purpose — on both sides. v = phase < 0.5 ? 1.0 : -1.0 - } else { + } else if (shape === "sine") { v = Math.sin(phase * Math.PI * 2) + } else { + // An unrecognised name is a pulse, not a sine. `pulse` is already the default for an absent + // `waveform`, and the GBA bake's catch-all arm is a pulse too (deckpack.rs `pcm_table`), so a + // sine here meant `waveform bogus` sounded one way in the browser and another in the ROM. + v = phase < dThresh ? 1.0 : -1.0 } data[i] = v i = i + 1