Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Performance: named controls and the drift walk

A control called Bright is a fixed direction in standardized φ. Which knobs it turns is measured per patch, checked on real renders, and refused when the knobs cannot honestly produce it.

PERFORM, the instrument’s first view, needs two things from the machinery. It needs controls whose names mean the same thing on every patch, which a knob address cannot give: node/0#cut is a brightness control in one patch and a wavefolder’s drive in another. And it needs motion that stays inside the sound: a patch that changes on its own without changing what it is made of.

The first is a least-squares problem on the patch’s own Jacobian. The second is the locked walk with every structural site locked. Both live in auracle_session::perform, and reach the browser as perform_wire, perform_apply, perform_drift, and perform_offer on WasmEngine. Under the model view the instrument also draws which way your taste leans along each control (below), perform_lean.

Symbols on this page

The notation fixes dd as the feature dimension and xx as a term, so this page uses different letters for the two things the code calls d and x.

SymbolIsIn the code
v∈[0,1)nv \in [0,1)^nThe patch’s nn continuous knob values, normalizedJacobian::values
z(v)∈R18z(v) \in \R^{18}The audio block of standardized φ\varphi at those valuesaudio_z
e^∈R18\hat e \in \R^{18}A named control’s unit directiondirection(...), d
J∈R18×nJ \in \R^{18 \times n}∂z/∂v\partial z / \partial v at the current values v0v_0Jacobian::cols
δ∈Rn\delta \in \R^{n}The knob move the wiring solves forx
SSThe knobs a control is allowed to move, ∣S∣≤4\lvert S \rvert \le 4support
c∈[−1,1]c \in [-1, 1]A control’s setting; 00 is the sound as it isc

Distances along e^\hat e are in zz units: one unit is one standard deviation sjs_j of the session’s own spread, from the standardizer. The instrument’s tooltips and the code’s comments write this unit as σ.

The constants on this page live in auracle-session’s perform.rs unless the text names another file.

A named control is a direction

Six controls on the panel, each a fixed weighting of named φ_audio coordinates, normalized to unit length. They are the first six of the palette's eighteen, which the engine defines and measures the same way:

ControlLow · highWeights before normalizing
Brightdark · brightcentroid_mean +1+1, rolloff_mean +1+1
Snapbloom · snapattack_s −1-1, crest +1+1
Motionstill · restlessheld_centroid_std, motion_slow, motion_mid, motion_fast, each +1+1
Bodythin · fullbass_fraction +1+1
Gritsmooth · roughflatness_mean +1+1
Spaceclose · fartail_ratio +1+1

So e^Bright=(ecentroid+erolloff)/2\hat e_{\text{Bright}} = (e_{\text{centroid}} + e_{\text{rolloff}})/\sqrt2, and Motion spreads over its four coordinates with weight 12\tfrac12 each, the motion bands plus the older held_centroid_std. A unit test requires each of the eighteen directions to have unit norm over φ’s real coordinate names, and every coordinate it weights to be one of them, so a control that lost any coordinate to a rename fails the build instead of quietly narrowing to the rest.

The direction is defined in zz, not raw φ\varphi, because only a standardized coordinate has a scale that means the same thing across axes. The patch’s current position on a control is e^⊤z(v0)\hat e^\top z(v_0); the instrument draws it as a dot on the control’s ring, at tanh⁡(e^⊤z/2)\tanh(\hat e^\top z / 2) of the way to the stop.

The standardizer is the session’s, refit at every posterior fit. A control’s wiring and position are therefore relative to the patches this session has seen, and can change after a refit. Before the pool has a standardizer at all, perform_wire returns null and the view says there is nothing to measure against yet.

The other two controls, Blend and Wander, are not directions in φ and live in the instrument, not in this module.

The Jacobian, by one-sided differences

For each continuous knob kk, one render nudged by hkh_k:

