Commit Graph
3 Commits
Author SHA1 Message Date
adminandClaude Opus 5.5 28909f0adf Show a Limiter node as a device that holds what it took away (#397)
game-maker / gate (push) Successful in 4m23s
game-maker / suite (push) Successful in 16m6s
A Limiter only said what it does in rows of numbers. How much it took
away, and when, could not be seen at all, and a short sound is over
before any needle could show it. Now the node is a device of its own
size, and its screen catches the reduction from the moment a sound
starts and holds it once the sound ends.

- LimiterPanel draws a 720x280 plate of brushed brick. The threshold
  knob is large, ceiling and release are small beside it, auto-gain is
  a lever. A LIMIT lamp lights while it takes something away.
- The screen hangs the reduction down from the top, 0 to 24 dB by the
  square root like the Compressor's meter. The level coming in runs
  along the bottom, orange above the limit. Time runs from the start
  of the sound over 1, 2, 4 or 8 s, and a longer sound rolls.
- ReductionCapture in limiterView holds the capture after 0.4 s of
  silence, without the silence, until the next sound. It writes the
  most taken away and when, and NOW or LASTED on the right.
- The Limiter is tapped now, like the Compressor. The face reads the
  loudest sample since the last frame on both sides.
- SpectrumTaps.levels takes a lateBy. The side in front is read 5 ms
  earlier, so a peak going in is met by what it became.
- limiterReduction leaves the auto-gain out and solves Wet's blend for
  the limited part. Less than 0.2 dB counts as none.
- A capture is also held when the node leaves the picture. Changing a
  knob or the lever leaves it as it is.
- Hook __gm.limiter.panel(id) for the sound FX and instrument graphs.

Decided myself:

- The capture stays held until the next sound, not for a fixed time.
- The screen has no wet knob, as the Compressor's has none.
- The Limiter's two taps cost two gains of 1 per voice. The analysers
  only exist while the node is in the picture.

Measured on stein2: the seeded blip at -4.4 dBFS against -12 dB showed
7.56 dB. Three hits at 0, -8 and -2 dBFS showed 11.9 dB at the first.
In e2e 34 on melektaus-atx, -10.44 dBFS in against -20 dB showed
9.56 dB, the difference to the hundredth.

Tests:
- Unit: limiter-view 13 tests (new), spectrum 6 (1 new), soundfx 67
  with the Limiter's taps.
- Counter-test: without Wet's share in the formula the blend test
  fails.
- e2e 34: ALL PASSED, 138 checks (1 new).
- Gate: CHECK EXIT 0, 290 files, 4445 tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 20:30:59 +02:00
adminandClaude Opus 5.5 1df38bd430 Edit a Compressor in a tab of its own, with knobs and levels (#378)
A Compressor had only its number rows in the node. Its numbers are
easier to set by feel on a dial, and what it does is easier to judge
when the level going in and the level going out are seen side by side.

- Knob is a new widget in the toolkit: a slider bent into a circle,
  its name above and a number field below. A drag up or down turns
  it, Shift a tenth as far, a notch of the wheel a fiftieth of the
  turn, a double-click sets the default, the number takes a typed
  value. A taper gives the low end more of the turn.
- The Compressor's tab opens on a double-click, one per node, like
  the Parametric EQ's. It has a knob for each of the seven numbers,
  greyed while its input is linked.
- Its curve shows level in to level out from -60 to 0 dB. The point
  where it bends sets the threshold, the end of the curve sets the
  ratio that ends there.
- Its levels show the last 4 s on both sides of the node. Where it
  takes more than 0.5 dB away, the stretch below the level coming in
  is tinted. The makeup is left out of that.
- The Compressor is tapped like the EQ. SpectrumTaps listens to more
  than one node at once and reads the loudest sample of the last
  25 ms on each side.
- The node tabs share one map in the editor (nodeTabs), so a third
  kind needs no new plumbing.

Findings:

- CI task 614 for 23922ee was red on the memory check of the stream:
  the tab's renderer grew by 94 MB with nothing decoded. Play mode
  made garbage of its own and was read before a collection. Both
  readings in play now come after one, and the check compares the
  growth streamed with the growth decoded (3.7 MB against 59.8 MB).
- The ratio handle sat on the right edge of the picture, where a
  widget's hit area ends. The curve is inset by the grab radius.

Tests:

- Gate (melektaus-atx): 282 files, 4338 tests (17 new)
- e2e 34 (melektaus-atx): ALL PASSED, 116 checks (6 new)
- Counter-checks: an inverted ratio search, stop() letting go of
  every node and a drag without its least step each fail exactly
  their test.
- Looked at the tab in a screenshot: a blip at -4.4 dB came out at
  -16.7 dB, the gap tinted, the threshold line at -24.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:40:12 +02:00
adminandClaude Opus 5.5 687377682c Draw the EQ's curve in its node and a spectrum behind it (#375, #374)
Both were asked for in #367 "for later". The node of a Parametric EQ
now shows its curve in small, and its tab shows what passes the node
while it is seen.

#375, the curve in the node:

- NodeDef has an optional `picture`: a height, and shapes made from
  the settings as plain point lists (guide, area, line). It is
  general, the Parametric EQ is its first user.
- NodeView draws it in a box below the rows, again only when the box
  or the settings change. A drag in the EQ tab changes them, so the
  node follows it live.
- Without a band the box stays, flat on its 0 dB line, so the node
  does not grow at the first band.
- The axes of the curve, `eqCurvePoints` and `fillShapes` move from
  editor/soundfx/eqView to core/soundfx/parametricEq. Tab and node
  draw the sum from the same function.

#374, the spectrum:

- A node marked `tapped` gets a `tap` stage in front of its own
  stages and one behind them when compiled, in a sound FX and in an
  instrument alike. Its id is asset and node, since a copied asset
  keeps its node ids.
- A tap is a gain of 1. SpectrumTaps (new, viewport/spectrum.ts)
  holds the tap of every voice and bus while it plays.
- While the EQ tab is seen, in the tab row or in a window, the taps
  of that node feed one analyser per side (8192 points). Nothing is
  made before a tap of the node plays, so no AudioContext is opened
  early.
- The tab draws both behind the curve, on a scale of 0 to -96 dBFS:
  the sound coming in faint and grey, the sound going on in the
  colour of a sound port. The analyser smooths it, and once the
  sound has gone the sum still hands it silence, so it falls away.
- Once the tab is not seen, Editor.tick lets the analysers go, like
  the meters of the Song tab.
- A tap does nothing to the sound, so `stats().last.stages` leaves it
  out, and a bypassed EQ keeps its taps.

Decided on my own:

- Every sound passing the node counts: Play of the sound FX tab, an
  instrument's keys, a song, a run. The issue proposed that.
- The spectrum has no labels of its own. Its scale is in the wiki.

Tests:

  Gate (melektaus-atx)     275 files, 4247 tests (11 new), EXIT 0
  e2e 34 (melektaus-atx)   ALL PASSED, 98 checks (2 new), twice

Counter-checks, each put back by copy and compared with cmp:

- The node's curve drawn without its bands: 2 unit tests fail.
- The spectrum without the loudest bin between two points: 1 fails.
- SpectrumTaps.stop leaving the taps linked: 1 fails.
- Taps that never feed the analyser: e2e 34 fails in exactly the
  spectrum check (frames 0). Run in the container only.

The screenshots of the second run were looked at: the blip as one
peak behind the curve, and the dip at 4 kHz in the node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 15:58:53 +02:00