home / skills / raphaelsalaja / userinterface-wiki / generating-sounds-with-ai

generating-sounds-with-ai skill

/skills/generating-sounds-with-ai

This skill audits Web Audio API code for sound synthesis best practices, helping you improve audio quality and reliability across projects.

npx playbooks add skill raphaelsalaja/userinterface-wiki --skill generating-sounds-with-ai

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
6.0 KB
---
name: generating-sounds-with-ai
description: Audit Web Audio API code for sound synthesis best practices. Use when reviewing procedural audio, implementing UI sounds, or checking audio parameter quality. Outputs file:line findings.
license: MIT
metadata:
  author: raphael-salaja
  version: "2.0.0"
  source: /content/generating-sounds-with-ai/index.mdx
---

# Generating Sounds with AI

Review Web Audio API code for sound synthesis best practices.

## How It Works

1. Read the specified files (or prompt user for files/pattern)
2. Check against all rules below
3. Output findings in `file:line` format

## Rule Categories

| Priority | Category | Prefix |
|----------|----------|--------|
| 1 | Context Management | `context-` |
| 2 | Decay & Envelope | `envelope-` |
| 3 | Sound Design | `design-` |
| 4 | Parameters | `param-` |

## Rules

### Context Management Rules

#### `context-reuse-single`
Reuse a single AudioContext instance; do not create new ones per sound.

**Fail:**
```ts
function playSound() {
  const ctx = new AudioContext();
  // Creates new context every call
}
```

**Pass:**
```ts
let audioContext: AudioContext | null = null;

function getAudioContext(): AudioContext {
  if (!audioContext) {
    audioContext = new AudioContext();
  }
  return audioContext;
}
```

#### `context-resume-suspended`
Check and resume suspended AudioContext before playing.

**Fail:**
```ts
function playSound() {
  const ctx = getAudioContext();
  // Plays immediately without checking state
}
```

**Pass:**
```ts
function playSound() {
  const ctx = getAudioContext();
  if (ctx.state === "suspended") {
    ctx.resume();
  }
}
```

#### `context-cleanup-nodes`
Disconnect and clean up audio nodes after playback.

**Fail:**
```ts
source.start();
// Nodes remain connected after sound ends
```

**Pass:**
```ts
source.start();
source.onended = () => {
  source.disconnect();
  gain.disconnect();
};
```

### Envelope Rules

#### `envelope-exponential-decay`
Use exponential ramps for natural decay, not linear.

**Fail:**
```ts
gain.gain.linearRampToValueAtTime(0, t + 0.05);
```

**Pass:**
```ts
gain.gain.exponentialRampToValueAtTime(0.001, t + 0.05);
```

#### `envelope-no-zero-target`
Exponential ramps cannot target 0; use 0.001 or similar small value.

**Fail:**
```ts
gain.gain.exponentialRampToValueAtTime(0, t + 0.05);
```

**Pass:**
```ts
gain.gain.exponentialRampToValueAtTime(0.001, t + 0.05);
```

#### `envelope-set-initial-value`
Set initial value before ramping to avoid glitches.

**Fail:**
```ts
gain.gain.exponentialRampToValueAtTime(0.001, t + 0.05);
// No setValueAtTime before ramp
```

**Pass:**
```ts
gain.gain.setValueAtTime(0.3, t);
gain.gain.exponentialRampToValueAtTime(0.001, t + 0.05);
```

### Sound Design Rules

#### `design-noise-for-percussion`
Use filtered noise for clicks/taps, not oscillators.

**Fail:**
```ts
// Click sound using sine oscillator
const osc = ctx.createOscillator();
osc.type = "sine";
// Results in tonal "beep" not "click"
```

**Pass:**
```ts
// Click sound using noise burst
const buffer = ctx.createBuffer(1, ctx.sampleRate * 0.008, ctx.sampleRate);
const data = buffer.getChannelData(0);
for (let i = 0; i < data.length; i++) {
  data[i] = (Math.random() * 2 - 1) * Math.exp(-i / 50);
}
```

#### `design-oscillator-for-tonal`
Use oscillators with pitch movement for tonal sounds (pops, confirmations).

**Fail:**
```ts
// Confirmation sound using static frequency
osc.frequency.value = 400;
```

**Pass:**
```ts
// Confirmation sound with pitch sweep
osc.frequency.setValueAtTime(400, t);
osc.frequency.exponentialRampToValueAtTime(600, t + 0.04);
```

#### `design-filter-for-character`
Apply bandpass filter to shape percussive sounds.

**Fail:**
```ts
// Raw noise without filtering
source.connect(gain).connect(ctx.destination);
```