J:,k  =  z(v0+hk ek)−z(v0)hk,hk={+hv0,k<12−hotherwiseh=0.08 J_{:,k} ;=; \frac{z(v_0 + h_k, e_k) - z(v_0)}{h_k}, \qquad h_k = \begin{cases} +h & v_{0,k} < \tfrac12 \ -h & \text{otherwise} \end{cases} \qquad h = 0.08

JACOBIAN_STEP =0.08= 0.08 of the knob’s normalized range: large enough to move φ past the numerical floor of a five-second render, small enough to stay local. Stepping toward the interior keeps every nudge inside the knob’s domain, and one-sided differences cost n+1n + 1 renders instead of the 2n2n that central differences would, all through the render memo. A knob whose nudge fails to vet gets a zero column, and the wiring simply cannot use it.

The estimate is first order: its error is O(h)O(h) in the curvature of the response. That is not bounded here. It is what the verification below exists to catch.

Wiring: ridge, support, re-solve

The knob move that best produces e^\hat e is the ridge solution

δ⋆  =  (J⊤J+λI)−1J⊤e^,λ=0.05  (RIDGE). \delta^\star ;=; \big(J^\top J + \lambda I\big)^{-1} J^\top \hat e, \qquad \lambda = 0.05 ;(\texttt{RIDGE}).

Ridge rather than plain least squares because JJ is badly conditioned by construction. Two knobs can do nearly the same thing to the sound, which makes columns nearly collinear, and many knobs are nearly inaudible, which makes columns nearly zero. Unregularized, the solve answers both with large, canceling moves.

The support SS is the four knobs with the largest effect ∣δk⋆∣ ∥J⋅k∥\lvert \delta^\star_k \rvert , \lVert J_{\cdot k} \rVert (MAX_KNOBS), and the move is re-solved on it:

δS  =  (JS⊤JS+λI)−1JS⊤e^. \delta_S ;=; \big(J_S^\top J_S + \lambda I\big)^{-1} J_S^\top \hat e .

Truncating δ⋆\delta^\star would throw away the other knobs’ contribution without letting the four that remain compensate; the re-solve is the best move on those four. Choosing the four by effect is a heuristic, not a best-subset search. It is effect and not ∣δ⋆∣\lvert\delta^\star\rvert because a knob that barely moves the sound needs a large coefficient to contribute anything. Ranked by coefficient, that knob headed the support, and the scale below then gave the knob doing the work a sliver of a turn. On Iron Bass, Bright wired to the drive (∥J⋅k∥=0.15\lVert J_{\cdot k}\rVert = 0.15) at +0.5+0.5, and the cutoff (∥J⋅k∥=5.2\lVert J_{\cdot k}\rVert = 5.2, +4σ+4\sigma of centroid per unit) barely moved: 0.03σ0.03\sigma of reach.

The control’s own knobs first. The solve runs twice at most. First it is restricted to the knobs a musician would name for the control (NamedControl::sites: cutoff, tone, … for Bright; mod depth and rate for Motion). If that wiring clears the gate below, it is used. Only if it does not does the solve range over every live knob, with those sites as a soft prior (SEMANTIC_RIDGE). A player who turns Bright and watches the cutoff move has learned something true about the patch. One who watches the amp release move, which is what the unrestricted solve chose on Acid Line, has learned nothing.

Four, because a control is heard as one gesture, and because four is where most of a patch’s audible leverage already is: over the preset library, a patch’s four most audible knobs carry a median 68% of its φ movement (below).

The movement this predicts is JSδSJ_S \delta_S, and three numbers follow from it.

Purity is the cosine between the predicted movement and the direction asked for:

ρ  =  e^⊤JSδS∥JSδS∥. \rho ;=; \frac{\hat e^\top J_S \delta_S}{\lVert J_S \delta_S \rVert}.

ρ=1\rho = 1 is a pure move along the label. At ρ=0.35\rho = 0.35 the off-axis part of the movement is 1−0.352/0.35≈2.7\sqrt{1 - 0.35^2} / 0.35 \approx 2.7 times the on-axis part.

Scale. A full turn may move no knob by more than MAX_TRAVEL =0.5= 0.5 of its range. The knob with the largest effect gets all of it, and the rest follow in proportion, clamped at the same limit:

α  =  0.5∣δS,k∗∣,k∗=arg⁡max⁡k∈S∣δS,k∣ ∥J⋅k∥,tk  =  clip⁡(α δS,k, ±0.5), \alpha ;=; \frac{0.5}{\lvert \delta_{S,k^\ast} \rvert},\quad k^\ast = \arg\max_{k\in S} \lvert\delta_{S,k}\rvert,\lVert J_{\cdot k}\rVert, \qquad t_k ;=; \operatorname{clip}(\alpha,\delta_{S,k},, \pm 0.5),

v(c)  =  clip⁡ ⁣(v0+c t,  0,  1−10−6). v(c) ;=; \operatorname{clip}!\big(v_0 + c,t,; 0,; 1 - 10^{-6}\big).

Purity and reach below are computed from the clamped travel tt, so they describe the move the control actually makes.

The upper clip is KNOB_MAX. Every continuous site is Uniform(0,1)\mathrm{Uniform}(0,1) on the half-open interval, so a knob at exactly 11 has log-prior −∞-\infty and would make the patch un-evolvable. A performance gesture must never do that.

Reach is the predicted movement along e^\hat e at a full turn, in zz units:

R  =  e^⊤JS t. R ;=; \hat e^\top J_S, t .

A control is a search control on this patch when the knobs cannot honestly produce it:

search  ⟺  ρ<0.35  ∨  R<0.15 \text{search} \iff \rho < 0.35 ;\lor; R < 0.15

(PURITY_FLOOR, REACH_FLOOR), or when there is no support or the predicted movement points the wrong way. The reach floor was first set at 0.250.25 against the preset library’s spread. The session pool is spread wider than a curated library, which shrinks every zz distance, and 0.250.25 hid controls that are plainly audible on a live patch.

Several controls turned at once add: each contributes ciαiδSic_i \alpha_i \delta_{S_i} to the knobs it wires, and the sum is clipped. The composition is linear by assumption and is not verified.

Purity measures cross-talk, not correlates

Purity asks whether a move is this control. Measured against the whole of φ, it cannot tell a brightening that also raises the zero-crossing rate and the high band (which every real brightening does) from one that also slows the attack. Over a fresh session pool, Bright’s median cosine with its own axis was 0.26 for that reason. What a player hears as “this control does something else” is movement along another control’s axis, so purity is the cosine with e^\hat e inside the subspace the six named axes span:

ρ  =  e^⊤m(e^⊤m)2+∑k≠self(a^k⊤m)2,m=JSδS, \rho ;=; \frac{\hat e^\top m}{\sqrt{(\hat e^\top m)^2 + \sum_{k \ne \text{self}} (\hat a_k^\top m)^2}}, \qquad m = J_S \delta_S ,

with a^k\hat a_k the other controls’ axes. Reach and position stay on e^\hat e. And two controls whose predicted movements are within ∣cos⁡∣>0.8\lvert\cos\rvert > 0.8 of each other are one gesture with two names: the later one in the order they were wired (for the panel, Bright, Snap, Motion, Body, Grit, Space) becomes a search control (separate, COLLINEAR).

A palette control is not one of the six axes, so the same idea is written for any direction (purity_basis). Take an orthonormal basis b0,…,bqb_0, \dots, b_q of the span of e^\hat e and the six axes, with b0=e^b_0 = \hat e and the rest from Gram–Schmidt over the six in order, and, for the predicted movement mm as above,

ρ  =  e^⊤m∑i=0q(bi⊤m)2. \rho ;=; \frac{\hat e^\top m}{\sqrt{\sum_{i=0}^{q} (b_i^\top m)^2}} .

For one of the six this is the formula above, bit for bit: the other five axes share no coordinate with it, so they enter the basis unchanged (a unit test holds the two equal). A control that leans on some of the six (Thump on Body, and on Snap through crest) takes up what it shares with them, and the remainder of each, the part orthogonal to e^\hat e, counts against it in full: a move of e^\hat e plus an equal part of that remainder has ρ=1/2\rho = 1/\sqrt2 (the unit test checks this for every such pair). One with a coordinate of its own (Air’s zcr_mean) widens the span by that much. A move along the control’s own direction has ρ=1\rho = 1.

Measured over the first 24 patches of a fresh session pool (reach_census, seed 7), with verification on real renders:

ReachableBrightSnapMotionBodyGritSpace
Purity against the whole of φ25%58%58%17%4%38%
Purity against the named axes29%71%62%21%4%38%

Patches on which no control reaches fell from 4 of 24 to 2. The gain is modest because purity was not Bright’s real limit: its median predicted reach is about 0.1σ, since many pool patches have no filter for a named control to turn. That is the honest reading, and a search control’s offer is the answer to it.

The same 24 patches, after the effect ranking, the control’s-own-knobs pass, and a half-travel retry in verify (all three above and below). Both rows are measured on the same build, since the pink-noise fix and the re-voiced presets moved the pool standardizer:

ReachableBrightSnapMotionBodyGritSpacemean per patch
Ranked by coefficient29%67%62%21%4%38%2.21
Ranked by effect50%79%46%29%4%46%2.54

The median verified reach of a reachable control grew three- to four-fold (Bright 0.09σ → 0.33σ, Snap 0.54σ → 0.95σ). Motion lost: 62% → 46%. Motion leans on several small knobs together, and giving the strongest one its whole turn is where a Motion wiring most often turns back on itself. The half-travel retry did not win those patches back. Dropping the weak knobs was tried first and cost Motion more.

Tried and not shipped. Aiming the solve at each control’s population pattern Σe^\Sigma \hat e (the correlation-weighted direction, Haufe et al. 2014) first looked like a large improvement, but only because purity was then measured against the pattern instead of the axis. Measured against the axis, with the pool correlation shrunk toward the identity (Schäfer & Strimmer 2005) and collinear controls separated, it reached fewer patches than the bare axis (Bright 21%, Motion 42%), and on 2 of 12 patches it put Bright and Body onto the same knobs with opposite signs. It was removed.

Verification on real renders

The Jacobian is a local, linear claim, and it fails exactly where a player would notice: at a boundary. On First Bass, which already sits at the floor of motion, the linear prediction said turning Motion down would make it stiller. Rendered, it made it very slightly more restless.

So verify renders every non-search control alone at four settings and measures the movement along its own axis:

m(c)  =  e^⊤(z(v(c))−z(v0)),c∈{−1,−12,+12,+1}. m(c) ;=; \hat e^\top \big( z(v(c)) - z(v_0) \big), \qquad c \in {-1, -\tfrac12, +\tfrac12, +1}.

For each half, with sign s∈{+1,−1}s \in {+1, -1}, the measured reach is

rs  =  {s m(s)if 0<s m(s2)<s m(s)0otherwise. r_s ;=; \begin{cases} s,m(s) & \text{if } 0 < s,m(\tfrac{s}{2}) < s,m(s) \ 0 & \text{otherwise.} \end{cases}

The half must move the asked way at half travel, and further at full travel. A half that moves at the end but reverses on the way is closed. A half is open when rs≥0.075r_s \ge 0.075, half the reach floor. A control with neither half open becomes a search control. The instrument draws a half-closed control’s ring solid on the side it can turn toward and dotted on the other, with a stop at the center, and says which way it turns: turns toward restless only, for Motion on First Bass.

A control that would close at full travel gets one retry at half: the same two-point test over c∈{±14,±12}c \in {\pm\tfrac14, \pm\tfrac12} (the ±12\pm\tfrac12 renders are already in the memo). If a half opens, the wiring keeps half its travel rather than closing.

Total cost for a patch with nn knobs and rr reachable controls is n+1+4rn + 1 + 4r renders, plus two for each retry, all through the memo. In the browser that is around 20–30 renders, and the page caches each measurement by tree, stamped with the standardizer's revision and the render namespace (cache_namespace: the featurizer's RENDER_EPOCH and the quiver version), so returning to a patch costs none. A stamp that no longer matches is played at once and re-measured in the background. The stamp is the standardizer's revision (the status's std_rev), not the vote count: the scale moves when a fit runs over sounds the session had not met, and a pick alone left every kept wiring stale. Every preset’s measurement also ships with the app (apps/web/perform-wirings.json, made natively through the same WasmEngine calls by make perform-wirings), so a preset is playable the moment it lands; the page re-measures it in the background, because the file was measured under a standardizer fitted to a standard pool, not the session’s. The view re-wires after every patch change, and after a glide or a Keep that carries the knobs out of the neighborhood the wiring was measured in (see below), so the claims are always about the neighborhood the sound is in. A background re-measurement that wires each control to the same knobs is taken in place, without re-centering the controls.

