JSFiddle - React, Tailwind, and code Playground

by mohayonao

HTML

<button id="test">
test
</button>

JavaScript

var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext = new AudioContext();
var audioBuffers = [];

function fetchAudioBuffer(audioContext, url) {
  return new Promise(function(resolve, reject) {
    var xhr = new XMLHttpRequest();

    xhr.open("GET", url, true);
    xhr.responseType = "arraybuffer";

    xhr.onload = function() {
      if (xhr.response) {
        audioContext.decodeAudioData(xhr.response, resolve);
      }
    };
    xhr.onerror = reject;

    xhr.send();
  });
}

Promise.all([ "ch", "sd", "bd" ].map(function(name) {
  return fetchAudioBuffer(
    audioContext,
    "https://mohayonao.github.io/files/samples/808/" + name + "00.wav"
  );
})).then(function(results) {
  [].push.apply(audioBuffers, results);
});

var timerId = 0;
var counter = 0;
var pattern = [
  [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
  [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 ],
  [ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 ],
];

document.getElementById("test").onclick = function() {
  if (timerId === 0) {
    counter = 0;
    timerId = setInterval(loop, 150);
  } else {
    clearTimeout(timerId);
    timerId = 0;
  }
};

function shot(destination, playbackTime, opts) {
  if (opts.buffer == null) {
    return;
  }
  var t0 = playbackTime;
  var audioContext = destination.context;
  var bufferSource = audioContext.createBufferSource();
  
  bufferSource.buffer = opts.buffer;
  bufferSource.start(t0);
  bufferSource.connect(destination);
}

function loop() {
  var destination = audioContext.destination;
  var playbackTime = audioContext.currentTime;

  pattern.forEach(function(pat, index) {
    if (pat[counter]) {
      shot(destination, playbackTime, { buffer: audioBuffers[index] });
    }
  });
  
  counter = (counter + 1) % 16;
}