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