Reputation: 4588
I am trying to learn how to write a basic program that lets me see the correct way to schedule sound events using the web audio API to seed my understanding of the pattern needed to build a simple sound sequencer. I have tried to understand Chris Wilson's tales of two clocks article and it just completely goes over my head. So basically I'm hoping people who do understand it could attempt to explain it in different ways with the hopes that one of them will 'stick', similar to how StackOverflow has a thread that encourages different explanations of closures. Let me show what I do understand thus far.
I understand how to make a simple sequencer with setInterval
I understand that you can schedule sounds to be played using code such as:
playSound.start(audioContext.currentTime+numb);
What I don't understand conceptually is how to hook visual ques to audio play events in a manner that uses the web audio api timing instead of setInterval/setTimeout.
I'm in the process of noodling around with this to learn exactly how it works: http://www.html5rocks.com/en/tutorials/audio/scheduling/goodmetronome.html
But in the meantime I thought I would post this thread to help learn more in parallel from those on SO.
Upvotes: 3
Views: 2646
Reputation: 13908
I'm not sure what you mean by "hook visual queues to audio play events", so elaborate if this doesn't address your concern.
You still need to use setInterval (or setTimeout) for scheduling in a well-implemented sequencer. The problem is the accuracy of setInterval/setTimeout, particularly in the main thread, can be quite low (i.e. when you say "setTimeout(600)", you might be called back in 600ms; you might be called back in 640ms). This happens due to other things going on in the main thread (like layout, rendering, and Javascript garbage collection), as well as the event handling system itself in Javascript.
To get around this problem, you need a second layer of scheduling - in other words, instead of your setInterval callback calling "start(0)" (which basically means "start playing as soon as you get this call"), you say "start( sequenceStartTime + offset )" early enough so it starts at the right time, but late enough so you can decide NOT to call it (i.e. you don't need to cue up the entire song in audio events). Audio events are dispatched with VERY high precision - if you say "start this buffer playing at time t", it will start at time t - not possibly thirty milliseconds later.
If you're asking "how do I make it so when the user hits the pad, it remembers that to play it back at the right time in the sequence" - well, you remember when you start the sequence in audio and system time:
sequenceStartTime = Date.now();
sequenceAudioStartTime = audioContext.currentTime;
and use what # of loop you're on times the length of the sequence to calculate the start time. (This is basically what that metronome does.) Happy to walk through in real-time in chat.
Upvotes: 2