Delay Tap Display
delay-tap-displayViewersA delay has no transfer curve — what it does is put the same sound somewhere else in time, quieter, again and again. So the picture is the train itself: a muted reference pip for the dry hit, then one pip per repeat at the moment it arrives and the height it arrives with, fading as well as shrinking so a tail five repeats deep is still readable. Two knobs that read as abstract numbers become a rhythm and a decay you can count. Set lanes to 2 and it becomes the ping-pong view: left grows up from the midline, right grows down, and the bounce reads as a zigzag without one being drawn. Which side the first repeat lands on is not a display choice — the shipped cross-coupled graph seeds only its left delay line, and the maths beside this component derives the alternation from that wiring. Supply a tempo and the beat grid appears behind the train, which is how you see repeats landing on the beat, or missing it. Computed rather than measured, so it is right before a single sample plays.
11 audible repeats above -60 dB, a 2.89 s tail. Height is level and so is opacity: by the fifth repeat a pip is two units tall, and one cue is not enough to read a tail by. The hollow pip at zero is the dry hit, whose own height is 1 - mix, because the stage crossfades rather than adding a send.
Install
Copies the source into your project. Anything it depends on comes with it.
$ npx shadcn add @syntho-ui/delay-tap-displayPulls in
First time? Add the registry to your components.json once:
{
"registries": {
"@syntho-ui": "https://engine.syntho.app/r/{name}.json"
}
}Usage
Controlled or uncontrolled, whichever suits the surrounding state.
import { DelayTapDisplay } from "@/components/ui/delay-tap-display"
// A mono feedback delay at a quarter second.
<DelayTapDisplay time={0.25} feedback={0.55} wet={0.4} />
// A ping-pong: the same train, alternating sides from the left.
<DelayTapDisplay time={0.25} feedback={0.4} wet={0.5} lanes={2} />
// With the beats drawn behind it, to see what the repeats are landing on.
<DelayTapDisplay time={0.25} feedback={0.5} wet={0.4} tempo={120} division={0.5} />Props
| Prop | Type | Default | Description |
|---|---|---|---|
| time | number | — | Seconds between repeats. The pips sit at 1x, 2x, 3x this. |
| feedback | number | — | Loop gain per repeat. Clamped to the audio path's own 0.95 ceiling on read, so a display fed 1.2 cannot draw a train that grows. |
| wet | number | 1 | Wet/dry mix. Sets the repeats' height and the dry pip's, which is 1 - mix: the shipped stages crossfade rather than adding a send, so the dry hit shrinks as the repeats come up. |
| lanes | 1 | 2 | 1 | 1 for a mono train on a baseline, 2 for a ping-pong mirrored about the midline. Only the drawing changes: a cross-coupled pair's levels are the same feedback^(n-1) a single line produces. |
| firstLane | 0 | 1 | 0 | Which side the first repeat lands on. The shipped graph seeds its left line, so left is the default and nothing in the repo passes anything else. |
| span | number | — | Seconds the axis covers. Defaults to a window that fits the train with half a repeat of headroom. A fixed span also bounds the train — you get the pips that fit, not pips off the edge. |
| floor / maxTaps | number | 1e-3 / 64 | Where drawing stops: an audibility cutoff at -60 dB and a hard cap. When the cap is what stopped it, the plot says so rather than implying the tail ended. |
| tempo | number | null | — | Beats per minute for the sync grid. Omit for no grid, which is what every shipped delay stage gets — none of them has a tempo sync. The grid syncs nothing; it draws where the beats are so you can see whether the repeats agree. |
| division / beatsPerBar | number | 1 / 4 | Sync-grid spacing in beats (1 is a quarter, 0.5 an eighth) and the bar length its labels count in. |
| showDry | boolean | true | Draw the dry hit at t = 0. In a two-lane view it appears in both lanes: the dry path is not in the delay loop, so it keeps the source's own centred image. |
| color | string | — | Override the accent colour for this instance. |
| height | number | 140 | Plot height in pixels. |
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
sliderandswitchroles with livearia-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.