LFO Visualizer

lfo-visualizerVisualizers

Purely parameter-driven: give it a shape, a rate and a range and it draws what the modulator is doing, with a cursor riding the current phase. Nothing is measured off an analyser — an LFO usually runs well below 20 Hz, where reading it back is both awkward and pointless when the shape is known in closed form. The cursor advances on its own clock, or you can pass a phase from a real modulator and the component becomes a controlled display of it. The waveform maths is an exported pure function with tests pinning every corner and discontinuity.

Drawn from the waveform's closed form, not measured — the cursor rides its own clock at the shown rate.

Install

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

$ npx shadcn add @syntho-ui/lfo-visualizer

Pulls in

control-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 { LFOVisualizer } from "@/components/ui/lfo-visualizer"

<LFOVisualizer type="triangle" frequency={2.5} min={200} max={2000} />

Props

PropTypeDefaultDescription
frequencynumber4Rate in Hz. Drives the cursor's clock when phase is not supplied.
type"sine" | "square" | "sawtooth" | "triangle""sine"Waveform shape.
min / maxnumber-1 / 1The modulation range, shown on the readout.
phasenumberCurrent phase in turns (0..1) from a real modulator. Supplying it stops the internal clock.
cyclesnumber2How many cycles fit across the display.
showGridbooleantrueDraw the dotted grid and the dashed centre line.
showReadoutbooleantrueShow the rate and the current value as text on the display.
colorstringTrace colour. Defaults to the --uikit-accent token.
lineWidthnumber2Trace thickness in CSS pixels.
heightnumber90Display height in pixels; width defaults to 100%.
pausedbooleanfalseStop the animation and hold the current frame.

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.