The gate, and why it samples somewhere else

named_controls_move_the_sound_they_name wires and verifies four presets (First Bass, Ceiling, Detune Dream, Long Way Down) and then checks every open half at c=±34c = \pm\tfrac34, a point verification never rendered:

s (e^⊤z(v(3s4))−e^⊤z(v0))  >  −0.05(MONO_TOL). s,\big(\hat e^\top z(v(\tfrac{3s}{4})) - \hat e^\top z(v_0)\big) ;>; -0.05 \qquad (\texttt{MONO_TOL}).

It requires at least eight open halves, so a wiring change that closed most of them would fail the gate rather than pass it vacuously. The palette’s twelve are held to the same check on the same four presets, each wired alone, and must show at least 16 open halves over at least 8 of the twelve.

It samples somewhere else because no finite set of samples proves a response monotone. A smooth function can agree with any finite set of points and reverse between them. Checking an unsampled point is the measurable form of the promise, and a check at the points verification already used would be the same test twice.

The tolerance is stated rather than zero because a five-second render has numerical noise. 0.050.05 zz units is two orders of magnitude below an audible difference and above that noise. A check with no tolerance failed on Detune Dream’s Snap, which reversed by 0.0180.018: real, measurable, and far below anything a listener would hear. That is the case the tolerance exists for. Verification itself has no tolerance: a half that reverses at a sampled point is closed however small the reversal.

The measurements, and what reproduces them

Per patch, not per knob kind. The obvious alternative to measuring a Jacobian per patch is a table: what a cutoff knob, or an attack knob, usually does. Both were measured over 61 presets. The table was built leave-one-out, from per-site-kind averages over the other 60, so no preset was wired by a table that had seen it.

Median purityBrightSnapMotion
Wired from the patch’s own Jacobian0.610.770.75
Wired from the best leave-one-out per-site table0.230.160.09

The same knob does different things in different patches. That is the reason the grammar exists, and it is the reason the table is never the last word.

It is the first one, though (#290). A first measurement is 8 to 71 renders, a minute and more on a slow computer, and a sound nobody has measured plays its controls at once on a wiring that costs none: one kept for a sound of the same shape (the same modules and selectors, so the same knobs; predict::shape_of) if one was measured, and otherwise one predicted from a table of how each kind of module's knob moves φ (predict::KnobTable: the median measured column per module kind, site, modulation target and third of the range, backing off to coarser keys), run through the same solve. The measurement then lands on it by a rebase, so nothing heard moves. Until it does, a control playing on either says not measured yet: a borrowed wiring was measured, on another sound, and is not gated; a predicted one is gated (below). Judged against each sound's own Jacobian, held out (examples/wire_predict.rs, 240 pool sounds from six sessions):

Table learned fromWiresTurns the named wayCovers the measured reach
The presets76770%53%
The presets and one session's pool68876%56%
The presets and five sessions' pools57979%50%

The gate. It is right on some controls far more than others (Space 99%, Bright and Snap about 78%, Motion 62%, Body 63%), so a control is wired from the prediction only where the table has shown it can be. make perform-wirings learns the shipped table from the presets' Jacobians and 240 pool sounds' (the standard pool's and five more sessions'), and for each palette control counts, on every pool sound held out of the table in turn, how often the prediction wired it and how often that turned it the named way (KnobTable::agreement). A control passes when the lower end of the Wilson interval at two standard errors reaches 0.70 (PREDICT_GATE, GATE_Z): more than two turns in three the named way, after paying for how few turns there were, so a perfect record needs ten. One session's pool is too few to read it on: across six, one pool's Bright read 65% and another's Motion 72%. The rest wait for the measurement and read listening…, as do controls the prediction cannot reach (a guess does not say a patch can't).

