Lab

Frequency Shifter

A frequency shifter device: a shift or ring mode, the shift in hertz, the ring's frequency, a precision and a mix, a panel that draws what it does to a note, a Web Audio engine and tools for agents.

Audio UI

Moves every frequency of the sound by the same number of hertz. A pitch shift multiplies frequencies and keeps a note's harmonics in line; a frequency shift adds to them, so they stop lining up: a few hertz make a slow phasing, more make the sound metallic and strange. In Ring mode it multiplies the sound by a sine instead, leaving the sum and the difference of each frequency and the sine's, the bell of a ring modulator. It is a device: a state, a panel, an engine and tools, each its own file.

Installation

pnpm dlx shadcn@latest add @audio-ui/frequency-shifter

It installs the device's state, its engine and its panel to components/audio-ui/devices/frequency-shifter/. The demo above, which wires them to a loop, is @audio-ui/block-frequency-shifter.

Controls

Controls · 6

Panel

The panel draws what the device does to a 220 Hz note and its harmonics: the frequencies that go in, faint, and the ones that come out. frequencyShifterPartials(state) is what it draws.

import { FrequencyShifterPanel } from "@/components/audio-ui/devices/frequency-shifter/panel";
import { frequencyShifterDevice } from "@/components/audio-ui/devices/frequency-shifter/device";

const [state, setState] = useState(() => frequencyShifterDevice.defaults());

<FrequencyShifterPanel onValueChange={setState} value={state} />;

Engine

Create it, connect it and update it as for any device: see The engine.

The shifter runs on the audio thread: the frequency shifter of @audio/effect-freqshift, a Hilbert filter that turns the sound into its analytic signal and turns it like a wheel, and the ring modulator of @audio/effect-ringmod, in an AudioWorklet loaded from a blob (FREQUENCY_SHIFTER_WORKLET is its source), 128 frames at a time. Each mixes the clean sound in itself, the shifter's delayed as long as its filter, so the mix never combs. The worklet plays both modes, one output each, and the mode fades one in and the other out. A worklet cannot import, so the device carries both kernels as published (FREQUENCY_SHIFTER_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.

The shift delays the sound by half its filter's length, which is the latency of the device: 32 samples at Mid. The ring has none.

Built by Ouest Labs, the source code is available on GitHub.
RSS