How to Generate Procedural Audio Textures in the Browser (No Samples Needed)
Procedural audio lets you generate complex sounds dynamically — no pre-recorded samples required. This tutorial explores how to build ambient textures like wind, rain, or static entirely in-browser using raw Web Audio API techniques. Lightweight, flexible, and surprisingly fun. Use Cases for Procedural Sound Background audio in games or immersive websites Generative music experiments or audio art Minimal sound libraries for performance-focused apps Step 1: Set Up Audio Context and Noise Generator White noise is a great foundation for procedural sound: const audioCtx = new (window.AudioContext || window.webkitAudioContext)(); function createWhiteNoiseBuffer() { const buffer = audioCtx.createBuffer(1, audioCtx.sampleRate * 2, audioCtx.sampleRate); const data = buffer.getChannelData(0); for (let i = 0; i < data.length; i++) { data[i] = Math.random() * 2 - 1; } return buffer; } Step 2: Play the Noise Loop We’ll loop the generated buffer to create a constant noise floor: const noiseSource = audioCtx.createBufferSource(); noiseSource.buffer = createWhiteNoiseBuffer(); noiseSource.loop = true; const gain = audioCtx.createGain(); gain.gain.value = 0.3; noiseSource.connect(gain).connect(audioCtx.destination); noiseSource.start(); Step 3: Add Texture with Filtering and Modulation Shape the noise into something more like “wind” or “hiss”: const filter = audioCtx.createBiquadFilter(); filter.type = 'lowpass'; filter.frequency.value = 1000; const lfo = audioCtx.createOscillator(); const lfoGain = audioCtx.createGain(); lfo.frequency.value = 0.2; // slow modulation lfoGain.gain.value = 500; lfo.connect(lfoGain).connect(filter.frequency); lfo.start(); noiseSource.disconnect(); noiseSource.connect(filter).connect(gain).connect(audioCtx.destination); Step 4: Try Different Textures Change filter.type to bandpass or highpass for different effects Add a second noise generator for stereo width Use multiple LFOs for layered modulation Pros and Cons ✅ Pros Zero asset downloads — small page weight Completely dynamic and tweakable in real time Perfect for low-memory environments or experimental audio ⚠️ Cons Procedural noise isn’t suited for realistic sound effects AudioContext timing can vary slightly across devices No built-in presets — must hand-tune filters/modulation
Procedural audio lets you generate complex sounds dynamically — no pre-recorded samples required. This tutorial explores how to build ambient textures like wind, rain, or static entirely in-browser using raw Web Audio API techniques. Lightweight, flexible, and surprisingly fun.
Use Cases for Procedural Sound
- Background audio in games or immersive websites
- Generative music experiments or audio art
- Minimal sound libraries for performance-focused apps
Step 1: Set Up Audio Context and Noise Generator
White noise is a great foundation for procedural sound:
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function createWhiteNoiseBuffer() {
const buffer = audioCtx.createBuffer(1, audioCtx.sampleRate * 2, audioCtx.sampleRate);
const data = buffer.getChannelData(0);
for (let i = 0; i < data.length; i++) {
data[i] = Math.random() * 2 - 1;
}
return buffer;
}
Step 2: Play the Noise Loop
We’ll loop the generated buffer to create a constant noise floor:
const noiseSource = audioCtx.createBufferSource();
noiseSource.buffer = createWhiteNoiseBuffer();
noiseSource.loop = true;
const gain = audioCtx.createGain();
gain.gain.value = 0.3;
noiseSource.connect(gain).connect(audioCtx.destination);
noiseSource.start();
Step 3: Add Texture with Filtering and Modulation
Shape the noise into something more like “wind” or “hiss”:
const filter = audioCtx.createBiquadFilter();
filter.type = 'lowpass';
filter.frequency.value = 1000;
const lfo = audioCtx.createOscillator();
const lfoGain = audioCtx.createGain();
lfo.frequency.value = 0.2; // slow modulation
lfoGain.gain.value = 500;
lfo.connect(lfoGain).connect(filter.frequency);
lfo.start();
noiseSource.disconnect();
noiseSource.connect(filter).connect(gain).connect(audioCtx.destination);
Step 4: Try Different Textures
- Change
filter.type
tobandpass
orhighpass
for different effects - Add a second noise generator for stereo width
- Use multiple LFOs for layered modulation
Pros and Cons
✅ Pros
- Zero asset downloads — small page weight
- Completely dynamic and tweakable in real time
- Perfect for low-memory environments or experimental audio
⚠️ Cons
- Procedural noise isn’t suited for realistic sound effects
- AudioContext timing can vary slightly across devices
- No built-in presets — must hand-tune filters/modulation