# UI Sound Design

> Programmatic UI sound design using Web Audio API and Tone.js. Use when creating click sounds, notification chimes, toggle feedback, hover sounds, success/error audio, whoosh effects, or building a sound library for UI interactions. Provides an iterative describe-generate-listen-refine workflow with audio engineering knowledge translated into plain English. Use when this capability is needed.

- Skill: `tomevault-io/ui-sound-design` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/ui-sound-design`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/ui-sound-design/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/ui-sound-design

---


```
  ▁ ▃ ▅ ▇ ▅ ▃ ▁     ▁ ▃ ▅ ▇ ▅ ▃ ▁     ▁ ▃ ▅ ▇ ▅ ▃ ▁
██╗   ██╗██╗    ███████╗ ██████╗ ██╗   ██╗███╗   ██╗██████╗
██║   ██║██║    ██╔════╝██╔═══██╗██║   ██║████╗  ██║██╔══██╗
██║   ██║██║    ███████╗██║   ██║██║   ██║██╔██╗ ██║██║  ██║
██║   ██║██║    ╚════██║██║   ██║██║   ██║██║╚██╗██║██║  ██║
╚██████╔╝██║    ███████║╚██████╔╝╚██████╔╝██║ ╚████║██████╔╝
 ╚═════╝ ╚═╝    ╚══════╝ ╚═════╝  ╚═════╝ ╚═╝  ╚═══╝╚═════╝
      ░ ▒ ▓ █ ▓ ▒ ░     ░ ▒ ▓ █ ▓ ▒ ░     ░ ▒ ▓ █ ▓ ▒ ░
       ██████╗ ███████╗███████╗██╗ ██████╗ ███╗   ██╗
       ██╔══██╗██╔════╝██╔════╝██║██╔════╝ ████╗  ██║
       ██║  ██║█████╗  ███████╗██║██║  ███╗██╔██╗ ██║
       ██║  ██║██╔══╝  ╚════██║██║██║   ██║██║╚██╗██║
       ██████╔╝███████╗███████║██║╚██████╔╝██║ ╚████║
       ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═════╝ ╚═╝  ╚═══╝
  ▇ ▅ ▃ ▁ ▃ ▅ ▇     ▇ ▅ ▃ ▁ ▃ ▅ ▇     ▇ ▅ ▃ ▁ ▃ ▅ ▇
