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.
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.
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.
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
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
Retro, @web-kits/audio - The 8-bit patch this site's success sound comes from.
@web-kits/audio - Layers, envelopes, and delays in one small library.
OscillatorNode - The four wave shapes every layer here is built from.
Chorus effect - Why slightly detuned copies of one sound feel wider than the original.
Learning Synths - Ableton's hands-on intro to oscillators, envelopes, and detuning.