The project involved a piece of music where each individual track (say, the bassline, drumbeat, synth lead, etc) could be individually toggled on/off at any time. The tracks themselves were a minute long and produced as a whole, then split apart into individual components. The technical challenge was to have them all play simultaneously in the browser—muted to start with—and let the user enable them at will, without them going out of sync.
My initial approach was a basic implementation of the standard HTML5
Next I spent some time with Gapless5 , a JavaScript library that promises to merge the capabilities of HTML5 audio and the new Web Audio API to give a “gapless” loop. This was initially successful, but we found that testing on non-local environments resulted in an audible out-of-sync issue with the individual tracks. In my best test conditions I measured a gap of 23ms between the first track starting and the sixth one, but even this was enough to noticeably throw out the sync between the drums and the bass.
In the end, I decided to harness the power of the Web Audio API . I spent some time poring over the very thorough introduction by Boris Smus over on HTML5 Rocks , and was able to put together a demo which began each track completely in sync. The downsides of this approach was the lack of Internet Explorer support, but here at the Guerrillas team we’re lucky enough to be able to use cutting-edge tech without having to implement it in every ancient browser.
In the end I used much of the example code in Boris’s article to build a reusable AMD-style module for loading audio files, triggering a callback when complete, and muting/unmuting arbitrary tracks at will. Here’s the audio code, mostly written by Boris:
… and here’s how we’re using it for the Sound of Autumn app – we pass it an object of track names and file paths, which will be downloaded (in full!) on the client, and then a callback function is triggered once each track is done (enabling a preloading animation to be toggled).
The audio module also exposes a startAll method which will begin all tracks at once (optionally muted), and a toggleTrack method which takes a track name and mutes/unmutes a song.
This code made the app much more viable for us to launch – before this, the HTML5