**Pass:**
```ts
const filter = ctx.createBiquadFilter();
filter.type = "bandpass";
filter.frequency.value = 4000;
filter.Q.value = 3;
source.connect(filter).connect(gain).connect(ctx.destination);
```

### Parameter Rules

#### `param-click-duration`
Click/tap sounds should be 5-15ms duration.

**Fail:**
```ts
const buffer = ctx.createBuffer(1, ctx.sampleRate * 0.1, ctx.sampleRate);
// 100ms is too long for a click
```

**Pass:**
```ts
const buffer = ctx.createBuffer(1, ctx.sampleRate * 0.008, ctx.sampleRate);
// 8ms is appropriate for a click
```

#### `param-filter-frequency-range`
Bandpass filter for clicks should be 3000-6000Hz.

**Fail:**
```ts
filter.frequency.value = 500; // Too low, sounds muffled
```

**Pass:**
```ts
filter.frequency.value = 4000; // Crisp, present
```

#### `param-reasonable-gain`
Gain values should not exceed 1.0 to prevent clipping.

**Fail:**
```ts
gain.gain.setValueAtTime(1.5, t);
```

**Pass:**
```ts
gain.gain.setValueAtTime(0.3, t);
```

#### `param-q-value-range`
Filter Q for clicks should be 2-5 for focused but not harsh sound.

**Fail:**
```ts
filter.Q.value = 15; // Too resonant, harsh
```

**Pass:**
```ts
filter.Q.value = 3; // Focused but natural
```

## Output Format

When reviewing files, output findings as:

```
file:line - [rule-id] description of issue

Example:
lib/sounds.ts:23 - [envelope-exponential-decay] Using linearRampToValueAtTime instead of exponential
lib/sounds.ts:45 - [context-reuse-single] Creating new AudioContext on each call
```

## Summary Table

After findings, output a summary:

| Rule | Count | Severity |
|------|-------|----------|
| `context-reuse-single` | 1 | HIGH |
| `envelope-exponential-decay` | 3 | MEDIUM |
| `param-click-duration` | 1 | LOW |

## Parameter Translation Table

When user describes issues, translate to parameter changes:

| User Says | Parameter Change |
|-----------|------------------|
| "too harsh" | Lower filter frequency, reduce Q |
| "too muffled" | Higher filter frequency |
| "too long" | Shorter duration, faster decay |
| "cuts off abruptly" | Use exponential decay |
| "more mechanical" | Higher Q, faster decay |
| "softer" | Lower gain, triangle wave |

## References

- [Web Audio API - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API)

Overview

This skill audits TypeScript Web Audio API code for sound synthesis best practices and outputs findings in file:line format. It focuses on context management, envelope usage, sound design, and parameter ranges to ensure reliable, natural, and safe UI sounds. Use it to enforce consistent procedural audio patterns and to catch common pitfalls that affect performance and perceived quality.

How this skill works

The tool scans specified files or user-provided file patterns and checks code against a set of prioritized rules. It detects issues like multiple AudioContext creations, missing context resume checks, improper envelope ramps, poor sound-design choices, and out-of-range parameter values. Results are emitted as file:line entries followed by a compact summary table and suggested parameter translations for user feedback.

When to use it

  • Reviewing procedural audio implementations for UI feedback (clicks, confirmations, alerts).
  • Auditing code before release to prevent audio performance or clipping problems.
  • Validating new sound components or libraries that use the Web Audio API.
  • Checking pull requests that add or modify audio playback logic.
  • Ensuring sound synthesis follows best practices for mobile and low-power environments.

Best practices

  • Reuse a single AudioContext instance and avoid creating one per sound.
  • Resume suspended contexts before playback and clean up nodes after sounds end.
  • Use exponential ramps with non-zero targets and set initial gain values to avoid glitches.
  • Model percussive clicks with filtered noise bursts and use oscillators for tonal sweeps.
  • Constrain parameters: click durations 5–15 ms, bandpass 3000–6000 Hz, Q ≈ 2–5, gain ≤ 1.0.

Example use cases

  • Scan a codebase to list lines that create new AudioContext instances or forget to resume suspended contexts.
  • Find envelopes that use linear ramps or exponential ramps targeting zero and point to exact lines to fix.
  • Detect click sounds implemented with oscillators instead of short filtered noise buffers.
  • Report filter frequency/Q values and gain settings that exceed recommended ranges for UI sounds.
  • Produce a summary table of rule violations and translate user feedback into concrete parameter changes.

FAQ

What output format does the auditor produce?

Findings are emitted as file:line - [rule-id] description entries followed by a compact summary table and parameter translation suggestions.

Can it suggest concrete parameter changes for designer feedback?

Yes. It maps common qualitative comments like "too harsh" or "too long" to explicit parameter adjustments such as lower filter frequency, reduce Q, or shorten decay.