API reference

Public API reference.

Copy-paste signatures, option tables, return values, and examples for the React package and browser-safe core helpers.

Reference

React package exports.

These APIs are imported from @webaudio-kit/react. The hooks must run under AudioProvider.

@webaudio-kit/react

AudioProvider

Wraps React UI that needs playback. It creates AudioContext lazily, routes playback through masterGain -> analyser -> destination, and starts with a safe master gain.

Signature
function AudioProvider(props: AudioProviderProps): JSX.Element;

type AudioProviderProps = {
  children: ReactNode;
  initialGain?: number;
};
Provider shell
import { AudioProvider } from "@webaudio-kit/react";

export function App() {
  return (
    <AudioProvider initialGain={0.2}>
      <AudioControls />
    </AudioProvider>
  );
}
NameTypeDefaultNotes
AudioProviderProps.childrenReactNoden/aRequired React subtree that can call webaudio-kit hooks.
AudioProviderProps.initialGainnumber0.2Initial master gain. Non-finite values fall back to the package default and negative values clamp to 0.

Returns

NameTypeDefaultNotes
audioContextAudioContext | nulln/aNull until the first user-initiated playback creates audio.
masterGainGainNode | nulln/aShared gain node for all playback created by provider hooks.
analyserAnalyserNode | nulln/aShared analyser node for waveform and spectrum UI.
stateAudioContextState | "idle"n/aIdle before creation, then mirrors the current AudioContext state.
@webaudio-kit/react

useAudioContext

Reads the provider runtime state and low-level controls. Use this when you need context state, analyser access, or custom UI around provider gain.

Signature
function useAudioContext(): AudioProviderValue;

type AudioProviderValue = {
  audioContext: AudioContext | null;
  masterGain: GainNode | null;
  analyser: AnalyserNode | null;
  state: AudioContextState | "idle";
  gain: number;
  ensureAudioContext(): Promise<AudioRuntime>;
  setGain(gain: number): Promise<void>;
  stopAll(): void;
};
Context state and panic control
import { useAudioContext } from "@webaudio-kit/react";

function AudioStateControls() {
  const audio = useAudioContext();

  return (
    <>
      <span>{audio.state}</span>
      <button onClick={() => audio.stopAll()}>Stop all</button>
    </>
  );
}
NameTypeDefaultNotes
stateAudioContextState | "idle"n/aDisplay whether audio is idle, running, suspended, closed, or interrupted by the browser.
ensureAudioContext()Promise<AudioRuntime>n/aCreates and resumes AudioContext on demand. Call it only from user-initiated handlers or higher-level hooks.
setGain(gain)Promise<void>n/aUpdates provider master gain and clamps invalid input to safe values.
stopAll()voidn/aStops active and scheduled hook playback handles. Use this for panic buttons or alert acknowledgement; it is stronger than muting gain.
@webaudio-kit/react

useAudioUnlock

Returns a small UX primitive for explicit browser audio enablement from a button, tap target, or keyboard action.

Signature
function useAudioUnlock(): AudioUnlockControls;

type AudioUnlockControls = {
  unlock(): Promise<AudioRuntime>;
  status: "idle" | "unlocking" | "suspended" | "running" | "closed" | "error";
  state: AudioContextState | "idle";
  isUnlocked: boolean;
  isUnlocking: boolean;
  error: Error | null;
};
Enable Audio button
import { useAudioUnlock } from "@webaudio-kit/react";

function EnableAudioButton() {
  const audio = useAudioUnlock();

  return (
    <>
      <button disabled={audio.isUnlocked} onClick={() => void audio.unlock()}>
        {audio.isUnlocked ? "Audio enabled" : "Enable Audio"}
      </button>
      <span>{audio.status}</span>
      {audio.error ? <span>unlock failed</span> : null}
    </>
  );
}
NameTypeDefaultNotes
unlock()Promise<AudioRuntime>n/aCreates/resumes the provider runtime. Call it from a click, tap, or keyboard handler because browser autoplay policy still requires a user gesture.
status"idle" | "unlocking" | "suspended" | "running" | "closed" | "error"n/aDisplay label for the current unlock UI. Use suspended for blocked browser audio and error for a failed unlock attempt.
isUnlockedbooleann/aTrue when the provider state is running and audio can be used for subsequent cues.
errorError | nulln/aStores the last failed unlock error so apps can show retry UI without losing the provider state label.
@webaudio-kit/react

