加载应用…
云澜 Clyune Clyune Component Gallery · 中文

Equalizer · How it works & code

5 Peak balance (RBJ biquad): Drag point changes frequency and gain, see how spectrum is "constructed".

Runtime logic

Visiting `/audio/eq`, DemoHost lazy-loads `demos/kits/kit-audio.js` (registry `mod: 'kit-audio'`) and calls `mount(host, { variant: 'eq' })`. mount resolves the variant to family `eq`; `withControls` builds the control panel (6 presets + sliders). `createCanvasStage` creates the `<canvas>` (HiDPI ≤ 2×, ResizeObserver) and the info panel. The family’s `build(S)` initialises state and returns the per-frame callback. Every `requestAnimationFrame`: read controls, advance a speed-scaled clock (dt ≤ 50 ms), run the frame callback; returned readouts go to the info panel. Pointer down/drag/move updates the interaction (drag handles, hover readouts); when untouched and auto-demo is on, the pointer follows a Lissajous path. With the top-right Sound switch on, sound plays through the shared AudioContext; off = muted. Changing parameters: colour/speed/size apply live; structural ones remount; leaving the page cancels rAF, removes listeners and frees resources.

Environment

Canvas 2D: 2D canvas drawing; requestAnimationFrame: Display-synced animation loop; ResizeObserver: Canvas follows container size; Pointer Events: Unified mouse/touch/pen events; devicePixelRatio: Crisp HiDPI rendering (capped at 2×) · react 18.3.1, react-router-dom 6.30.6, vite 5.4.21

Dependencies

react 18.3.1

Imported APIs

withControls — Wraps the demo in the shared control panel (presets, sliders, reset); hot-updates or remounts on change; paramsFromSpec — Turns the spec (colour/speed/size/count/extras) into control-panel parameter definitions; createCanvasStage — Shared Canvas 2D stage: canvas + info panel, HiDPI, one rAF loop, pointer state, idle auto-pointer; hueOf — Hue of a colour (0–360°); clamp — Clamps a value to a range; TAU — Constant 2π; fmt — Number formatting (fixed decimals); F — Formula block HTML; S.onDown — Pointer down; S.get — Reads current control values; S.onMove — Pointer move; S.onUp — Pointer up; S.clear — Clears with the background colour (translucent = trails); S.onFrame — Registers a per-frame callback; its return value feeds the info panel; ctx.beginPath() — Starts a new path; ctx.moveTo() — Moves the pen without drawing; ctx.lineTo() — Adds a straight line to a point; ctx.stroke() — Strokes the current path; ctx.closePath() — Closes the current sub-path; ctx.fill() — Fills the current path; ctx.arc() — Adds a circular arc (center, radius, start/end angle); ctx.arcTo() — Adds an arc using tangent lines; ctx.fillText() — Draws filled text; ctx.measureText() — Measures text width

Source code

frontend/src/demos/kits/kit-audio.js: FAM.eq (L411-L458)

Code walkthrough

L412-412: Canvas cursor style. L413-413: Control definitions (colour/speed/size/count/extras): Curve color, Maximum gain dB, Number of bands, Q value (higher = narrower), Auto-oscillation amplitude, Show spectrum. L414-414: Preset buttons: name → parameter overrides (6). L415-423: Info-panel content: live rows(v), formula, notes, params, steps. L424-457: Init function: sets up state and returns the per-frame callback: registers pointer handlers `S.onDown`, `S.onMove`, `S.onUp`; draws with Canvas 2D `beginPath`, `moveTo`, `lineTo`, `stroke`, `closePath`, `fill` …; produces/reads sound via `A.voices`; math via `Math.sin`, `Math.hypot`, `Math.round`; returns readouts `fs`, `ml`, `mr`, `mt`, `mb`, `w`, `h` … to the info panel.

Principles

Each frequency is a "peak filter": A = 10 ^ (G) / 40),ω₀ = 2π f₀ / fs,α = sin ω₀ / (2Q) Total Response dB) = Σ Frequency response dB Directly Plus) Processing spectral = original spectrum + total Response Equalizer (EQ)Exactly"A volume spin button for the frequency segment":把低音、中音、高音分别调大或调小。每个圆点是一个频段, Left and right drag = Re-centre frequency, up and down = Change gain (Up, down. Yellow curve is folded from all frequency bands Frequency Response :Curve in 0 dB 以上的频率会被放大。底下暗色是原始频谱,亮色是处理后的频谱,你能看到被"Lift up"或"It's on the top"The area. Q Value determines how wide each drum pack is: Q Large = It's narrow and sharp, it only affects a small frequency.

Open the interactive demo · GitHub