Commit Graph
3 Commits
Author SHA1 Message Date
adminandClaude Opus 5.5 01fd6e6464 Swirl and comb a sound with a Phaser and a Flanger node (#341)
sfxr's "phaser" is a comb filter, the sound plus a copy delayed by up
to 2.9 ms. That is a flanger, not the phaser a guitarist knows. Both
effects come in as nodes of their own, so each name fits its sound and
sfxr is covered in full. Both run on the FX worklet like the
Bitcrusher, because a feedback loop in Web Audio costs a render quantum
per round.

- Phaser: first-order allpasses (Stages 2, 4, 6, 8, 12) around
  Frequency, moved by a sine LFO Depth octaves wide at Rate Hz, with
  Feedback and Mix. An Envelope can move Frequency and Mix.
- Flanger: a delay line of Offset ms. Sweep moves it on in ms/s from
  the start of the voice, an LFO adds up to Depth ms. As in sfxr the
  delay is mirrored at 0, and it never goes past 20 ms. Feedback comes
  back exactly one delay later. An Envelope can move Offset and Mix.
- Mix 0 leaves the sound as it is, 1 is half sound and half copy. The
  notches are deepest there and the peaks stay at the sound's level.
  sfxr adds both at full, so its sound comes out 6 dB louder.
- The Flanger's processor gets the start of its voice and begins the
  sweep on that sample. stageNodes takes it as a new argument `at`.
- Explosion gets a Flanger in one draw out of two, with sfxr's offset
  and sweep and no LFO. Offset is offset^2 * 2.89 ms, Sweep is
  ramp^2 * 125 ms/s, signed so the direction holds.
- Randomize draws a Flanger's offset and sweep like sfxr. Its LFO and
  feedback and all of a Phaser are drawn within bounds of their own.
  Mix and Stages stay, as a Bitcrusher's Mix does. Mutate moves them
  too, and a 0 stays 0.
- New instrument preset Phased Pad: saw, Envelope, low-pass, Phaser of
  six stages. The other 14 are unchanged.
- The Bitcrusher's worklet setup is now shared with both nodes
  (workletNodes), its behaviour is unchanged.

Tests:
- Unit phaser (new): 8 green. Counter-check with clamping at 0 instead
  of mirroring and a flipped allpass coefficient: 3 red.
- Unit soundfx, sound-library, chip-presets: 45 / 76 / 14 green.
  Counter-checks: start time not passed on, phaser frequency eased
  linearly, sweep sign dropped, Phaser left out of Mutate, each red.
- Unit core, viewport, graph: 179 files, 2979 tests green.
- e2e 34 (melektaus-atx): ALL PASSED, 70 checks (1 new), first run.
  Chrome offline: 1 kHz notch RMS 0.0000 with two stages, 0.5657
  with four. Flanger echo after 48 samples, swept echo at 533/534.
  About 47 Phasers (12 stages) or 63 Flangers fill the audio thread.
- Gate (melektaus-atx): CHECK EXIT 0, 257 files, 3991 tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:11:54 +02:00
adminandClaude Opus 5.5 f46b2316f2 Make 8-bit sounds without a file with a Chip node in instruments (#329)
game-maker / suite (push) Failing after 36s
game-maker / gate (push) Successful in 3m33s
An instrument could only play sound files so far. The Chip makes the
sound of a note itself, the way old game consoles and sfxr did: a raw
wave and what its frequency does over the note. A laser, a jump or a
pickup is now an instrument and ends by itself.

- Chip node with wave (square, triangle, saw, sine, noise and the
  periodic noise of the NES), follow note, frequency, duty, duty
  sweep, slide, delta slide, min frequency, vibrato, arpeggio and
  repeat. It counts in Hz, semitones and seconds, not sfxr's 0 to 1.
- It runs as a third processor in the FX worklet. The math is a plain
  class, ChipPlayer, tested in Node. Every sample is worked out 8
  times and averaged, as sfxr does.
- Frequency and duty are AudioParams, so an Envelope can move them
  and a parameter can tune them while the note plays. A Pitch behind
  a Chip moves its frequency directly, without the phase vocoder.
- Below its min frequency a Chip ends and tells the page. Without the
  worklet it is silent and its note ends at once.
- An Envelope with sustain 0 now ends its note once the decay is over,
  for every source under it, Samples too. Before, a note with
  duration 0 ran on silently until a Stop sound.
- A note made of Chips alone needs no file. playNote and the wait for
  the bytes no longer drop it for having none.
- Inputs that do nothing as things stand are grey in the inspector.
  idleParams is told which inputs are connected, so a connected one
  always counts.

The credit names sfxr (Tomas Pettersson, MIT) and jsfxr, which turned
out to be public domain, not MIT as the plan in #329 said.

Tests:
- Unit chip (new) 12, sound-library +4. All of tests/core,
  tests/viewport, tests/editor/graph and tests/editor/inspector:
  178 files, 2953 green.
- Counter-checks: semitones read as /24 turn 4 chip tests red. Without
  the sustain rule and the file check 4 library tests fail.
- e2e 34 (melektaus-atx): ALL PASSED, 60 checks (2 new). Offline in
  Chrome a square at 220 Hz plus 12 semitones and duty 0.25 gave 329
  periods in 0.75 s, up 0.249. 64 noise voices for 2 s rendered in
  2.0 s, about 63 at once. Live a 0.2 s note with sustain 0 was gone
  after 0.26 s.
- Gate (melektaus-atx): CHECK EXIT 0, 255 files, 3962 tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:54:44 +02:00
adminandClaude Opus 5.5 165f022fc0 Crush a sound to fewer bits and a lower rate with a Bitcrusher (#322)
game-maker / gate (push) Successful in 3m32s
game-maker / suite (push) Successful in 18m49s
A new effect for sound FX and instruments makes a sound rough like an
old console. It rounds the sound to fewer steps and holds it at a lower
sample rate, and all three of its numbers move while the sound plays.

- Bitcrusher node with bits (1 to 16, not only whole), rate (100 Hz to
  48 kHz, sample-and-hold) and mix. A mix typed in at 0 leaves it out.
- It runs on the audio thread as a second processor next to the pitch
  player. The module is now fxWorklet.ts and the test hook is called
  fxWorkletUrl.
- A play that needs the worklet waits for it, for a Pitch or a
  Bitcrusher alike. Without the worklet the sound goes through as is.
- Bits and mix move in what they hold, the rate in octaves. An
  Envelope can move all three in an instrument.
- A stage that runs on the worklet is stopped with its voice, like the
  drivers of an Envelope or a Mix.
- The math is a plain class, Crusher, so it is tested in Node.

The cleanup check of e2e 64 from af9b202 turned suite 553 red. It
asked that no editor run was left at all. In CI a step before 64 still
leaves one of its own running. The check now asks only about its own
behavior and prints what is still running, so the next suite names it.

Tests:
- Unit crusher (new) 4, soundfx +2, sound-library +3. All of tests/core,
  tests/viewport and tests/editor/graph: 176 files, 2934 green.
- Counter-check: without the rounding 2 of 4 crusher tests fail.
- e2e 34 (melektaus-atx): ALL PASSED, 58 checks (1 new). Offline in
  Chrome 2 bits at 4 kHz leave five levels held for 12 samples each.
  64 stereo voices for 2 s render in 1.9 s, about 68 at once.
- e2e 64 (melektaus-atx): ALL PASSED, 30 checks.
- Gate (melektaus-atx): CHECK EXIT 0, 254 files, 3946 tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:22:54 +02:00