Custom Sounds

Create custom sound packs and override individual sound roles in sensory-ui.

sensory-ui ships with 9 built-in sound packs, but you can create your own or override individual roles with custom audio.

Override a Single Role

The simplest way to use custom audio is via config.overrides in sensory.config.js:

// sensory.config.js
module.exports = {
  overrides: {
    "interaction.tap": "/sounds/custom/my-click.mp3",
    "hero.complete": "/sounds/custom/fanfare.mp3",
  },
};

Overrides can point to:

  • URL paths: files in your public/ directory (e.g., /sounds/custom/click.mp3)
  • Base64 data URIs: inline audio (e.g., data:audio/mp3;base64,//uQx...)

Custom overrides bypass the synthesizer entirely. The engine fetches them by URL and decodes them via decodeAudioData.

Audio File Requirements

When providing custom audio files:

RequirementSpec
Format.mp3 (primary), .ogg (optional fallback)
Sample rate44.1 kHz or 48 kHz
Bit depth16-bit
ChannelsMono preferred (stereo allowed)
Peak normalization−1.0 dBTP
Leading silenceNone: trimmed to first transient
Trailing silence≤ 20 ms
Per-file size≤ 15 KB recommended

Create a Custom Instrument

For deeper customization, you can create a new instrument and generate a full sound pack:

// sounds/core/instruments.ts
import type { InstrumentConfig } from "./instruments";

const MY_INSTRUMENT: InstrumentConfig = {
  filterFreq: 4000,
  q: 5,
  oscType: "triangle",
  decayMult: 1.0,
  gainMult: 0.85,
  pitchMult: 1.1,
  effects: [
    { type: "reverb", options: { duration: 1.0, decay: 2.0, mix: 0.2 } },
  ],
};

Then generate the pack:

import { generateSoundPack } from "./core/factory";

export const myPack = generateSoundPack(MY_INSTRUMENT);
// myPack covers all 17 roles

Modify an Existing Pack

Create a variant by adjusting key parameters:

import { INSTRUMENTS } from "./core/instruments";
import { generateSoundPack } from "./core/factory";

const myInstrument = {
  ...INSTRUMENTS.glass,
  gainMult: 0.6, // Quieter
  pitchMult: 2.0, // Higher pitched
  effects: [
    { type: "reverb", options: { duration: 2.0, mix: 0.4 } },
  ],
};

export const myPack = generateSoundPack(myInstrument);

Instrument Properties

interface InstrumentConfig {
  filterFreq: number; // Filter cutoff frequency (1500-6000 Hz)
  q: number; // Filter resonance (1-12)
  oscType: OscillatorType; // "sine" | "square" | "sawtooth" | "triangle"
  decayMult: number; // Decay time multiplier (0.5-1.5)
  gainMult: number; // Volume multiplier (0.4-1.0)
  pitchMult: number; // Pitch multiplier (0.7-1.8)
  effects?: EffectDefinition[]; // Optional effects chain
}

Available Effects

EffectOptionsDescription
reverb{ duration, decay, mix }Algorithmic reverb via noise-buffer impulse response
delay{ time, feedback, filterFreq, mix }Feedback delay with low-pass filter
chorus{ rate, depth, detune, mix }Delay-based chorus with LFO modulation
distortion{ amount, filterFreq, mix }Waveshaper saturation with post-filter

All effects support a mix parameter (0–1) for wet/dry balance.

Pack Effects Mapping

PackEffectsCharacter
aeroreverb (long tail, 2s)Airy, ethereal: needs space
glassreverb (1.5s) + chorusCrystalline shimmer
retrochorus + delayAnalog warmth
industrialdistortionMetallic grit
organicreverb (short room, 0.4s)Natural warmth
softreverb (medium warm, 0.8s)Gentle presence
arcade(dry)Authentic chiptune
minimal(dry)Pure tones
crisp(dry)Sharp transients

Which path should you take?

SituationPathEffort
One sound feels wrong (e.g. brand click)Override that role with an MP3Minutes
A pack is close but too loud, low, or wetSpread an existing instrument and tweak 1–2 knobsAn hour
Nothing fits your product's voiceDesign a new instrument + generateSoundPackA day
A moment needs real recorded audioOverride with a file and keep synthesis for the restMinutes

Start from the pack dossiers to find the closest character, and check Designing with Sound before adding new sounds. Most products need fewer custom sounds than they think.

Sound synthesis patterns adapted from Generating Sounds with AI. Effects system inspired by @web-kits/audio by Raphael Salaja.