useAudioEngine

Returns provider-scoped wrappers around core playback helpers for custom or layered React sounds.

Signature
function useAudioEngine(): AudioEngineControls;

type AudioEngineControls = AudioProviderValue & {
  playTone(options): Promise<PlaybackHandle>;
  playFrequencySweep(options): Promise<PlaybackHandle>;
  playNoise(options): Promise<PlaybackHandle>;
  withAudioRuntime<T>(
    callback: (runtime: AudioRuntime) => T | Promise<T>,
  ): Promise<T>;
};
Provider-scoped layered cue
import { useAudioEngine } from "@webaudio-kit/react";

function LayeredAlertButton() {
  const engine = useAudioEngine();

  async function playLayeredAlert() {
    await engine.playTone({
      frequency: 880,
      durationMs: 160,
      gain: 0.1,
      type: "square",
    });
    await engine.playNoise({
      durationMs: 120,
      gain: 0.025,
      type: "pink",
    });
  }

  return (
    <>
      <button onClick={() => void playLayeredAlert()}>Play alert</button>
      <button onClick={() => engine.stopAll()}>Stop all</button>
    </>
  );
}
NameTypeDefaultNotes
playTone(options)Promise<PlaybackHandle>n/aEnsures/resumes the provider runtime and routes tone playback through runtime.masterGain.
playFrequencySweep(options)Promise<PlaybackHandle>n/aRuns provider-scoped frequency sweeps without manual audioContext or masterGain plumbing.
playNoise(options)Promise<PlaybackHandle>n/aRuns provider-scoped white, pink, or brown noise bursts through the analyser graph.
withAudioRuntime(callback)Promise<T>n/aProvides the non-null provider runtime for custom Web Audio code that needs runtime.masterGain.
@webaudio-kit/react

useTone

Creates stable controls for one oscillator tone. Every play call creates fresh oscillator, gain, and pan nodes and cleans them up when playback ends.

Signature
function useTone(): {
  play(options: ToneOptions): Promise<void>;
  stop(): void;
  isPlaying: boolean;
};

function useTone(options: ToneOptions): {
  play(overrides?: Partial<ToneOptions>): Promise<void>;
  stop(): void;
  isPlaying: boolean;
};
Patterned tone
import { useTone } from "@webaudio-kit/react";

function AlertCueButton() {
  const tone = useTone();

  return (
    <>
      <button onClick={() => void tone.play({
        frequency: 880,
        durationMs: 120,
        gain: 0.12,
        type: "square",
        envelope: { attackMs: 8, releaseMs: 45 },
        filter: { frequency: 1800, q: 0.7 },
        pattern: { repeat: 3, gapMs: 90 },
        voices: { count: 2, spreadCents: 10 },
      })}>
        Play alert cue
      </button>
      <button onClick={tone.stop}>Stop</button>
    </>
  );
}
NameTypeDefaultNotes
ToneOptions.frequencynumbern/aTone frequency in Hz. Values are clamped by core playback to 20..20000 by default.
ToneOptions.gainnumber0.2Per-play gain before the provider master gain.
ToneOptions.typeOscillatorType"sine"Any browser oscillator type: "sine", "square", "sawtooth", or "triangle".
ToneOptions.pannumber0Stereo pan from -1 left to 1 right when StereoPannerNode is available.
ToneOptions.durationMsnumbern/aOptional duration. Omit it for manual stop control.
ToneOptions.detuneCentsnumber0Oscillator detune in cents.
ToneOptions.envelope{ attackMs?: number; decayMs?: number; sustain?: number; releaseMs?: number }n/aOptional gain envelope. Durations are milliseconds; sustain is a 0..1 gain multiplier.
ToneOptions.filter{ frequency: number; q?: number; type?: BiquadFilterType }n/aOptional filter node. Defaults to lowpass when set; frequency is clamped to the playable range.
ToneOptions.pattern{ repeat?: number; gapMs?: number }n/aOptional repeat pattern. Repeated tones require durationMs and share one stop handle.
ToneOptions.voices{ count?: number; spreadCents?: number }n/aOptional 1..8 oscillator layering. Requested gain is divided across voices.

