William
William

Reputation: 4578

How to compensate for setInterval timing drift in Javascript audio

I have two instances of setInterval. Each is triggering a different function ( these two functions are title quarterNoteFunc & eighthNoteFunc ) at repeated intervals. The interval for quarterNoteFunc is 600 milliseconds. The interval for eighthNoteFunc is 300 milliseconds. Both of these functions each trigger a different audio file at repeat intervals hence creating a basic music rhythm. The rhythm between the two function calls eventually "drifts" in Google Chrome making the rhythm between the two sounds dissolve. My question is:

It seems that even though browser based timing is garbage their should be a way to create some kind of "hard" timing reference so that the sounds are locked even if the "global" timing gets offset hence keeping the sounds in sync. I thought assigning the same variable milliseconds (code below) would inhibit this - but I was wrong.

The (abbreviated) code looks like this

milliseconds = 600;

quarterNote = setInterval(quarterNoteFunc, milliseconds);

eighthNote = setInterval(eighthNoteFunc, milliseconds/2);

Upvotes: 2

Views: 510

Answers (1)

OverZealous
OverZealous

Reputation: 39560

Probably the best way to do this is to have a single, always active 1/8 note interval, then call the quarter-note every other tick:

// wrapped in a closure to allow for a private tickCount variable
// alternatively, you could use a more advanced object with start/stop methods, etc.
(function() {
    var tickCount = 0,
        tick = function() {
            eighthNoteFunc();
            if(tickCount %2 == 0) {
                quarterNoteFunc();
            }
            tickCount++;
        };

    setInterval(tick, 300);
})();

This ensures that the methods are always called on the same tick. You can also expand this to support half notes (tickCount % 4 == 0) and whole notes (tickCount % 8 == 0).


This interested me, so I decided to create a fully-working sample (except, using animated backgrounds instead of audio): http://jsfiddle.net/SycBm/

This allows you to see the eighth-, quarter-, and half- notes ticking in sync, as well as start & stop the timer, and independently enable or disable the notes.

Enjoy!

Upvotes: 1

Related Questions