Lab

Core

@audio-ui/core: the framework-agnostic logic under every audio/ui control and device, in modules you import one at a time, the same in React, plain DOM, Vue, Svelte or a worker.

@audio-ui/core holds the logic of every control that is not its view: the controller of each one, its geometry, values and their scales, and the sources a view follows outside its render. No framework, no DOM required for the logic, no Web Audio, and no dependency. The React primitives and the custom elements are each one adapter over it; a page of your own can be another. What makes and times the sound is in Engine.

It is one package, npm install @audio-ui/core, and each module is its own entry point, so a page pays only for what it imports.

Controls

The controller of each control: its value, its gesture, its keys and its formatting, whatever draws it. Controllers is the contract they share.

ModuleControls
knob, fader, xypadOne or two bounded values dragged, stepped and typed.
meterLevels on a scale, their ballistics, painted every frame.
envelope, plotPoints on a curve, and a plot's axes, paths, ticks and handles.
piano, padKeys and pads struck with a velocity.
sequencer, piano-rollSteps and notes on a grid: selection, editing, scales.
timeline, waveformClips in time, a zoom and a playhead; a recording's peaks and a seek.

The root

@audio-ui/core itself holds what every module shares: ranges, scales and stepping (resolveScale, roundToStep), values that change outside a framework (createSource, createStore), a frame task that sleeps when nothing moves (createFrameTask), and the details a change or a commit reports.

pnpm add @audio-ui/core
import { getDataAttributes, createFrameTask, isReleased, observeVisibility, clamp, /* … */ } from "@audio-ui/core";
Adapters@audio-ui/react/envelope, @audio-ui/react/fader, @audio-ui/react/knob, @audio-ui/react/meter, @audio-ui/react/piano, @audio-ui/react/piano-roll, @audio-ui/react/plot, @audio-ui/react/sequencer, @audio-ui/react/timeline, @audio-ui/react/waveform, @audio-ui/react/xypad, @audio-ui/elements/knob, @audio-ui/elements/piano, @audio-ui/elements/piano-roll, @audio-ui/elements/plot, @audio-ui/elements/timeline, @audio-ui/elements/waveform
ExportKindWhat it is
getDataAttributesfunctionThe data attributes a part renders: data-<part> (or data-<component>), data-orientation, data-disabled, and data-<key> for every other option given, its value as text.
createFrameTaskfunctionRuns step on animation frames for as long as it returns true, and sleeps otherwise: a painter with nothing left to animate costs no frames until it is woken.
FrameTaskinterfaceWhat createFrameTask returns: wake it when something moves, flush it to step at once, stop it for good.
isReleasedfunctionA mouse or pen move with no button down: the press was released where this page could not see it, outside the window or over a menu, so the drag it belongs to is over.
observeVisibilityfunctionCalls onChange when element enters or leaves the viewport, so a painter can skip frames nobody sees.
PointtypeA point on two axes.
clampconstvalue kept within min and max.
clampFiniteconstClamp into min…max; a non-finite value (NaN from a 0/0, ±Infinity) falls back to min.
clampUnitconstvalue kept within 0 and 1.
degToRadconstAn angle in degrees, in radians.
PI_HALFconstA quarter turn in radians: π/2.
quantizeRoundconstvalue rounded to the nearest multiple of interval.
radToDegconstAn angle in radians, in degrees.
roundToStepfunctionSnap to step with min as the origin, without float noise (0.1 + 0.2).
TAUconstA full turn in radians: 2π.
isBlackKeyfunctionWhether pitch falls on a black key of a piano.
pitchClassNamefunction"C", "C#", "D"...
pitchNamefunction"C4" for middle C (MIDI 60), the naming tuners and score editors agree on.
ChangeEventDetailsinterfaceWhat a change reports: why it happened (reason), the event behind it, the element that triggered it, and cancel() to refuse the change.
CommitEventDetailsinterfaceWhat a commit reports once a gesture ends: why it happened (reason) and the event behind it.
createChangeEventDetailsfunctionThe details of a change for reason and event, with cancel() to refuse it and allowPropagation() to let the event go on.
createPairFormatterfunctionFormats two numbers as one string ("0.3, 0.4").
moveRangefunctionMoves one edge of origin by delta, or the whole range, without leaving the timeline.
normalizeRangefunctionOrders a range's edges and keeps them on the timeline.
RangeEdgetypeWhat a change moves: one edge, or the whole range with both.
RangeLimitsinterfaceWhat a range is kept within: the timeline's length and the shortest it may be.
RangeValuetypeA stretch of a timeline, [start, end] in its units.
LINEAR_SCALEconstEven steps: the right feel for levels, times and anything heard in differences.
LOGARITHMIC_SCALEconstEven ratios: the right feel for frequency, Q, ratios and times heard in proportions, where a linear sweep hides the useful range in its first few degrees.
ParameterScaleinterfaceHow a value maps onto a control's travel, and back.
ParameterScaleProptypeA scale as an option takes it: "linear", "log", or a scale of your own.
resolveScalefunctionThe scale an option names: "linear" and "log" as LINEAR_SCALE and LOGARITHMIC_SCALE, a scale of your own as it is.
createSourcefunctionCreates a source you push to yourself, from an audio callback, a WebSocket, a worker or a test: call set with each new reading, and whatever reads the source follows.
SourceinterfaceA value that changes outside React, in the shape useSyncExternalStore expects: subscribe registers a listener called on each change, and getSnapshot returns the current value.
WritableSourceinterfaceA source that also takes values: what createSource returns.
createStorefunctionA store holding initial: set tells every listener, unless the value is the same one.
StoreinterfaceA value that can be read and observed outside React, in the shape useSyncExternalStore expects.

Adapters

  • React: @audio-ui/react, the headless primitives.
  • Elements: @audio-ui/elements, the primitives as custom elements, for any framework.
  • Engine: @audio-ui/engine, the audio logic: devices, musical time, levels, MIDI input, scales and the clip player.
  • Registry: the styled components, devices, hooks and libraries you install and own.
Built by Ouest Labs, the source code is available on GitHub.
RSS