Returns

NameTypeDefaultNotes
play(overrides)Promise<void>n/aResumes provider audio, stops any previous tone from this hook, then starts the next tone.
stop()voidn/aStops and disconnects the current tone for this hook.
isPlayingbooleann/aTrue after play starts and false after stop or scheduled duration completion.
@webaudio-kit/react

useFrequencySweep

Creates stable controls for a scheduled oscillator ramp between two clamped frequencies.

Signature
function useFrequencySweep(): {
  play(options: FrequencySweepOptions): Promise<void>;
  stop(): void;
  isPlaying: boolean;
};

function useFrequencySweep(options: FrequencySweepOptions): {
  play(overrides?: Partial<FrequencySweepOptions>): Promise<void>;
  stop(): void;
  isPlaying: boolean;
};
Sweep button
import { useFrequencySweep } from "@webaudio-kit/react";

function SweepButton() {
  const sweep = useFrequencySweep({
    from: 250,
    to: 8000,
    durationMs: 2400,
    gain: 0.12,
  });

  return <button onClick={() => void sweep.play()}>Run sweep</button>;
}
NameTypeDefaultNotes
FrequencySweepOptions.fromnumbern/aStart frequency in Hz. Core playback clamps it to the playable range.
FrequencySweepOptions.tonumbern/aEnd frequency in Hz. Core playback clamps it to the playable range.
FrequencySweepOptions.durationMsnumbern/aRequired positive sweep duration. Invalid values throw before scheduling.
FrequencySweepOptions.gainnumber0.2Per-sweep gain before the provider master gain.
FrequencySweepOptions.typeOscillatorType"sine"Oscillator waveform used throughout the sweep.
FrequencySweepOptions.pannumber0Stereo pan from -1 left to 1 right when supported by the browser.
FrequencySweepOptions.detuneCentsnumber0Oscillator detune in cents for sweep voices.
FrequencySweepOptions.envelope{ attackMs?: number; decayMs?: number; sustain?: number; releaseMs?: number }n/aOptional gain envelope for softer sweep starts and stops.
FrequencySweepOptions.filter{ frequency: number; q?: number; type?: BiquadFilterType }n/aOptional filter node for taming bright sweep waveforms.
FrequencySweepOptions.pattern{ repeat?: number; gapMs?: number }n/aOptional repeat pattern for chirps or repeated sweeps without app-owned timers.
FrequencySweepOptions.voices{ count?: number; spreadCents?: number }n/aOptional 1..8 oscillator layering for fuller sweep cues.

Returns

NameTypeDefaultNotes
play(overrides)Promise<void>n/aResumes provider audio and schedules a linear frequency ramp.
stop()voidn/aStops and disconnects the active sweep.
isPlayingbooleann/aTrue while the scheduled sweep is active.
@webaudio-kit/react

useNoise

Creates stable controls for short generated white, pink, or brown noise buffers.

Signature
function useNoise(): {
  play(options: NoiseOptions): Promise<void>;
  stop(): void;
  isPlaying: boolean;
};

function useNoise(options: NoiseOptions): {
  play(overrides?: Partial<NoiseOptions>): Promise<void>;
  stop(): void;
  isPlaying: boolean;
};
Noise burst
import { useNoise } from "@webaudio-kit/react";

function NoiseButton() {
  const noise = useNoise({
    type: "pink",
    durationMs: 800,
    gain: 0.08,
  });

  return <button onClick={() => void noise.play()}>Play pink noise</button>;
}
NameTypeDefaultNotes
NoiseOptions.durationMsnumbern/aRequired positive duration for the generated buffer.
NoiseOptions.gainnumber0.2Per-burst gain before the provider master gain. Keep this low.
NoiseOptions.pannumber0Stereo pan from -1 left to 1 right when supported by the browser.
NoiseOptions.type"white" | "pink" | "brown""white"Noise color used when generating the buffer.
NoiseOptions.envelope{ attackMs?: number; decayMs?: number; sustain?: number; releaseMs?: number }n/aOptional gain envelope for noise bursts that should fade in or out.
NoiseOptions.filter{ frequency: number; q?: number; type?: BiquadFilterType }n/aOptional filter node for shaping white, pink, or brown noise.
NoiseOptions.pattern{ repeat?: number; gapMs?: number }n/aOptional repeat pattern for repeated bursts without setTimeout wrappers.

