Describe the Compressor's tab and the Knob (#378)

- Sounds: the Compressor's row and a paragraph on its tab: knobs,
  curve with threshold and ratio to drag, levels in and out.
- Architecture: Knob + knob in the toolkit, CompressorEditor,
  compressorView and nodeTabs, several nodes listened to at once.
- Development: 1947 editor checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
adminandClaude Opus 5.5 committed 2026-10-09 22:40:15 +02:00
1 parent 2abe43caa6
commit 5b9343f173
3 files changed
+28 -5

No files matched your search

+7 -3
@@ -214,7 +214,7 @@ src/runtime/physics/ engine (loads Rapier once, reports its state, converts be
src/ui/ widget toolkit (generic, knows nothing about assets); fonts (the faces the editor ships:
Source Sans 3 in 400, 500 and 600, Source Code Pro 400, Latin only, #202/#214/#273), icons +
Icon (the menu's tick boxes and current-entry dot as SVG files, and a widget that shows one file
on its own: a symbol the Latin subset lacks is never written as a character, #214); SortableList + sortable (the layer list of every editor that has one: rows dragged into order, eye, duplicate, cross, rename in place; the index arithmetic of a list shown upside down, of a drop in the tile strip and of blocks of rows of any height, kept apart so it is measured without a canvas); blockDrag (`sortBlocks`: the inspector's own rows dragged into order by a `Grip` (the row's mark, wrapped: dots once it drags, lit under the pointer while the block is washed), a block being every row it covers, #310)
on its own: a symbol the Latin subset lacks is never written as a character, #214); SortableList + sortable (the layer list of every editor that has one: rows dragged into order, eye, duplicate, cross, rename in place; the index arithmetic of a list shown upside down, of a drop in the tile strip and of blocks of rows of any height, kept apart so it is measured without a canvas); blockDrag (`sortBlocks`: the inspector's own rows dragged into order by a `Grip` (the row's mark, wrapped: dots once it drags, lit under the pointer while the block is washed), a block being every row it covers, #310); Knob + knob (#378: a slider bent into a circle, its name above and a number field below; where a value sits on the turn and what a drag or the wheel makes of it, kept apart so it is measured without a canvas)
src/viewport/ WorldViewport (the drawing of a world or a holder, the base of every view; it draws from
a `ViewSource` — the project and word of a change — so a released game draws without the
editor, #266; a view through a camera keeps only what that camera `Sees` and lays one
@@ -245,7 +245,8 @@ src/viewport/ WorldViewport (the drawing of a world or a holder, the ba
CPU and laid side by side onto one canvas, so a frame is cut out like a texture frame),
SoundLibrary + fxNodes (what each stage of a sound FX becomes as Web Audio nodes, and
how the knobs of a playing voice move) + spectrum (#374: the taps of the voices and
buses playing, and the analysers they feed while a node is listened to) + fxWorklet (the AudioWorklet of the effects Web Audio has no node for: a
buses playing, and the analysers they feed while a node is listened to, several nodes at once, and the
loudest sample of the last stretch on each side, #378) + fxWorklet (the AudioWorklet of the effects Web Audio has no node for: a
`Source` plays a sound of its own, a way with a Pitch, #317, or a Chip, #329; an `Effect`
sits between two stages, the pitch of a bus, #346, a Bitcrusher, a Phaser, a Flanger, a
Limiter, a Tremolo or a Vibrato; `Start` keeps either silent until its voice starts,
@@ -418,7 +419,10 @@ src/editor/sound/ SoundEditor (#343: header with Play, the clip's direction
src/editor/soundfx/ SoundFxEditor (#311: the graph, a sound to try it on, Play and Stop), PreviewParams (the
header's fields for the parameters a tab plays with, shared with the Instrument tab),
EqEditor + eqView (#367/#370: the Parametric EQ in a tab of its own, its handles on
the picture, and the spectrum behind the curve, #374)
the picture, and the spectrum behind the curve, #374), CompressorEditor +
compressorView (#378: the Compressor's tab, its knobs, its curve with threshold and
ratio to drag, and the levels in and out tinted where it squeezes), nodeTabs (which
nodes open a tab of their own)
src/editor/instrument/ InstrumentEditor (#331: the graph over the keys, Preset, Randomize, Mutate, Audition),
PianoKeyboard + keys (the keys drawn, played by the pointer and the computer keyboard)
src/editor/routing/ RoutingEditor (#351: the Master routing tab, one per project)
+1 -1
@@ -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 # 1941 editor checks, screenshots in /tmp/gm-e2e-*.png
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1947 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
+20 -1
@@ -435,7 +435,7 @@ response of a Reverb, and as what the Sound FX tab tries out. Its row means noth
| **Phaser** | Sweeps notches through the sound, the swirl of a phaser pedal. **Stages** (2, 4, 6, 8 or 12, 4 by default) is how many allpass stages it has, every two make one notch. They sit around `frequency` (800 Hz by default), and an LFO moves them `depth` octaves wide (2), `rate` times a second (0.5 Hz). `feedback` (0.4) sharpens the notches, `wet` (1) is how much is heard. See [below](#phaser-and-flanger). |
| **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. |
| **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` (0) blends that with the gain that brings a sound at full scale back to full scale. See [below](#compressor-and-limiter). |
| **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` (0) blends that with the gain that brings a sound at full scale back to full scale. A double-click on the node opens its tab: a knob for each number, 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` (1) raises the limited sound towards `ceiling` (-1 dB). Nothing ever goes above the ceiling. 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). `output` (0 dB) and `auto-gain` (1) set the level of the bent sound, `wet` (1) how much of it is heard instead of the sound itself. 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). |
@@ -725,6 +725,25 @@ Both (#326) work on the whole sound passing them: on a voice that is one sound,
with a Limiter is let go only once what the Limiter still holds is out.
- Every number moves with *Set sound FX parameters*: dB values evenly, times and the ratio in
their ratio.
- **The Compressor's tab** (#378): a double-click on the node opens it, one tab per node, named
and closed like a [Parametric EQ's](#parametric-eq). It has three parts:
- **Knobs**, one for each of the seven numbers. Drag up or down to turn one: 200 px is the
whole turn, with Shift a tenth of that. A notch of the wheel turns it by a fiftieth.
A double-click sets the default, and a click on the number below lets you type one. Attack,
release and ratio give most of the turn to the low end, where they are used. A knob whose
input is linked is greyed: the link decides its value.
- **The curve**, level in across and level out up, both -60 to 0 dB, before the makeup and
auto-gain. Two points are dragged: the one where it starts to bend sets `threshold`, the one
at its end sets the `ratio` that ends there. A dot on the curve is the level coming in now.
- **The levels** of the last 4 s, newest at the right, +6 to -60 dB: grey what comes in, in
the colour of a sound port what goes out. Where the compressor takes more than 0.5 dB away,
the stretch below the level coming in is tinted by as much as it takes. The makeup is left
out of that, so a raised sound still shows what was squeezed. A level is the loudest sample
of the last 25 ms. The line across is the threshold.
Each drag, notch or typed number is one undo step. The levels come from the same taps as the
EQ's spectrum: a gain of 1 in front of the node and behind it, fed into an analyser only while
the tab is seen. An EQ's tab and a Compressor's can be listened to at once.
- **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 full scale through a hard-knee
Compressor at -12 dB and 4:1 came out at +0.19 dB with full auto-gain and at -8.81 dB with none