```

Describe what your UI should sound like.
Preview it, tweak it, and download it from the browser.

# UI Sound Design

Translate plain-English sound descriptions into working Web Audio API code. No audio engineering background needed — describe what you want to hear, and this skill provides the synthesis knowledge to make it real.

## Workflow

Every sound follows this loop: **Describe → Generate → Listen → Refine** (with optional **Review** for auditing existing code)

### 1. Describe

The user describes the sound in plain language. Ask clarifying questions using this framework:

**Four questions before generating any sound:**

1. **What triggers it?** (click, hover, toggle, notification, transition, success, error)
2. **What's the emotional tone?** (satisfying, subtle, urgent, playful, professional, minimal)
3. **How prominent should it be?** (barely perceptible, noticeable, attention-grabbing)
4. **Any reference points?** (iOS keyboard, Slack notification, macOS trash, game UI, "like a bubble popping")
5. **Have an audio reference file?** If the user has a .wav or .mp3 file they want to match, direct them to run the analyzer:

   ```
   node skills/ui-sound-design/tools/analyze-sound.mjs path/to/reference.wav
   ```

   Then paste the output back. When a sound profile is provided:
   1. Load `references/audio-file-references.md` for interpretation guidance
   2. Read the `synthesis_suggestion` block for initial parameters
   3. Match to the closest **sound category** using `recipe_starting_point`
   4. Load that recipe from `references/sound-recipes.md`
   5. Override recipe defaults with the profile's suggested parameters
   6. Apply any vocabulary bridge terms from the profile's `VOCABULARY MATCH` section
   7. Proceed to Generate as normal

If the user gives a vague request like "make a click sound", use sensible defaults from the recipes and generate immediately — don't over-ask.

### 2. Generate

1. Match the description to a **sound category** (see quick reference below)
2. Load the recipe from `references/sound-recipes.md`
3. Apply the **vocabulary bridge** to translate adjectives into parameter changes
4. For novel sounds not covered by recipes, compose from building blocks in `references/web-audio-api.md`
5. Output format: **HTML preview** by default (adapt `assets/sound-preview.html`), or ES module / React hook / class if requested

### 3. Listen

Provide the HTML preview file so the user can open it in a browser and hear the sound immediately. Each sound includes a download button that exports a .wav file for use in production code or handoff to developers. Include labeled buttons for each sound variation. The preview must:
- Handle AudioContext suspension (user gesture to start)
- Use the singleton AudioContext pattern
- Include visual feedback on play (the template handles this)

### 4. Refine

When the user gives feedback, translate it using the vocabulary bridge and adjust parameters. Common refinement patterns:
- "I like it but..." → tweak 1-2 parameters
- "Completely wrong" → try a different recipe/approach
- "Too much/little" → scale the relevant parameter up/down
- "More like X" → identify what makes X distinctive and match those characteristics

### 5. Review (optional)

Enter review mode when the user says "review", "audit", or "check my sound code", or pastes existing Web Audio code for evaluation.

**Steps:**
1. Load rules from `references/audio-rules.md`
2. Scan the code against each rule, starting with Critical priority
3. Report findings using the format in `audio-rules.md` — one line per violation with `file:line — [rule-id] description`
4. Provide a summary table (pass/fail counts by priority)
5. Suggest concrete fixes for each failing rule

**When to stay in generate mode:** If the user's request is ambiguous (e.g., "here's my click sound" without asking for review), default to the generative workflow. Only enter review mode when the intent to audit is clear.

## Vocabulary Bridge

This is the core translation layer. When the user uses subjective language, map it to synthesis parameters:

| User Says | Parameter Change | Example |
|-----------|-----------------|---------|
| "Brighter" | Raise frequency or filter cutoff | Filter cutoff 1500 → 3000 Hz |
| "Warmer" | Lower filter cutoff, use sine/triangle wave | Switch sawtooth → sine, cutoff 3000 → 1200 |
| "Darker" | Lower frequency, reduce high harmonics | Add lowpass filter at 800 Hz |
| "Snappier" | Shorter attack and decay | Decay 0.15 → 0.05s |
| "Softer" | Lower volume, longer attack, gentle envelope | Volume 0.3 → 0.15, attack 0 → 0.01s |
| "Louder" / "More prominent" | Raise volume (max 0.8) | Volume 0.2 → 0.4 |
| "Fuller" / "Richer" | Layer oscillators, add detune | Add second osc detuned +7 cents |
| "Thinner" | Remove layers, use sine wave, raise highpass | Single sine, highpass at 500 Hz |
| "More metallic" | FM synthesis, inharmonic ratios | Mod ratio 1.4, increase mod depth |
| "More organic" / "Natural" | Use noise components, subtle randomness | Mix in filtered noise burst |
| "Shorter" / "Crisper" | Reduce total duration | Duration 0.15 → 0.06s |
| "Longer" / "More sustained" | Increase duration and sustain | Duration 0.1 → 0.3s, add sustain phase |
| "More playful" | Higher pitch, bounce/overshoot | Frequency +200 Hz, add pitch overshoot |
| "More professional" | Subtle, clean, minimal | Lower volume, sine wave, short duration |
| "Retro" / "8-bit" | Square wave, quantized pitch | Switch to square, use note frequencies |
| "Bubbly" | Rapid pitch drop, sine wave | startFreq 2000, quick exponential drop |

## Sound Categories — Quick Reference

| Category | Duration | Recipe | Trigger | Key Character |
|----------|----------|--------|---------|---------------|
| Click | 10–80ms | `references/sound-recipes.md#click` | Button press, tap | Noise burst, bandpass filtered |
| Toggle | 80–200ms | `references/sound-recipes.md#toggle` | Switch on/off | Rising/falling pitch sweep |
| Hover | 30–80ms | `references/sound-recipes.md#hover` | Mouse enter | Gentle, nearly subliminal |
| Success | 200–500ms | `references/sound-recipes.md#success` | Task complete, save | Ascending major third |
| Error | 150–400ms | `references/sound-recipes.md#error` | Validation fail, rejected | Descending, buzzy |
| Warning | 150–350ms | `references/sound-recipes.md#warning` | Caution state | Double pulse, mid-range |
| Notification | 200–800ms | `references/sound-recipes.md#notification` | New message, alert | Bell-like FM synthesis |
| Whoosh | 100–400ms | `references/sound-recipes.md#whoosh` | Page transition, slide | Filtered noise sweep |
| Pop | 30–80ms | `references/sound-recipes.md#pop` | Add item, bubble, appear | Sine with pitch drop |
| Custom | varies | `references/web-audio-api.md` | Anything else | Compose from building blocks |

