I\'m trying to mimic the Web Audio API multitrack demo from the \'Mozilla Web Audio API for games\' Web doc.
https://developer.mozilla.org/en-US/docs/Games/Techniques/Au
Figured it out with help from @Kaiido
Example with both synchronization and starting a new track where a previous track stops:
let active_source = null;
let buffers = {};
const context = new(window.AudioContext || window.webkitAudioContext)();
let offset = 0;
const tempo = 3.074074076;
const tracks = document.getElementsByClassName('track');
function playTrack(url) {
let buffer = buffers[url];
let source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.loop = true;
if (offset == 0) {
source.start();
offset = context.currentTime;
active_source = source;
} else {
let relativeTime = context.currentTime - offset;
let beats = relativeTime / tempo;
let remainder = beats - Math.floor(beats);
let delay = tempo - (remainder*tempo);
let when = context.currentTime+delay;
stopActiveSource(when);
source.start(context.currentTime+delay,relativeTime+delay);
active_source = source;
source.onended = function() {
active_source = null;
};
}
}
for (var i = 0, len = tracks.length; i < len; i++) {
tracks[i].addEventListener('click', function(e) {
playTrack(this.href);
e.preventDefault();
});
getBuffer(tracks[i].href);
}
function getBuffer(url) {
const request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function(evt) {
context.decodeAudioData(request.response, store);
};
request.send();
function store(buffer) {
buffers[url] = buffer;
}
}
function stopActiveSource(when) {
if (active_source) {
active_source.onended = null;
active_source.stop(when);
}
}
http://jsfiddle.net/mdq2c1wv/1/