Layering Sounds

One sine wave is the thinnest sound a speaker can make. It is fine for a tick, and not much else.

A layer is a second source that plays with the first: a different wave shape, a few cents off pitch, a little quieter, and a few milliseconds late. Stack three or four and the same note stops sounding like a test tone. Play the note below, then add layers.

0100200300400 ms

Each bar is one layer on a timeline. Two things make the stack feel like one sound instead of several. The layers start within about 30ms to 60ms of each other, and each one is quieter than the one before it. Push the spacing to 80ms and you start to hear the seams.

The small detune matters as much as the delay. Two copies of the exact same frequency just get louder. Copies that are 5 to 8 cents apart drift against each other, and that drift is what reads as width.

From chord to arpeggio

Layers do not have to share a pitch. This site's success sound is four square waves on C, E, G, and C, each starting 60ms after the last. Drag the spacing to hear where a chord turns into an arpeggio.

C
E
G
C

At 0ms all four notes land together, which is heavier than a confirmation needs to be. Between 40ms and 80ms the ear hears one rising gesture. Past 120ms it becomes a melody, and a cue that takes half a second is asking for more attention than a copy button deserves.

Mixing textures

Not every layer is a note. A short burst of filtered noise has no pitch, but it has an attack, and that is what makes a sound feel like something was pressed. Flip the switch with each texture selected.

Do not disturb

The tone on its own is a beep. The noise on its own is a tap. Together they are a click with a pitch, which is what most physical switches sound like. The noise layer is under 30ms long and sits behind a bandpass filter, so it adds edge without hiss.

Usage

app.ts
import { definePatch } from "@web-kits/audio";

export const patch = definePatch({
  name: "Minimal",
  sounds: {
    // one note, three layers
    note: {
      layers: [
        {
          source: { type: "sine", frequency: 523 },
          envelope: { attack: 0.002, decay: 0.09, sustain: 0, release: 0.03 },
          gain: 0.08,
        },
        {
          source: { type: "triangle", frequency: 523, detune: 8 },
          envelope: { attack: 0.002, decay: 0.09, sustain: 0, release: 0.03 },
          gain: 0.05,
          delay: 0.04,
        },
        {
          source: { type: "noise", color: "white" },
          filter: { type: "bandpass", frequency: 2600 },
          envelope: { attack: 0, decay: 0.018, sustain: 0, release: 0.01 },
          gain: 0.06,
        },
      ],
    },
  },
});

Build one layer at a time. Get the first layer right on its own, then add the next at a lower gain and only keep it if you can hear what it adds. If muting a layer changes nothing, delete it.

Resources

Search concepts

Search for a command to run...