If you've ever wanted to load a sample in the browser and manipulate it like an instrument — think start time, pitch shifting, and looping — the Web Audio API gives you the tools. This guide walks through building a browser-based sampler with dynamic playback control using nothing but vanilla JavaScript.
Use Cases for Browser-Based Samplers
- Interactive music experiences
- Drum machines or pad samplers
- Real-time sound design tools
Step 1: Load the Sample
We’ll fetch a WAV/MP3 and decode it for playback:
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
async function loadSample(url) {
const res = await fetch(url);
const arrayBuffer = await res.arrayBuffer();
return await audioCtx.decodeAudioData(arrayBuffer);
}
Step 2: Create a Sampler Function
We’ll build a function that creates a playback node each time a note is triggered:
function playSample(buffer, options = {}) {
const source = audioCtx.createBufferSource();
source.buffer = buffer;
const gain = audioCtx.createGain();
gain.gain.value = options.volume || 1.0;
source.playbackRate.value = options.pitch || 1.0;
if (options.loop) {
source.loop = true;
source.loopStart = options.loopStart || 0;
source.loopEnd = options.loopEnd || buffer.duration;
}
source.connect(gain).connect(audioCtx.destination);
source.start(audioCtx.currentTime, options.offset || 0);
return source;
}
Step 3: Trigger with UI or Keyboard
You can hook this into pads, keys, or sequencers:
let sampleBuffer;
loadSample('/samples/snare.wav').then(buffer => {
sampleBuffer = buffer;
});
document.getElementById('trigger').addEventListener('click', () => {
if (sampleBuffer) {
playSample(sampleBuffer, {
pitch: 1.2, // speed up slightly
offset: 0.05, // trim attack
volume: 0.8
});
}
});
Optional: Add a UI for Looping
Browser samplers can support loop regions:
playSample(sampleBuffer, {
loop: true,
loopStart: 0.2,
loopEnd: 0.8,
pitch: 0.8
});
Pros and Cons
✅ Pros
- No dependencies, loads instantly
- Pitch, trim, and loop all in-browser
- Modular and extensible (add envelopes, filters, UI)
⚠️ Cons
- Limited real-time editing without AudioWorklet
- No time-stretching — pitch alters speed
- Needs care to prevent overlapping or memory leaks
🚀 Alternatives
- Howler.js: Simpler sample playback with fallbacks
- Tone.js: Abstractions for sampling, synthesis, and transport
- Web Audio Modules: For advanced samplers and plugin-style architecture
Summary
With just a few lines of code, you can build a fully functional sample trigger in the browser — no plugins, no libraries, just native Web Audio. Add more UI or modulation for full instrument control, or plug it into sequencers for a browser DAW foundation.
If this was useful, you can support me here: buymeacofee.com/hexshift