Returns

NameTypeDefaultNotes
play(overrides)Promise<void>n/aResumes provider audio, generates a fresh buffer, and starts it.
stop()voidn/aStops and disconnects the active noise source.
isPlayingbooleann/aTrue while the burst is active.
@webaudio-kit/react

useVolume

Reads and updates the provider master gain. Use this for one shared volume control across tone, sweep, and noise playback.

Signature
function useVolume(): {
  gain: number;
  setGain(gain: number): Promise<void>;
};
Master volume
import { useVolume } from "@webaudio-kit/react";

function VolumeSlider() {
  const volume = useVolume();

  return (
    <input
      max={0.5}
      min={0}
      onChange={(event) => void volume.setGain(event.currentTarget.valueAsNumber)}
      step={0.01}
      type="range"
      value={volume.gain}
    />
  );
}
NameTypeDefaultNotes
gainnumbern/aCurrent provider master gain.
setGain(gain)Promise<void>n/aNormalizes invalid input and updates masterGain when audio already exists.
@webaudio-kit/react

useVolumeControl

Builds a controlled volume slider from provider gain, safe bounds, and optional persisted browser preference storage.

Signature
function useVolumeControl(options?: VolumeControlOptions): VolumeControlControls;

type VolumeControlOptions = {
  defaultGain?: number;
  label?: string;
  maxGain?: number;
  minGain?: number;
  step?: number;
  storageKey?: string;
};

type VolumeControlControls = {
  gain: number;
  db: number;
  inputProps: VolumeControlInputProps;
  resetGain(): Promise<void>;
  setGain(gain: number): Promise<void>;
};
Controlled Volume Slider
import { useVolumeControl } from "@webaudio-kit/react";

function ControlledVolumeSlider() {
  const volume = useVolumeControl({
    label: "Master volume",
    maxGain: 0.5,
    storageKey: "app-master-gain",
  });

  return (
    <>
      <input {...volume.inputProps} />
      <span>{volume.gain.toFixed(2)}</span>
      <button onClick={() => void volume.resetGain()}>Reset volume</button>
    </>
  );
}
NameTypeDefaultNotes
inputPropsrange input propsn/aSpread onto an input to keep provider gain as the controlled value without duplicate React state.
storageKeystring | undefinedn/aOptional localStorage key for persisting a browser preference. Omit it when volume should reset each session.
minGain / maxGain / stepnumbern/aSafe bounds for the controlled slider. Defaults are 0, 1, and 0.01.
resetGain()Promise<void>n/aRemoves the stored preference and restores defaultGain through provider gain.
@webaudio-kit/react

useAnalyser

Returns the provider analyser node so custom visualizers can read time-domain or frequency-domain data.

Signature
function useAnalyser(): AnalyserNode | null;
Custom analyser read
import { useAnalyser } from "@webaudio-kit/react";

function Meter() {
  const analyser = useAnalyser();

  if (!analyser) {
    return <span>Idle</span>;
  }

  return <span>{analyser.fftSize} point analyser</span>;
}
NameTypeDefaultNotes
return valueAnalyserNode | nulln/aNull before the provider creates AudioContext. Non-null after playback initializes the graph.
@webaudio-kit/react

WaveformCanvas

Draws analyser time-domain data into a canvas and renders an idle center line before audio exists. Keep width/height as the backing buffer and use style or className for responsive CSS sizing.

Signature
function WaveformCanvas(props: WaveformCanvasProps): JSX.Element;

type WaveformCanvasProps = Omit<
  CanvasHTMLAttributes<HTMLCanvasElement>,
  "children"
> & {
  backgroundColor?: string;
  idleStrokeColor?: string;
  lineWidth?: number;
  strokeColor?: string;
};
Waveform
import { WaveformCanvas } from "@webaudio-kit/react";

