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>
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>