Audio UI
Sweeps a resonant band through the sound. In Envelope mode the sound's own loudness moves it, the classic auto-wah: the harder a note is played, the higher the band. In Sweep mode a slow oscillator moves it. In Pedal mode it stays where it is set, a wah pedal held at one place, for a host to move by automation. It is a device: a state, a panel, an engine and tools, each its own file.
Installation
pnpm dlx shadcn@latest add @audio-ui/wah
It installs the device's state, its engine and its panel to components/audio-ui/devices/wah/. The demo above, which wires them to a loop, is @audio-ui/block-wah.
Controls
Controls · 14
Panel
The panel draws the band where it rests, and dashed where its travel ends: the top of the envelope's lift, or both ends of the sweep. The mode is picked in its title bar. wahCurve(state, bandHz) is a curve it draws, the band at a frequency mixed with the clean sound, and wahReach(state) where the band rests and how far it goes.
import { WahPanel } from "@/components/audio-ui/devices/wah/panel";
import { wahDevice } from "@/components/audio-ui/devices/wah/device";
const [state, setState] = useState(() => wahDevice.defaults());
<WahPanel onValueChange={setState} value={state} />;Engine
Create it, connect it and update it as for any device: see The engine.
The wah runs on the audio thread: the auto-wah of @audio/effect-autowah and the wah of @audio/effect-wah in an AudioWorklet loaded from a blob (WAH_WORKLET is its source), 128 frames at a time. Both are the same band-pass, a trapezoidal state-variable filter stable at any resonance, so every mode plays at the same level. The worklet plays all three modes, one output each, and the mode fades one in and the others out, so changing it does not click. A worklet cannot import, so the device carries both kernels as published (WAH_KERNELS, in its kernels.ts). Until it is ready, and in a context with no worklets, the sound passes clean: ready resolves once it is in the graph.