function Signal() {
  return (
    <WaveformCanvas
      aria-label="Waveform analyser"
      height={180}
      idleStrokeColor="#394135"
      lineWidth={2}
      strokeColor="#c8ea3a"
      style={{ width: "100%", height: 140 }}
      width={720}
    />
  );
}
NameTypeDefaultNotes
WaveformCanvasProps.strokeColorstring"#c8ea3a"Stroke color used when analyser data is available.
WaveformCanvasProps.idleStrokeColorstringn/aOptional separate stroke color for the idle center line.
WaveformCanvasProps.backgroundColorstring"#10110f"Canvas fill color.
WaveformCanvasProps.lineWidthnumber2Canvas stroke width.
@webaudio-kit/react

SpectrumCanvas

Draws analyser frequency-domain data into compact bars and renders low idle bars before audio exists. Keep width/height as the backing buffer and use style or className for responsive CSS sizing.

Signature
function SpectrumCanvas(props: SpectrumCanvasProps): JSX.Element;

type SpectrumCanvasProps = Omit<
  CanvasHTMLAttributes<HTMLCanvasElement>,
  "children"
> & {
  backgroundColor?: string;
  barColor?: string;
  barCount?: number;
  barGap?: number;
  idleBarColor?: string;
  minBarHeight?: number;
};
Spectrum
import { SpectrumCanvas } from "@webaudio-kit/react";

function Spectrum() {
  return (
    <SpectrumCanvas
      aria-label="Spectrum analyser"
      backgroundColor="#10110f"
      barColor="#8ed8ff"
      barCount={48}
      barGap={2}
      height={140}
      idleBarColor="#394135"
      minBarHeight={2}
      style={{ width: "100%", height: 120 }}
      width={720}
    />
  );
}
NameTypeDefaultNotes
SpectrumCanvasProps.barColorstring"#c8ea3a"Bar color used when analyser data is available.
SpectrumCanvasProps.idleBarColorstringn/aOptional separate bar color for the idle state.
SpectrumCanvasProps.backgroundColorstring"#10110f"Canvas fill color.
SpectrumCanvasProps.barCountnumber48Number of bars to draw from the analyser bins.
SpectrumCanvasProps.barGapnumber2Gap in canvas pixels between bars.
SpectrumCanvasProps.minBarHeightnumber2Minimum rendered bar height so idle state stays visible.
@webaudio-kit/react

useAudioTestMode

Runs a short low-gain sequence that checks tone output, stereo pan, sweep scheduling, noise generation, and analyser routing.

Signature
function useAudioTestMode(options?: AudioTestModeOptions): AudioTestModeControls;

type AudioTestModeOptions = {
  gapMs?: number;
  steps?: AudioTestModeStep[];
};

type AudioTestModeControls = {
  currentStep: AudioTestModeStep | null;
  currentStepIndex: number;
  isRunning: boolean;
  previewStep: AudioTestModeStep | null;
  previewStepIndex: number;
  run(): Promise<void>;
  stop(): void;
  steps: AudioTestModeStep[];
};
Audio test mode
import { useAudioTestMode } from "@webaudio-kit/react";

function AudioSelfCheck() {
  const testMode = useAudioTestMode();

  return (
    <>
      <button onClick={() => void testMode.run()}>Run test</button>
      <button onClick={testMode.stop}>Stop</button>
      <span>{testMode.previewStep?.label ?? "Idle"}</span>
    </>
  );
}
NameTypeDefaultNotes
AudioTestModeOptions.gapMsnumber120Delay between steps.
AudioTestModeOptions.stepsAudioTestModeStep[]n/aCustom sequence. Falls back to the package default steps when omitted or empty.
AudioTestModeControls.currentStepAudioTestModeStep | nulln/aThe active step while the sequence is running. currentStep remains null before run.
AudioTestModeControls.previewStepAudioTestModeStep | nulln/apreviewStep points at the first planned step before run, follows the active step while running, and resets to the first planned step after stop.
AudioTestModeControls.previewStepIndexnumbern/aIndex for previewStep. Use it to highlight the initial or active planned step without guessing.
AudioTestModeControls.run()Promise<void>n/aStarts the full sequence from a user action.
@webaudio-kit/react

