The Filter node from #335 only knew low-pass, high-pass and band-pass
and had a Resonance from 0 to 1. It now has every type Web Audio
offers, a Q as a plain factor and a slope up to 48 dB per octave.
- Types: low-pass, high-pass, band-pass, notch, low shelf, high shelf,
peaking and all-pass. The cutoff row is now labelled Frequency, its
key stays `cutoff`.
- Q from 0.1 to 30, 0.707 by default, replaces Resonance. Web Audio
takes the Q of a low- or high-pass in dB, so it is converted when the
voice is wired. No project used the node.
- Gain in dB is an input only for the shelves and the peak. It is a
derived port, so the sound FX compiler now resolves derived ports.
- Slope 12, 24 or 48 dB/oct runs 1, 2 or 4 filters in a row. They
share one cutoff carried by a ConstantSource, only the last has the
Q. Shelves, peak and all-pass hide the row.
- The Chip Presets get the Q their resonance gave before. Mutate moves
Q in octaves and gain by up to a dB.
- bindStage in the instrument compiler binds every amount of a stage
generically, so new stages need no case of their own there.
Finding: FLAT_Q was in dB and the delay damping used it. It is a
factor now, the damping takes it through passQ and is unchanged.
Tests:
- Unit envelope 13, sound-library 96 (2 new), chip-presets 14,
soundfx 45, all green.
- Counter-checks: the Q on every filter in a row, the gain row for
every type. Each turns one test red.
- e2e 34 (melektaus-atx): ALL PASSED, 76 checks (1 new). Chrome
offline, 2 kHz through a low-pass at 1 kHz: -12.37 dB at 12 dB/oct,
-49.5 dB at 48. A +6 dB peak gives 6.00 dB, a notch -124 dB.
- The gate runs once on the last commit of this series.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without an envelope a note set in hard and broke off 10 ms after its
end. An instrument now has an Envelope node with attack, decay,
sustain and release. On the way of the sound it is the volume. Its
output "value" moves a number of the note with the same curve, from
"From" to "To", for a filter sweep among others. A new Filter node
gives that sweep something to move.
- Envelope (instrument only): attack a straight line, decay and
release ease out and are 60 dB of the way at their time. A release
takes 10 ms at least. Defaults 0.005 / 0.1 / 1 / 0.1.
- The end of a note goes to the Envelope instead of the 10 ms fade. A
Gate or Loop Sample under it plays on through the release, "Loop,
then release" leaves its loop too, and the voice ends with the
release. A One-shot under an Envelope of its own plays through.
- A note ending before attack and decay releases from the level it
has reached. Chrome holds it with cancelAndHoldAtTime, Firefox gets
the level worked out from the shape.
- New port type "envelope" (coral). It fits only a number input that
says it can follow one (PortDef.followsEnvelope): Filter cutoff and
resonance, Pitch, Gain, the EQ bands and Mix. Not the Delay, not the
Envelope's own numbers. portsMeet() decides it for ConnectCommand,
the drag and the drawn edges.
- On the audio thread every Envelope of a note is one
ConstantSourceNode. A number it moves gets the curve through a
WaveShaper, in equal ratios for a cutoff and a gain. A number an
Envelope moves is no longer reached by a parameter.
- Filter (sound FX and instrument): low-, high- or band-pass, cutoff
in Hz, resonance 0 to 1 as a Q. A low- or high-pass is flat at 0
and rises 20 dB at 1, a band-pass goes from Q 0.7 to 20.
- Stop sound with "let ring" lets a note with an Envelope fall away
in its release. Without it, and with Stop in the tab, it is cut.
- The same note again during a release is a voice of its own.
- The Envelope's numbers are set when the note starts. They can come
from velocity or a parameter, later changes do not bend the note.
Tests:
- envelope.test.ts (new, 12): curve, ratios, Filter Q, compiling an
Envelope, its value into each number, a Delay refused
- sound-library +7: attack and decay on the clock, release from the
level reached, One-shot held, Stop sound with and without let ring,
a cutoff and a pitch moved by the curve
- e2e 34: ALL PASSED, 50 checks (+2). Offline in Chrome the curve
rendered 0.5 / 1 / 0.5005 at 0.05 / 0.1 / 0.3 s, released at 0.5 s
it was 0.0158 at 0.65 s and 0.0005 at 0.8 s, released mid-attack it
fell from 0.5 to 0.05 in 0.1 s. A Gain moved 0.25 to 1 was 0.5
halfway. A looped note of 0.2 s with a release of 1 s was gone
after 1.32 s.
- Five counter-checks (release end, One-shot hold, the follows check,
ratios, pitch sum) failed 3, 1, 1, 2 and 2 tests.
- Gate on melektaus-atx: CHECK EXIT 0, 245 files, 3812 tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>