ControlWiredNamed wayBound
Bright13982%0.746passes
Snap23183%0.776passes
Motion10860%0.506
Body1932%0.151
Grit5100%0.556
Space7399%0.924passes

Of the palette's twelve, Warmth, Thump, Round, Distance, Haze and Bite pass; Air, Heft, Punch, Throb, Sway and Lo-fi do not. shipped_wirings.rs pins the list. By ear, rendering each gated control turned fully up and fully down on a fresh session's 40 sounds (wire_predict --shipped), 81% moved the named way turned up and 66% both ways (ungated, 66% and 55%), and the prediction wires 58% of the controls the measurement reaches. "The named way" is the sign of the movement along the control's own direction, not how much else moves with it, so a purity row like the one above would read lower.

Grit and Space measure a median purity of about zero by knobs alone on most presets, because most patches contain no drive or reverb to turn. They are the controls most often drawn as search controls.

Grafts. Turning a search control first tries to give it something to turn (graft_for). Bright and Body get a flat EQ, placed below any stereo module that ends the chain, because above one it folds the patch to mono (Ghost Bell moved 0.27σ that way). Space, turned up, gets its amp release raised to 0.6 (≈250 ms). A reverb was tried first, and every effect here sits before the amp envelope: on First Bass with a reverb grafted, ∂Space/∂mix measured −0.04 and ∂Space/∂release +3.65. Grit gets nothing (see the open question). perform_inserts measures each graft. Over the preset bank, the EQ is transparent (median |Δz| 0.000; the unit test bounds it at 0.05σ). It opens Bright on 7 of the 10 presets where Bright was a search control, and Body on 15 of 48. The release graft opens Space on 41 of 46, at 1–2σ of reach. It is not transparent, and is not meant to be: it is what “farther” asked for.

Leverage. Nudging every knob of every preset by ±0.15\pm 0.15 and measuring how far φaudio\varphi_{\text{audio}} moves, in units of the library’s own per-coordinate spread: over 61 presets and 821 knobs, a patch’s four most audible knobs carry a median 68% of its total movement and its top eight 94%. 172 of the 821 knobs barely move it at all. That is what makes MAX_KNOBS =4= 4 a real operation rather than a random pick with a story attached.

