From fdb016d88db5710af31e89bf04fa44d29c1ba357 Mon Sep 17 00:00:00 2001 From: MelekTaus Date: Sat, 10 Oct 2026 20:31:12 +0200 Subject: [PATCH] Describe the Limiter node as a device that holds its reduction (#397) - Sounds: the table row, and a part on the device under Compressor and Limiter. It covers the knobs, the lever, the lamp, the screen, how the capture is held and how the reduction is read. - Architecture: LimiterPanel, LimiterFace and limiterView. - Development: 1970 editor checks. Co-Authored-By: Claude Opus 5.5 --- Architecture.md | 5 ++++- Development.md | 2 +- Sounds.md | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/Architecture.md b/Architecture.md index ede08b2..673d314 100644 --- a/Architecture.md +++ b/Architecture.md @@ -443,7 +443,10 @@ src/editor/soundfx/ SoundFxEditor (#311: the graph, a sound to try it on, Pla worked out apart from the drawing), SaturationPanel + SaturationFace + saturationView (#396: the Saturation as a device, the wave a sine comes out as and the heat it glows with worked out apart from the drawing; its type buttons - are the Reverb's `PickButton`), nodeParamDrag (a knob's drag as one undo step, for the tab and the + are the Reverb's `PickButton`), LimiterPanel + LimiterFace + limiterView (#397: + the Limiter as a device, what it takes away read from its taps and caught from + the start of a sound, held once it ends, worked out apart from the drawing), + nodeParamDrag (a knob's drag as one undo step, for the tab and the node, several settings at once since #389), nodeTabs (which nodes open a tab of their own) src/editor/instrument/ InstrumentEditor (#331: the graph over the keys, Preset, Randomize, Mutate, Audition), diff --git a/Development.md b/Development.md index 82e45ab..677f0b7 100644 --- a/Development.md +++ b/Development.md @@ -19,7 +19,7 @@ php tests/php/accounts.test.php # the API's accoun php tests/php/snapshots.test.php # the snapshot store (#231), the same way php tests/php/releases.test.php # the release store (#266), the same way php tests/php/files.test.php # uploaded files in a folder per account (#344), the same way -node tools/seed-e2e.mjs && node tools/e2e.mjs # 1969 editor checks, screenshots in /tmp/gm-e2e-*.png +node tools/seed-e2e.mjs && node tools/e2e.mjs # 1970 editor checks, screenshots in /tmp/gm-e2e-*.png GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step ./e2e.sh start [GM_STEPS] # the same run detached, see below ./e2e.sh status # live progress, or the last run's result diff --git a/Sounds.md b/Sounds.md index 33feb40..12443dd 100644 --- a/Sounds.md +++ b/Sounds.md @@ -435,7 +435,7 @@ response of a Reverb, and as what the Sound FX tab tries out. Its row means noth | **Flanger** | Blends the sound with a copy a few ms late: the jet sound of a flanger, and what sfxr calls its phaser. `offset` is how late the copy is (1 ms by default), `sweep` moves that on by so many ms a second from the start of the sound (0), an LFO adds up to `depth` ms (2) `rate` times a second (0.25 Hz). `feedback` (0.5) and `wet` (1) as on the Phaser. See [below](#phaser-and-flanger). | | **Pan** | Moves the sound left or right: `pan` -1 is all left, 1 all right, 0 (the default) leaves it in the middle. A mono sound is spread on both sides and then moved (each side 0.707 at 0). A stereo sound keeps the side it goes to and the other side moves over into it, as Web Audio's `StereoPannerNode` does: at 1 both sides are heard on the right. In an [instrument](Instruments#envelopes) an Envelope can move it. Measured (e2e 34, Chrome offline): a mono sine at 0.5 came out 0.5 / 0 at -1 and 0.354 / 0.354 at 0, a stereo one at 0.5 came out 0.354 / 0.854. In the graph the node is drawn as the Gain's device in cyan (#392), with one knob for `Pan`: the middle stands straight up, the turn goes evenly to *L* and *R* engraved at its ends. A linked `Pan` greys the knob. | | **Compressor** | Squeezes the loudness together: what goes above `threshold` (-24 dB by default) comes out only 1/`ratio` (4) as much louder. `knee` (6 dB) eases into it, `attack` (0.003 s) and `release` (0.25 s) say how fast it turns down and lets go. `makeup` (0 dB) raises it afterwards. **Auto-gain** (off) gives back what it takes from a sound at -18 dB, with the makeup on top. The node is drawn as a device with a meter of what it takes away, and a double-click opens a tab with its curve and the level going in and out. See [below](#compressor-and-limiter). | -| **Limiter** | Keeps every peak below `threshold` (-6 dB): it looks 5 ms ahead, so even a sudden peak never gets through, and comes back up in `release` (0.1 s). **Auto-gain** (on) raises the limited sound to `ceiling` (-1 dB). Nothing ever goes above the ceiling. See [below](#compressor-and-limiter). | +| **Limiter** | Keeps every peak below `threshold` (-6 dB): it looks 5 ms ahead, so even a sudden peak never gets through, and comes back up in `release` (0.1 s). **Auto-gain** (on) raises the limited sound to `ceiling` (-1 dB). Nothing ever goes above the ceiling. The node is drawn as a brick device whose screen holds how much it took away and when (#397). See [below](#compressor-and-limiter). | | **Saturation** | Bends the sound, from warmth to a hard distortion. **Type**: *Soft (tanh)* (the default), *Cubic*, *Hard clip*, *Tube*, *Fuzz*, *Foldback*, *Sine fold* or *Rectify*. `drive` (12 dB) is how hard the sound is pushed into it, `tone` (1) a low-pass after it from 1 kHz (0) to wide open (1). **Auto-gain** (on) keeps the bent sound about as loud as it came in, `output` (0 dB) is added on top. `wet` (1) how much of it is heard instead of the sound itself. The node is drawn as a copper device whose screen glows hotter the harder it is driven (#396). See [below](#saturation). | | **Tremolo** | Makes the volume swing `rate` times a second (5 Hz by default), from full down by `depth` percent (50) and back. **Shape**: *Sine* (the default), *Triangle*, *Square* or *Saw*. See [below](#tremolo-and-vibrato). | | **Vibrato** | Makes the pitch swing `rate` times a second (5 Hz), `depth` semitones up and as far down (0.5). **Shape** as on the Tremolo; a *Square* jumps between two pitches. See [below](#tremolo-and-vibrato). | @@ -853,6 +853,37 @@ Both (#326) work on the whole sound passing them: on a voice that is one sound, so the node keeps hearing. - The pictures of the tab, curve and levels, are not on the panel. A double-click on the node opens the tab for them. +- **The Limiter's node is a device as well** (#397): a plate of brushed brick, 720x280 graph + units, its inputs on the left and its output on the right. It has no tab. + - **Chrome knobs**: threshold large, ceiling and release small beside it. They turn and reset + as the Compressor's do, each one undo step. A knob whose input is linked is greyed. At wet 0 + the knobs and the lever are pale and the screen says `DRY`. + - **Auto-gain** is a lever at the top right. Beside it stands what it gives, `ceiling - + threshold`, for example `+5 dB`, or `off`. + - **The lamp** `LIMIT` beside the name lights red while the Limiter takes something away. + - **The screen** catches what the Limiter takes away **from the moment a sound starts**: the + reduction hangs down from the top, 0 to 24 dB by the square root like the Compressor's meter, + with marks at 1, 3, 6, 12 and 24 dB. Along the bottom runs the level coming in, -60 to 0 dB, + orange above the line of the limit. Time runs across from the start of the sound. The screen + shows 1 s and grows to 2, 4 and 8 s as the sound goes on. A longer sound rolls, and the last + 8 s of it are kept. The times stay counted from its start. + - **It is held**: once nothing has come in for 0.4 s, the capture stands still, the silence + after the sound left off, until the next sound starts a new one. Above the screen stands + `WAITING FOR SOUND`, `LIVE` or `HELD`. Under it the most taken away is written with when, for + example `MOST -11.9 dB AT 0 ms`, and the time counts from the first reading that is heard. + On the right stands `NOW -3.9 dB` while live and `LASTED 1.47 s` once held. A white line + and dot mark the most. A capture is also held when the node leaves the picture. + - **How it is read**: from the same taps as the Compressor's, a gain of 1 in front of the node + and behind it. Each frame reads the loudest sample since the last frame, at least 25 ms, at + most 150 ms. The side in front is read 5 ms earlier, as late as the Limiter is, so a peak + going in is met by what it became. What is taken away is the level in less the level out, + without the auto-gain. Below 1, Wet blends the limited sound with what came in, and the + reading is solved for the limited part: `out / in = wet * gain * auto + (1 - wet)`. Less than + 0.2 dB counts as none. + - **Measured** (2026-10-10, live, stein2): the seeded blip at -4.4 dBFS through a threshold of + -12 dB showed 7.56 dB taken away. A sound of three hits at 0, -8 and -2 dBFS showed + 11.9 dB at the first and lasted 1.47 s on the screen (the file is 1.5 s, the first hit + 50 ms in). In e2e 34 (test Chrome) -10.44 dBFS in against a limit of -20 dB showed 9.56 dB. - **Measured** (2026-10-07, e2e 34, Chrome offline): an impulse came out of the Compressor 288 samples late and out of the Limiter 240. A 1 kHz sine at -18 dB through a hard-knee Compressor at -24 dB and 4:1 came out at -17.92 dB with auto-gain on and at -22.42 dB with it