## Critical Implementation Rules

### AudioContext user-gesture requirement
Browsers block audio until a user interaction (click, tap, keydown). Always initialize or resume the AudioContext inside an event handler. The singleton pattern in `references/web-audio-api.md` handles this.

### Never ramp gain to zero
`exponentialRampToValueAtTime(0, ...)` throws an error. Always ramp to `0.001` — it's inaudible but mathematically valid. This applies to every sound. No exceptions.

### Node cleanup
- OscillatorNodes auto-disconnect after `stop()` — no manual cleanup needed
- BufferSourceNodes are one-shot — create a new one each play
- For long-lived filter/gain nodes, call `disconnect()` when done
- Never create a new AudioContext per sound — use the singleton

### Volume safety
- Default volume: `0.3` (gain value)
- Maximum volume: `0.8` — never exceed this
- Hover sounds: `0.03–0.08` (barely perceptible)
- UI sounds should complement, not dominate — err on the side of quiet

### Scheduling precision
Capture `const now = ctx.currentTime` once at the start of each sound function. Derive all scheduling times from `now`. Never read `currentTime` multiple times.

### Use exponential ramps by default
`exponentialRampToValueAtTime` sounds natural for both volume and frequency. `linearRampToValueAtTime` sounds mechanical. Only use linear for sub-50ms transitions.

## Output Formats

### HTML Preview (default)
Adapt `assets/sound-preview.html`. Self-contained, no dependencies, opens in any browser. Best for the iterative listen-refine loop. Includes WAV download — click the download button on any sound to get a .wav file. Sound functions must use `(ctx, dest)` parameters with fallback defaults for download support, and each sound needs a matching entry in the `durations` map.

### ES Module
```javascript
// ui-sounds.js
export function playClick(options) { /* ... */ }
export function playSuccess(options) { /* ... */ }
```

### React Hook
```javascript
// useUISound.js
export function useUISound() {
  const ctxRef = useRef(null);
  const getCtx = useCallback(() => { /* singleton */ }, []);
  return { playClick, playSuccess, /* ... */ };
}
```

### Sound Library Class
Use the `UISoundLibrary` class from `references/sound-recipes.md`. Bundles all sounds with enable/disable and master volume control.

## Resources

### references/
- **`web-audio-api.md`** — Core Web Audio API building blocks: oscillators, envelopes, filters, noise, FM synthesis, factory patterns, common mistakes. Load when building custom sounds or understanding low-level mechanics.
- **`sound-recipes.md`** — Complete working implementations for all 9 sound categories plus a bundled `UISoundLibrary` class. Each recipe includes parameters, code, tuning guide, and variations. **Start here for most requests.**
- **`audio-rules.md`** — Formal validation rules with IDs, priorities, and pass/fail examples. Load when reviewing existing code or when you need to verify generated output against best practices.
- **`tone-js.md`** — Tone.js abstractions for faster prototyping. Simplified synth types, recipe equivalents, effects, and a conversion guide to vanilla Web Audio. Load when the user prefers Tone.js or wants rapid iteration.
- **`audio-file-references.md`** — How to interpret sound profiles from the `analyze-sound.mjs` CLI tool. Maps audio analysis metrics to synthesis parameters and recipe selection. Load when the user provides a sound profile from an audio file reference.

### assets/
- **`sound-preview.html`** — Self-contained HTML template with all 10 default sounds, visual feedback, and AudioContext handling. Adapt this for every preview output.

### tools/
- **`analyze-sound.mjs`** — CLI script that analyzes .wav/.mp3 files and outputs a sound profile. Run with `node tools/analyze-sound.mjs <file>`. Zero dependencies — works with any Node.js installation. Supports .wav natively; other formats require ffmpeg. Outputs duration, envelope, spectral content, tonality, and a synthesis suggestion that maps directly to recipe parameters.

---
> Source: [dannyjpwilliams/ui-sound-design-skill](https://github.com/dannyjpwilliams/ui-sound-design-skill) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-06-24 -->