AudioProvider state machine

useAudioContext().state can return idle, suspended, running, or closed. idle is a webaudio-kit value, not a native browser AudioContextState.

NameTypeDefaultNotes
initial render"idle"n/aNo AudioContext, master gain, or analyser has been created.
first user gesture"suspended" | "running"n/aplay(), setGain(), or ensureAudioContext() creates the graph and asks the browser to resume audio.
resume allowed"running"n/aThe provider mirrors the native AudioContext state after browser autoplay policy allows playback.
stopAll()"running" | "suspended"n/aStops active and scheduled hook playback, but does not close the shared AudioContext.
provider unmount"closed"n/aThe provider closes the context when the browser allows close().
audio unavailable"idle"n/aIf AudioContext creation fails, hooks reject with the browser error and state remains usable for UI.
AudioStateBadge
import { useAudioContext } from "@webaudio-kit/react";

function AudioStateBadge() {
  const audio = useAudioContext();
  const label =
    audio.state === "idle"
      ? "Idle: audio has not been created yet"
      : `AudioContext: ${audio.state}`;

  return <span aria-label={label}>{audio.state}</span>;
}

Keep first playback directly inside click, tap, or keyboard handlers. Browsers may leave the context suspended until a gesture satisfies autoplay policy.

@webaudio-kit/core

Core helpers

These exports come from @webaudio-kit/core and are also re-exported by the React package for convenience.

NameTypeDefaultNotes
PlaybackFilter{ frequency: number; q?: number; type?: BiquadFilterType }n/aOptional filter routing shared by tone, sweep, and noise options. Defaults to lowpass when set.
PlaybackVoices{ count?: number; spreadCents?: number }n/aOptional oscillator voice layering for tone and sweep options. count is bounded to 1..8.
PlaybackEnvelope{ attackMs?: number; decayMs?: number; sustain?: number; releaseMs?: number }n/aOptional gain envelope shared by tone, sweep, and noise options. Durations use milliseconds.
dbToGain(db)(db: number) => numbern/aReturns 10 ** (db / 20). Use it when UI stores volume in decibels but Web Audio needs gain.
gainToDb(gain)(gain: number) => numbern/aReturns 20 * log10(gain). Zero, negative, and non-finite values return -Infinity.
clampFrequency(value, min, max)(value: number, min?: number, max?: number) => number20..20000Clamps a frequency into the configured range and normalizes swapped min and max values.
midiToFrequency(midiNote, concertA)(midiNote: number, concertA?: number) => numberA4 = 440Converts a MIDI note number to Hz. Invalid input returns NaN.
frequencyToMidi(frequency, concertA)(frequency: number, concertA?: number) => numberA4 = 440Converts Hz to a fractional MIDI note number. Invalid input returns NaN.
frequencyToNoteName(frequency, options)(frequency: number, options?: NoteNameOptions) => stringn/aReturns labels such as "A4" or "A4 +3c". Invalid input returns "unknown".
PlaybackPattern{ repeat?: number; gapMs?: number }n/aOptional repeat schedule shared by tone, sweep, and noise options. repeat is total plays; gapMs is silence between plays.
playTone(context, options, destination)(AudioContext, ToneOptions, AudioNode?) => PlaybackHandlen/aCreates oscillator, gain, optional stereo panner, starts playback, and returns stop cleanup for one shot or the full pattern.
playFrequencySweep(context, options, destination)(AudioContext, FrequencySweepOptions, AudioNode?) => PlaybackHandlen/aCreates an oscillator and schedules a linear frequency ramp between clamped endpoints.
playNoise(context, options, destination)(AudioContext, NoiseOptions, AudioNode?) => PlaybackHandlen/aGenerates a white, pink, or brown noise buffer for the requested duration.
Core helper usage
import {
  clampFrequency,
  dbToGain,
  frequencyToNoteName,
  gainToDb,
} from "@webaudio-kit/core";

const frequency = clampFrequency(inputFrequency);
const gain = dbToGain(-14);
const db = gainToDb(0.2);
const note = frequencyToNoteName(440, { includeCents: true });