@@ -5,16 +5,14 @@ routing, what is driven versus set. But information a casual author cannot read
55is decoration, and the rack speaks entirely in Hz, dB and ratios. So the drawing
66stays and the ** language changes** .
77
8- The plain-language layer over every effect in the registry ships as
9- ` packages/core/src/audioFxCopy.ts ` , and the coverage that used to gate a review
10- page — every effect, parameter and preset must have copy — is now
11- ` audioFxCopy.test.ts ` , so it runs on every commit rather than when somebody
12- remembers to regenerate a page.
8+ ` copy.mts ` is the design work: a plain-language layer over every effect in the
9+ registry. ` build-preview.mts ` renders the review page from it ** plus the real
10+ registry and preset catalogue** , and ** fails** if any effect, parameter or
11+ preset lacks copy — so the page cannot quietly omit something that ships.
1312
14- This document is the design record. What it describes is built: read it against
15- the FX rack in the studio, or against ` audioFxCopy.ts ` , ` audioFxJobs.ts ` ,
16- ` audioFxProfiles.ts ` and the panel components under
17- ` packages/studio/src/components/editor/propertyPanelFx* ` .
13+ ``` bash
14+ bun plans/audio-fx-ux/build-preview.mts /tmp/rack-ux.html
15+ ```
1816
1917## The three rules
2018
@@ -130,9 +128,7 @@ the frequency under **Details**, for the author who wants to.
130128This changes the catalogue, not just the copy: the presets should reference
131129named jobs, and ` EFFECT_COPY.peaking ` stops being one entry.
132130
133- ## Shipped: a multi-band EQ ("Tone")
134-
135- _ Built in ` e984a9e62 ` / ` 2eaa71cac ` . The design below is what was built._
131+ ## Proposed: a multi-band EQ ("Tone")
136132
137133The clearest failure this exercise surfaced is a rack holding two _ Shape One
138134Range_ modules doing different jobs. A multi-band EQ is the answer, and it is a
@@ -161,97 +157,24 @@ detent is what an equaliser looks like to everyone who has met one. Collapsed,
161157it reads like every other module: "Bass +3, Middle −2, Treble +2", or "Flat"
162158when nothing has been touched.
163159
164- ## Decided (2026-08-10)
165-
166- All three were open until now, and the first was blocking the wiring.
167-
168- ** The plain name replaces the DSP name; the DSP name lives under Details.**
169- The rack reads plain top to bottom — ` Remove Rumble ` , not ` highpass ` — and the
170- header stays narrow, which matters because it already carries a summary, a
171- bypass, two arrows and a delete. Nothing is lost: opening a module shows the
172- DSP name beside its real parameters, so the author who wants the mapping finds
173- it exactly where the mechanism is, and the author who does not never meets it.
160+ ## What still needs deciding
174161
175- ** Presets sort by complaint; the effect list stays in signal order.**
176- The two menus stop competing to be the same thing. Presets are the casual
177- author's door and ` PRESET_PROBLEM ` already carries the line for all 18 of them,
178- so this costs no new writing. The effect list stays Filters / Dynamics /
179- Non-linear / Time — it is the expert's tool, and that grouping teaches the
180- signal path the rack itself is ordered by.
181-
182- ** Everything auditions on hover, with a spinner for the ones that measure.**
183- Static presets apply to the playing audio and revert on leave, which the graph
184- rebuild path already supports. A carve or an Even Out Levels analyses first and
185- says so while it does — the same spinner the carve module already shows. This
186- is the expensive answer of the three: analysis is seconds, and a hover that
187- takes seconds is one the author has often already left, so whatever gets built
188- needs a cancel on leave and must not apply a result that arrives late.
162+ - Does the plain name ** replace** the DSP name or sit beside it? Replacing is
163+ friendlier but strands what the author learns.
164+ - Should the ** menus** be organised by complaint ("my voice sounds boomy")
165+ rather than by effect family? The rack itself must stay in signal order,
166+ because order is audible — but the menus have no such constraint, and the
167+ preset section of the preview is written that way to show the difference.
168+ - How much should ** hover audition** ? Hearing a preset before committing is the
169+ single strongest affordance here. Cheap for static presets; a measuring script
170+ has to analyse first and cannot preview instantly.
189171
190172## Status
191173
192- The EQ, the named jobs and the levelling script are ** built** , and the copy
193- layer has now landed as ` packages/core/src/audioFxCopy.ts ` — ` EFFECT_COPY ` ,
194- ` BANDS ` , ` PRESET_PROBLEM ` and ` SUMMARY ` , with the completeness check as a test
195- beside it rather than a build step.
196-
197- ** It is wired.** ` propertyPanelFxNodeRow.tsx ` takes the name from ` EFFECT_COPY ` ,
198- the sentence under it from ` SUMMARY ` , and every knob's name from the same place
199- via ` plainDef ` — which writes the words over the registry's def and leaves range,
200- step, unit and automatability alone. The DSP name sits above the knobs as
201- ` Details — High-pass ` . The preset shelf leads with ` PRESET_PROBLEM ` and follows
202- with the preset's own name. Hover and focus both audition, through the same
203- preview channel a slider drag uses; the leveller measures first, says
204- "measuring…" while it does, caches the decode per ` src ` , and drops a result that
205- arrives after the pointer has gone.
206-
207- Three things that took a second pass, all worth knowing before touching this
208- again. An audition has to survive the panel re-rendering under it — the group
209- re-renders every playhead tick, so anything keyed on its inline callbacks tears
210- down thirty times a second. Applying must NOT revert, since the audition _ was_
211- the thing applied. And moving between two entries in a shelf is not leaving it,
212- so each entry has to call its neighbours' auditions off itself.
213-
214- ** The three rules are built too** , and so is the visual direction:
215-
216- - _ Two faces._ A module opens on its name, what it is for, and the one control
217- that carries it — ` EFFECT_COPY.primary ` , with ` primaryEnds ` saying what its
218- two ends sound like. Everything else is behind a Details disclosure, which is
219- also where the DSP name lives. Ten of fifteen effects; the five whose primary
220- is "strength" open on all their controls until ` PROFILES ` ships, which is
221- honest — inventing one knob for them now would be a knob that lies.
222- - _ One knob that matters._ ` packages/core/src/audioFxProfiles.ts ` . Five effects
223- get a derived control over several parameters, continuous rather than the
224- three-point tables proposed here. ** Three of the five figures were wrong** and
225- only rendering showed it — the write-up is ` ~/audio-fx-profiles-ab/README.md ` .
226- - _ Name the outcome._ Modules, knobs, the add menu and the preset shelf.
227-
228- - ** The range IS the module.** The add menu offers five named jobs — Tame
229- Boominess, Reduce Mud, Reduce Boxiness, Add Clarity, Soften Harshness — and
230- ` peaking ` is not offered as itself. ` packages/core/src/audioFxJobs.ts ` . Every
231- one is a job the preset catalogue already ships, at the settings it ships it
232- with, so the list names the vocabulary the presets were written in rather than
233- inventing a second one.
234- - ** The shared ruler.** Every spectral module shows where it acts across the
235- seven named ranges, log-spaced, with the range it is in named underneath.
236- - ** Family lettering and the tint step.** Four families told apart by the sans,
237- the serif spent on non-linear, monospace for the measuring modules, and a
238- lightness step per module derived from registry position.
239- - ** The schematic** , translated to one column: IN and OUT terminals, every step
240- numbered over what the rack shows, and a preset's consecutive nodes bracketed
241- as the one thing that was added.
242-
243- Everything in this document is now built.
244-
245- It has no entry for Tone or for the levelling module, because both carry their
246- own copy in core (` audioEqSummary ` , ` levellingSummary ` ). That is the right home
247- for it: a summary that has to read the chain belongs beside the code that
248- writes it.
249-
250- The ` PROFILES ` figures — what one knob derives at gentle/middle/strong — have
251- ** shipped and been corrected** . They are ` HF_AUDIO_FX_PROFILES ` in
252- ` packages/core/src/audioFxProfiles.ts ` , continuous rather than three-point, and
253- three of the five were wrong as proposed: the compressor's make-up left the
254- track quieter at full evenness, saturation's trim went the wrong way and made
255- "Warmth" mean "much quieter", and the gate did essentially nothing because
256- ` release ` was not in the profile at all. Measurements, method and the sweep that
257- found the last one are in ` ~/audio-fx-profiles-ab/README.md ` .
174+ ` copy.mts ` is a proposal, not shipped code. When it lands it wants to be
175+ ` packages/core/src/audioFxCopy.ts ` beside the registry, with the completeness
176+ check as a test rather than a build step.
177+
178+ The ` PROFILES ` figures — what one knob derives at gentle/middle/strong — are
179+ proposed values, not measured ones. They want the same before/after listen the
180+ clip-before-duck fix got.
0 commit comments