Dynamics Display

dynamics-displayViewers

The one picture that says what a dynamics processor does: input level across, output level up, and wherever the line leaves the diagonal it is pulling on the signal. Computed rather than measured, so it is true the moment the page paints — the knee shaded as a width rather than implied by a number, the threshold marked, and a gate's hysteresis drawn as the band it is. The live gain-reduction meter beside it answers the other question: the curve is what the processor would do at any level, the meter is what it is doing to this one.

-60-60-48-48-36-36-24-24-12-1200INPUT dBOUTPUT dB
GR
--
-24.0 dB
4.0:1
+6.0 dB

The shaded strip is the knee — the soft in soft-knee, drawn as a width rather than implied by a number. The meter is fed a level sweeping through the threshold, read through this same curve.

Install

Copies the source into your project. Anything it depends on comes with it.

$ npx shadcn add @syntho-ui/dynamics-display

Pulls in

dynamics-mathuse-audio-sourcecontrol-theme

First time? Add the registry to your components.json once:

components.json
{
  "registries": {
    "@syntho-ui": "https://engine.syntho.app/r/{name}.json"
  }
}

Usage

Controlled or uncontrolled, whichever suits the surrounding state.

example.tsx
import { DynamicsDisplay } from "@/components/ui/dynamics-display"

<DynamicsDisplay
  mode="compressor"
  threshold={-24}
  ratio={4}
  knee={6}
  showMeter
  getReduction={(out) => {
    out[0] = compressorNode.reduction
    return true
  }}
/>

Props

PropTypeDefaultDescription
mode"compressor" | "gate""compressor"Which curve to draw. The gate reads range/hysteresis instead of ratio.
thresholdnumberWhere the curve bends, in dB. The one parameter both modes share.
rationumber4Compressor only: compression ratio, n:1. 1 is a no-op.
kneenumber0Total knee width in dB, centred on the threshold. 0 is a hard corner.
rangenumber-60Gate only: attenuation while shut, in dB. Negative.
hysteresisnumber0Gate only: how far below the threshold the gate holds open. Drawn as a band, with the other edge's curve ghosted behind the solid one.
phase"opening" | "closing""opening"Which edge of the hysteresis band the solid curve draws.
minDecibels / maxDecibelsnumber-60 / 0The dB window both axes cover.
probeLevelsnumber[]Mark these input levels on the curve with a dot.
showMeterbooleanfalseShow the live gain-reduction meter under the plot.
reductionnumberGain reduction in dB supplied directly — the driven form. Sign-agnostic, so a DynamicsCompressorNode's negative reading works as-is.
getReduction(target: Float32Array) => boolean | voidFill target[0] with the current reduction in dB each frame — the getData form the kit's other live displays take.
meterRangenumber40Reduction in dB that fills the meter.
colorstringOverride the curve's accent colour for this instance.
heightnumber220Plot height in pixels. The plot stays square inside it.

Interaction

  • Drag with pointer capture, so the gesture keeps tracking past the edge of the control.
  • Shift while dragging for a fine pass; release it mid-gesture and coarse tracking resumes.
  • Double-click resets to defaultValue.
  • Arrow keys step normally, Shift+arrow steps finely, PageUp/PageDown jump by ten, Home/End go to the extremes.
  • Proper slider and switch roles with live aria-valuetext, so a screen reader announces the formatted value rather than the raw number.
  • The scroll wheel adjusts the value while the pointer is over the control; stepped ranges move at least one declared step per notch by default.