ExampleProduces
cargo run -p auracle-features --example jacobian_probe --release > jac.csv∂φaudio/∂knob\partial\varphi_{\text{audio}}/\partial\text{knob} for every preset: the raw material for both purity rows
cargo run -p auracle-features --example leverage_probe --release > leverage.csvPer-knob leverage for every preset
cargo run -p auracle-session --example perform_wiring --release -- "First Bass"The shipped wiring on named presets: knobs, purity, reach, position, search
cargo run -p auracle-session --example offer_cost --release -- 12 3 20What an offer, an aimed offer and a drift cost, per preset and as a distribution, and how much of it is renders (offer_cost.mjs in auracle-wasm's examples is the wasm twin)
cargo run -p auracle-session --example perform_inserts --releaseFor each preset’s search controls, whether PERFORM’s graft is transparent and whether it makes the control reachable
cargo run -p auracle-session --example reach_census --release -- 24 7How many controls reach the patches of a fresh session pool, with verification, and how the gate would read with purity against the whole of φ
cargo run -p auracle-wasm --example palette_census --release -- 3 --prototypeThe palette: the eighteen directions, their cosines, how often each reaches the presets, and what measuring them costs natively
node crates/auracle-wasm/examples/palette_cost.mjs 4The same measurement’s cost in wasm, the six against the eighteen (make wasm first)

The two probes print CSV and the medians are computed from it. jacobian_probe uses central differences on raw φ at the same h=0.08h = 0.08, so it measures the same response as the shipped code without being bit-identical to it. perform_wiring runs the shipped jacobian and the bare-axis wire under a preset-library standardizer, and does not run verification; reach_census runs the shipped path (Engine::wire_controls) with verification.

The palette: eighteen directions

RFC-006 turns PERFORM’s controls into a palette of eighteen in six families, of which the player places up to eight. The engine defines all eighteen (PALETTE in perform.rs) and measures any of them exactly as it measures the six: one Jacobian, the ridge solve onto at most four knobs, the purity and reach gate, separation, and verification on real renders (Engine::wire_named; the arithmetic alone, unverified and without a render, is wire_set). The first six entries are CONTROLS, at the same indices, so an index names the same control in either list. The app wires the controls the player has placed on PERFORM’s panel, at most eight (PANEL_MAX in perform.js): for the six it sends no controls, so the request is the one it always was, and for any other panel it sends the panel’s set.

The set is asked for in palette order, whatever order the panel shows. separate makes the later of two collinear controls the search control, so the order asked is part of the answer; asking in palette order makes the answer a function of the set alone, so reordering the panel costs no renders, and the six keep the precedence the census above measured them with (“beside the six”). The page keys its cache of wirings (wireKey) by the patch and the set: the patch’s own key for the six, which is the key every kept and shipped wiring already had, and that key with #controls= and the set for any other. A set not measured on a patch yet borrows, control by control, from any set that was (borrowWiring), and is measured behind it.

How a control is named across the boundary. perform_wire’s controls is a JSON array of palette indices, read entry by entry: a non-negative whole number is an index, and an index out of range, a repeat, or anything else in the array (a negative, a fraction, a string) is dropped on its own. What is not an array at all means the six. An array with nothing valid in it wires nothing and renders only the patch itself. The reply’s wiring follows the order asked, and each entry carries its palette index (Wiring::index) beside its name. The page names a control back to the engine by that index (perform_offer’s control, perform_graft’s k), never by the entry’s position: asked for [16, 6], the first entry is Bite with index 16, and a position of 0 would aim along Bright. Only for the six asked in order are position and index the same.

The directions

Each of the twelve is a direction of its own over φ’s coordinates, normalized like the six:

FamilyControlLow · highWeights before normalizingWhat it means in φ
ToneBrightdark · brightcentroid_mean +1+1, rolloff_mean +1+1The six, above
ToneWarmthcold · warmbass_fraction +1+1, high_ratio −1-1Weight low down and a soft upper register: the highest note comes through quieter than the held one, as under a low-pass that does not follow the keys
ToneAirclosed · airyzcr_mean +1+1, rolloff_mean +12+\tfrac12, centroid_mean −12-\tfrac12The very top, above the notes: the highest partials and any breath, and the rolloff, measured against the centroid, so the top opens while the body of the sound stays
WeightBodythin · fullbass_fraction +1+1The six
WeightThumplight · thumpingbass_fraction +1+1, crest +1+1Weight low down that hits
WeightHeftslight · heavyrms_mean +1+1, bass_fraction +1+1Dense, held weight: frames full of level (which loudness normalization gives a sustained, low sound, since K-weighting counts the lows for less) and weight low down
DynamicsSnapbloom · snapattack_s −1-1, crest +1+1The six
DynamicsPunchgentle · punchycrest +1+1, rms_std +1+1The size of the hit against the rest: peaks, and a level that moves over the phrase
DynamicsRoundhard · roundattack_s +1+1, rolloff_mean −1-1A soft attack and few harmonics, the voice’s round
MovementMotionstill · restlessheld_centroid_std, motion_slow, motion_mid, motion_fast, each +1+1The six
MovementThrobsteady · throbbingmotion_mid +1+1Pulsing and tremolo: the held note’s motion at 2–8 Hz alone
MovementSwayfixed · swayingmotion_slow +1+1Sweeps and breathing: the held note’s motion at 0.5–2 Hz alone
SpaceSpaceclose · fartail_ratio +1+1The six
SpaceDistancenear · distanttail_ratio +1+1, attack_s +12+\tfrac12, crest −12-\tfrac12, rolloff_mean −12-\tfrac12What distance does to a sound: a longer tail, a softer attack, smaller peaks and a duller top
SpaceHazeclear · hazytail_ratio +1+1, motion_fast +1+1, crest −1-1A wash: a tail, a shimmer (the 8–30 Hz beating that detune and chorus give) and peaks smoothed away
CharacterGritsmooth · roughflatness_mean +1+1The six
CharacterBitemild · bitingflux_mean +1+1, zcr_mean +1+1An edge: the spectrum changing fast, and high partials (a filter that snaps open, a resonance that rings)
CharacterLo-ficlean · wornflatness_mean +1+1, rolloff_mean −1-1, motion_fast +1+1Worn like tape: hiss, a dull top and flutter

Three things φ lacks shaped these. It has no low-mid band, so Warmth is not quite the voice’s warm, “weight in the low middle, a soft top”. It measures weight low down (bass_fraction, below about 250 Hz) against a soft top of the keyboard (−high_ratio: the highest note quieter than the held one). That is close to the word, and not exactly it: a sound can gain low-middle warmth that this does not see, and lose some that it does not count. Defined with the spectrum’s top instead (rolloff_mean down with bass_fraction up), it moved with Body across the sounds (r=0.92r = 0.92), and on 28 of the 40 presets where both it and Bright reached it was Bright’s gesture, which is why it reads the keyboard’s top and not the spectrum’s. φ has no bit-depth or bandwidth feature, so a crusher reaches Lo-fi only through the flatness it adds. And its only space coordinate is tail_ratio, which the amp release sets (a reverb’s tail is cut at note-off), so Distance and Haze lean on what else distance and a wash do to a sound.

Two names for one control

The approved prototype (docs/notes/vision-2026-09/prototype/perform.js) defined the twelve as blends of the six. Five pairs of those blends were one direction, ∣cos⁡∣≥0.9\lvert\cos\rvert \ge 0.9: Air and Bright (+0.94+0.94), Softness and Snap (−0.94-0.94, Snap turned down), Wobble and Motion (+0.99+0.99), Distance and Space (+0.92+0.92), and Warmth and Air (−0.94-0.94). Punch was +0.89+0.89 to Snap. That is why each of the twelve above is its own direction. Redundancy was then measured three ways over the eighteen, on the presets and the shipped engine’s pool:

  • The directions themselves, e^i⊤e^j\hat e_i^\top \hat e_j: no pair reaches 0.90.9. The largest are Space and Distance (+0.76+0.76) and Body with each of Warmth, Thump and Heft (+0.71+0.71).
  • The sounds’ positions along them, correlated over the 62 presets and the pool of 40: no pair reaches 0.90.9. The closest are Motion and Throb (+0.88+0.88), Snap and Distance (−0.87-0.87), Motion and Sway (+0.85+0.85) and Throb and Sway (+0.83+0.83): a sound that moves tends to move in every band, and a distant one tends to have a slow attack.
  • The wirings: over the presets where both reach alone, how often their predicted movements are one gesture (∣cos⁡∣>0.8\lvert\cos\rvert > 0.8, what separate checks). Only Space and Distance do on more than half (9 of 14): where a patch can reach Space at all, it is through the release, and Distance turns it too. A first Heft that also carried −-crest was Thump turned down on two presets in three (both turned the amp envelope, opposite ways), and was changed to the definition above.

How often each reaches

Each control wired on each of the 62 presets, on the engine the shipped wirings are measured under. Alone is the control wired by itself: whether this patch has knobs that move it, purely and verifiably. Beside the six is the control wired after the six, so a control whose gesture on a patch is one of theirs (∣cos⁡∣>0.8\lvert\cos\rvert > 0.8) is a search control there: whether it adds a gesture the panel does not have. Both halves is both directions open after verification.

FamilyControlAloneBeside the sixBoth halvesMedian purityMedian reach (σ)
ToneBright79%79%74%0.811.64
ToneWarmth73%52%26%0.700.57
ToneAir66%48%35%0.600.47
WeightBody53%32%21%0.540.68
WeightThump81%40%27%0.701.55
WeightHeft76%52%19%0.650.77
DynamicsSnap82%82%32%0.991.56
DynamicsPunch73%60%15%0.890.92
DynamicsRound82%44%34%0.741.18
MovementMotion77%74%26%0.981.91
MovementThrob47%29%6%0.751.80
MovementSway55%34%5%0.942.67
SpaceSpace23%23%3%0.982.18
SpaceDistance94%39%32%0.551.16
SpaceHaze90%63%35%0.691.49
CharacterGrit11%6%11%0.580.29
CharacterBite81%58%37%0.730.72
CharacterLo-fi56%34%23%0.560.91

Purity and reach are medians over the presets the control reaches alone. For the six, “beside the six” is the panel as it is today: Body and Grit lose patches to the gestures of the controls wired before them. Alone, a median preset is reached by 12 of the eighteen (5 at least, 16 at most), against 3 of the six.

Read the table with one caution. Purity measures cross-talk against the named axes, not whether a control moved every coordinate it names, so a direction is reached through whichever of its coordinates the knobs move. On a patch where nothing moves the flatness, Lo-fi is reached by a duller top and flutter, and Distance (94%) by a softer attack and a duller top, since few patches can move their tail (Space reaches 23%). Throb and Sway rarely open both halves: a sound that is still cannot be made stiller.

What it costs

A measurement is n+1n + 1 renders for the Jacobian, shared by every control, then four per reachable control and two more for each retry. Wiring eighteen instead of six multiplies only the arithmetic (the solve per control takes microseconds) and the verification renders.

Per presetRenders, medianMeanMostNative s, meanwasm s, mean
The Jacobian alone1212.123
The six, today2526.2425.97.5
All eighteen4949.88411.214.2

The render counts are over all 62 presets (palette_census). The native times are from the same run, three presets at a time on an Apple M3 Max shared with other work, at 224 ms a render (173 ms in a quieter run). The wasm times are palette_cost.mjs under node, on one thread as the engine worker has, over every fourth preset (16), at 265 ms a render. That run boots its own pool from the same seed, and in wasm the pool comes out differently from the native one, so its counts differ a little per preset (median 28 renders for the six, 60 for the eighteen).

A control that reaches costs about five verification renders: 4.7 for the six, and 5.0 for the eighteen wired in palette order, where 7.5 controls reach a preset on average. So the eighteen double today’s measurement. The panel never needs all eighteen. To keep within today’s budget:

  1. Wire all eighteen by prediction from the one Jacobian the six already pay for. That is arithmetic, and enough for each palette entry to preview what it would do, drawn as a guess (ADR-012): verification closes some predicted reaches (Throb predicted on 71% of presets alone, verified on 47%).
  2. Verify only the placed controls, at most eight. A panel of the six and two of the twelve adds one or two controls that reach (the twelve reach a mean 46% of presets beside the six, 73% alone), so five to seven renders, a fifth to a quarter more than today’s measurement.
  3. Verify a control placed later from the memo: the Jacobian is already there, so it costs only its own four renders, and two more if it is retried at half travel.

The app does the second and the third: it measures the panel’s set and nothing off the panel, on the sound in hand, when PERFORM is in sight (measurePanel in perform.js), and the engine’s memo holds the Jacobian from the six’s measurement. The first, a preview of every palette entry by prediction, is not built (below).

The shipped preset wirings stay the six’s. With the twelve’s wirings beside them, apps/web/perform-wirings.json would weigh 391,740 bytes instead of 173,171 (2.3 times), fetched by every visitor for controls the panel does not show yet.

Names

Three of the prototype’s names are changed, and the maintainer approved them with Heft and the end words below on 2026-10-01 (voice):

  • Round (hard · round) for Softness (hard · soft): the voice’s word table already defines round as “a soft attack, few harmonics”, which is this direction.
  • Throb (steady · throbbing) for Wobble: Wobble Board is a preset, and a control of the same name reads as that sound. Throb is the tremolo module’s own tag. Pulse was the other candidate, and it is a wave shape.
  • Sway (fixed · swaying) for Drift: drift is already WANDER’s zone and the walk behind it (Engine::drift). Breath would read as Air’s breathiness, and Sweep Machine is a preset.

Heft (slight · heavy), the twelfth, is new. The four have their rows in the voice’s word table.

Drift: a local walk on the live knobs

Engine::drift samples the same target

πβ(x)  ∝  pgrammar(x) exp⁡ ⁣(β E[uθ(φ(x))]),\pi_\beta(x) ;\propto; p_{\text{grammar}}(x),\exp!\big(\beta,\E[u_\theta(\varphi(x))]\big),

restricted to this patch’s shape: every structural and categorical address, every continuous site without a live handle, and the player’s own locks are held fixed; the walk moves only live_knobs. Holding sites fixed in a Metropolis–Hastings walk is exact conditioning (Locks as conditional refinement), so the walk targets πβ(v∣xL)\pi_\beta(v \mid x_{\mathcal{L}}) over the knobs the voices can take live. Structure cannot change under the player’s hands, and nothing the walk moves needs a recompile to be heard.

The kernel is not refinement’s. Each step picks one free knob uniformly and proposes

v′  =  reflect⁡[0,1) ⁣(v+σ ξ),ξ∼N(0,1), v' ;=; \operatorname{reflect}_{[0,1)}!\big(v + \sigma,\xi\big), \qquad \xi \sim \mathcal N(0, 1),

accepted with probability min⁡ ⁣(1, πβ(x′)/πβ(x))\min!\big(1,\ \pi_\beta(x')/\pi_\beta(x)\big). The reflected Gaussian is symmetric, so there is no Hastings correction (Engine::drift). Refinement’s kernel, fugue’s adaptive single-site MH, starts every fresh chain at a step of scale 1 on each site and adapts it only after ten proposals there, so on a unit-interval knob each step of a short walk is a Gaussian as wide as the whole range, reflected back into it: close to a fresh draw. An offer of 8 steps with every site but the live knobs locked moved its farthest knob 0.36–0.68 of its range over the table’s 12 presets (its last row). A drift should wander, and how far is the Wander dial’s to say.

WanderStepsσ\sigmaFarthest knob moved (12 presets)
drift, at its start80.050.06–0.14
drift, at its top180.080.15–0.33
roam, at its top400.150.25–0.61
refinement’s kernel, the live knobs alone81, at first0.36–0.68

(cargo run -p auracle-session --example drift_distance --release.) Within each zone the pace rises linearly with the dial (wanderPace, in perform.js); roam starts at 24 steps and σ=0.10\sigma = 0.10. The walk returns its end state, or nothing if it ends where it started. Like refinement, a short walk’s end state is local movement on πβ\pi_\beta, not a draw from it (What is not sampled). Nothing enters the pool: a performance gesture is not a candidate until the player keeps it.

The wiring survives a small drift. The named controls are a linear model measured with 0.08 knob steps, so the instrument re-measures them only when some knob has left a 0.12 neighborhood of where they were measured (TRUST, in perform.js). A gentle drift usually stays inside and costs nothing; before, every glide was followed by a full re-measure of about 46 renders, which in drift kept the worker busy much of the time and queued offers behind it.

The instrument then glides the knobs from where they are to the returned values along a smoothstep, v(t)=v0+(v1−v0)(3u2−2u3)v(t) = v_0 + (v_1 - v_0)(3u^2 - 2u^3), over 2 to 6 seconds. The intermediate states are interpolations, not states of the walk. They are all valid patches, since the structure is fixed and the knob box is convex. A touch stops the glide where it is.

Offers

Engine::offer is the same walk with only the player’s locks, so structural moves are allowed: it may add, remove, or replace a module. It is also non-inserting. The instrument asks for 20 steps (40 in roam) and plays the result in the B slot, never as a jump. The Offer pad and Wander ask for this walk. A search control released more than 0.30.3 from its center (ASK_AT, in perform.js) asks for an aimed one (below), and springs back without moving a knob.

A search control’s offer is aimed

Engine::offer_toward walks the same kernel on the target tilted along the control’s direction e^\hat e, turned up (s=+1s = +1) or down (s=−1s = -1):

πγ(x)  ∝  pgrammar(x) exp⁡ ⁣(β (f(x)+γ s e^⊤z(x))), \pi_{\gamma}(x) ;\propto; p_{\text{grammar}}(x), \exp!\Big(\beta,\big(f(x) + \gamma, s, \hat e^\top z(x)\big)\Big),

where ff is the taste surrogate E[uθ(φ(x))]\E[u_\theta(\varphi(x))], or VetOnlyFitness before any fit, and γ\gamma is AIM_GAMMA =1= 1. At β=2\beta = 2, a proposal one σ further the asked way gains as much log-weight as one unit more of expected utility. TiltedFitness reads zz from the memo entry the inner fitness has just written, so the tilt costs no render, and a proposal that does not vet keeps its quarantine score untilted.

Twenty single-site steps rarely propose the one module that makes a patch rough (a noise source, a crusher), and the tilt cannot make a proposal the kernel never draws. So a walk that has not moved at least REACH_FLOOR the asked way,

s e^⊤(z(xend)−z(x0))  <  0.15, s,\hat e^\top\big(z(x_{\text{end}}) - z(x_0)\big) ;<; 0.15,

keeps walking from the state it stopped in, up to AIM_WALKS =3= 3 walks of the asked steps. It is one longer chain that stops as soon as it has arrived, not a filter: nothing grown is thrown away, which is what the rejected alternative (grow several undirected offers and keep the one that moved most) would have done.

The reply carries moved =e^⊤(z(offer)−z(home))= \hat e^\top\big(z(\text{offer}) - z(\text{home})\big) (Engine::moved_along), and B’s strip prints s⋅s \cdot moved in amber: grittier by 1.8σ. Below half of REACH_FLOOR (AIM_SAID, in perform.js: the line a verified half must clear to be said to turn that way), it says the walk did not get there, not grittier: this walk found no way there, and invites another turn.

The census. γ\gamma and the walk count were chosen by make offer-census (offer_census): 16 presets (every third in the bank), every control PERFORM draws as a search control on each (verified, as the app wires them: Grit on 14, Body on 14, Space on 12, and a few of the rest), turned both ways, two seeded offers of 20 steps a walk per arm, the same seeds in every arm so the arms are paired and 0×10{\times}1 is the Offer pad’s walk itself. The session is a filled pool (its standardizer) with a taste taught by the synthetic listener search_health climbs toward, which dislikes noise; the prior rows are the same session before any fit. A move counts when it is at least REACH_FLOOR the asked way; R∗=0.95R^\ast = 0.95σ is the median verified reach of a control that does reach, on the same presets.

γ×\gamma \times walks≥ floor, taught≥ R∗R^\ast, taughtmedian ΔE[u]\Delta\E[u], taught≥ floor, priorGrit up ≥ floor, taught / prior
0×10 \times 1 (Offer pad)22%13%+0.9223%7% / 14%
0.5×10.5 \times 126%16%+0.8431%14% / 35%
1×11 \times 134%23%+0.7435%17% / 35%
2×12 \times 139%22%+0.6336%25% / 32%
4×14 \times 140%23%+0.6238%32% / 32%
0×30 \times 332%18%+1.7241%17% / 32%
1×31 \times 3 (shipped)46%28%+1.3353%46% / 64%
2×32 \times 348%28%+1.1854%50% / 71%

(192 offers per arm. ΔE[u]\Delta\E[u] is the offer’s expected utility less the patch it grew from; the pool’s spread of E[u]\E[u] is 0.72.)

Reading it: the tilt buys most of what it can by γ=1\gamma = 1. Past that, more aim buys a few points of the floor, none of R∗R^\ast, and a lower E[u]\E[u], so 1 is the smallest γ\gamma at which the curve has flattened. The walks do more than the tilt for the control that needs them most. Grit turned up went from 7% (Offer pad) to 17% with the tilt alone and 46% with three walks, after a taste that dislikes noise, and from 14% to 64% before any fit. Continuing without the tilt (0×30 \times 3) does less than continuing with it (32% and 41% of all asks, against 46% and 53%). The taste cost is bounded: every arm’s median offer still climbs E[u]\E[u].

Some asks have nowhere to go, and no γ\gamma changes that: Grit down and Space down moved in none of 28 and 24 trials, because a patch with no noise sits at the floor of flatness and one with no tail at the floor of tail_ratio. B says not smoother then, which is the truth. Space up reaches 29–45%; the instrument asks for it only when the release graft did not reach.

What it costs in time. The tilt costs no render; the extra walks do. Timed natively on a shared four-core machine (offer_census --timed, each offer from a fresh memo holding only the patch it grew from, as in the app), one tilted walk took 5.1 s on average against 5.1 s for the untilted one, and the shipped offer, which walks again only when it has not arrived, 15.6 s against 6.0 s for the Offer pad’s. The instrument counts the seconds in B while it grows. Growing it on the render farm, and starting both ways at pointer-down, would take the wait off the player’s hands; that belongs to the farm’s walk path and is not built here.

Whether it holds the engine. It does not. A walk is a chain of steps, and a step costs at most one phrase render (about 0.15 s natively, 0.3 s in wasm under node on the machine this was timed on, offer_cost), so the engine worker runs an offer or a drift one step at a time and answers the player’s picks, Keeps and plays between steps. An offer you did not ask for (the spare grown while you play) gives way to one you did. Cutting a walk up does not change what it finds: for a seed, the offer is the same tree whatever the step sizes (the walk is the same code, run in pieces), and what you do between steps does not move it, because it keeps the target it began on and draws from a generator of its own.

Before any evidence: VetOnlyFitness

With no posterior there is no utility to climb, and the first version of PERFORM returned nothing for drift and offers until the player had made picks. But the posterior before any evidence is not undefined. It is the prior.

With a zero-mean prior on θ\theta and a single style, the prior expectation of utility is E[θ]⊤z=0\E[\theta]^\top z = 0 for every patch, so the target is pgrammarp_{\text{grammar}} itself. VetOnlyFitness writes that down, with the vetting gate kept:

f(x)  =  {0x vets−50otherwise (QUARANTINE_FITNESS)⟹πβ(x)  ∝  pgrammar(x) eβf(x). f(x) ;=; \begin{cases} 0 & x \text{ vets} \ -50 & \text{otherwise } (\texttt{QUARANTINE_FITNESS}) \end{cases} \qquad\Longrightarrow\qquad \pi_\beta(x) ;\propto; p_{\text{grammar}}(x), e^{\beta f(x)} .

At β=2\beta = 2 an unvetted term is down-weighted by e−100≈4×10−44e^{-100} \approx 4 \times 10^{-44}, so πβ\pi_\beta is pgrammarp_{\text{grammar}} restricted to listenable patches, to any precision that matters. The proposal distribution is the plain grammar prior too, since the taste tilt needs a posterior.

Every drift and offer reply carries whether it was taste-directed (Engine::has_taste), and the instrument says which: the line under Wander reads drift · gliding · no taste yet while a grammar-drawn drift glides, and drift · gliding once there is a taste to walk toward. Wiring the named controls needs no taste at all, only a standardizer.

The B slot

An offer is heard through a second LivePoly in the same AudioWorklet. It receives every note-on, note-off, bend, glide, unison, and arpeggiator message the first one does, and notes held when it loads are replayed into it, so it joins a chord already sounding. It renders continuously while loaded, so its envelopes and tails are in step with A when the mix moves.

The mix is equal-power, with the mix position mm smoothed per sample:

y=cos⁡ ⁣(π2m) yA+sin⁡ ⁣(π2m) yB,m←m+0.002 (m∗−m). y = \cos!\big(\tfrac{\pi}{2} m\big), y_A + \sin!\big(\tfrac{\pi}{2} m\big), y_B, \qquad m \leftarrow m + 0.002,(m^\ast - m).

The one-pole has a time constant of 500 samples, about 10 ms at 48 kHz, so a Peek is a gesture rather than a click. The gains satisfy gA2+gB2=1g_A^2 + g_B^2 = 1, which holds the summed power constant when A and B are uncorrelated. When they are nearly identical the sum rises by up to 3 dB at m=12m = \tfrac12, since cos⁡45°+sin⁡45°=2\cos 45° + \sin 45° = \sqrt2. An equal-gain law would have the opposite error, flat for identical sources and 3 dB down for unrelated ones. An offer is a different patch, so the equal-power error is the one taken.

B is loudness-matched. Its makeup gain is the one loudness normalization computes for the offer, TARGET_LUFS minus the phrase’s measured lufs_before, so the offer’s standard phrase plays at −18 LUFS. The gain is clamped only to the range the voice accepts (MAKEUP_MIN_DB to MAKEUP_MAX_DB, −24 to +60 dB, in auracle-wasm’s live.rs). It is the same makeup every live patch gets (live_makeup, in level.rs). It used to be clamped to ±12 dB, which left 43% of a fresh pool outside the clamp; a leveler on the summed polyphony now catches a held note that grows louder than the phrase predicted. Without the match a crossfade would mostly compare levels, and the louder side reliably wins. The match is made on the standard phrase at each patch’s own settings; a named control turned on A afterward changes A’s level without re-normalizing it.

Which way your taste leans

Under the model view (hold ⌥, or MODEL), each control carries its lean: how the model’s rating of the sound in hand changes as the sound moves along the control’s direction. With z0=z(x)z_0 = z(x) the sound’s standardized φ\varphi and e^\hat e the control’s unit direction, extended to all dd coordinates with zeros on the structural block (turning a control moves the sound, never the patch’s module counts), the lean of one posterior draw is the derivative of its utility along e^\hat e:

ℓ=∂∂t u ⁣(z0+t e^)∣t=0=θk⋆⊤e^,k⋆=arg⁡max⁡k θk⊤z0.\ell = \frac{\partial}{\partial t}, u!\left(z_0 + t,\hat e\right)\Big|{t=0} = \theta{k^\star}^\top \hat e, \qquad k^\star = \arg\max_k, \theta_k^\top z_0 .

The utility is a maximum of experts, piecewise linear, so its slope at a sound is the slope of the style that claims that sound, and k⋆k^\star is chosen per draw: a draw in which another style rates the sound highest answers with that style’s θ\theta. It is not the mean θ\theta of one style projected on e^\hat e, which would describe a style that may not be the one rating this sound. Far enough along e^\hat e another style can take the sound over, so a lean says what happens near the sound, not along the whole control. Which style a draw names does not depend on how the styles are labeled, so no alignment is needed.

The instrument is sent the importance-weighted mean and standard deviation of ℓ\ell over the draws (TastePosterior::slope, through Engine::lean; in utility per unit of zz moved toward the control’s high word), and draws it on the control’s dial: an arc from 12 o’clock toward the end it leans to, its ±1\pm 1 SD interval behind it, every control of the panel on one scale. A lean whose interval crosses zero (∣mean∣<SD\lvert \text{mean} \rvert < \text{SD}) is drawn as a guess, the rule LEARNING’s weights and PATCH’s worth chips use. Before the first fit there is no posterior and perform_lean answers null: nothing is drawn. Opening a taste file takes the posterior away until it is fitted again from the file (a file with nothing taught in it asks for no fit), and the leans go with it.

The lean is taken at the tree PERFORM measures, with no overrides. That tree's render is in the engine's memo once PERFORM has measured it (the measurement renders it first) or the bench has opened it, and then the lean is a few dot products per draw; a tree not in the memo costs one render, as ▶ does. A control turned since is not part of it, and it is asked again when the view comes up, the sound or the panel changes (for a sound with an AUDIO IN, a new audition clip of an input it reads too, since it is measured through it), and the posterior moves (a refit, a pick’s reweighting, a taste file opened), never per frame.

What is not done

  • An aimed offer is aimed at a direction, not at a sound. A search control’s offer tilts the target along e^\hat e (above); it does not aim at a reference sound. Breeding a generation toward a recording is a sound of your own, which the engine has and PERFORM's offers do not use. Nor is the aim itself tuned per patch or per player: repeated turns the same way do not ask harder, and Wander’s offers are not aimed at the last control turned (RFC-002’s open questions).
  • The palette doesn’t preview. A palette entry not on the panel is not measured, so the palette shows nothing of what it would do to this sound. The preview by prediction from the Jacobian (the first of the budget’s three points, above) needs the unverified wiring (wire_set) exposed to the page, and is not built. The twelve have no grafts yet, so a search control among them asks for an aimed offer only. The shipped preset wirings are the six’s, so a preset opened with a palette control on the panel plays the six at once and measures the rest.
  • The directions are fixed, not personal. The eighteen are the same for every player. A control along a fitted style θk\theta_k is a different and more interesting object, and not this one.
  • Most of what the player does here is logged, not fitted. Keep, Back, Take, each offer asked for, and each control turn are recorded as ImplicitEvents (perform_keep, perform_back, perform_take, perform_offer, perform_turn), and none of those events enters the likelihood. A Keep can mean I love this or stop drifting for a moment, and implicit signals stay out of the model until a fit using them can be validated against the explicit ones. The exception is an offer’s answer: once B has been heard for a second (HEARD_MS, in perform.js), Take, or asking for another offer, is recorded as a duel with the PerformOffer provenance, and it counts as a pick.
  • Combinations are not verified. Each control is verified alone, at v0v_0.
  • Motion hears one note. Its axis is built from the held note’s span, with the limits that implies.