1 define([ 'util/ensureCallback', 'util/cacheBust', 'util/timeout' ], function (ensureCallback, cacheBust, timeout) {
4 function getPlayLatency(audio, callback) {
5 callback = ensureCallback(callback);
10 var endTime = Date.now();
12 audio.removeEventListener('play', update, false);
13 audio.removeEventListener('timeupdate', update, false);
16 callback(null, endTime - startTime);
19 audio.addEventListener('play', update, false);
20 audio.addEventListener('timeupdate', update, false);
22 startTime = Date.now();
26 function audioLatency(callback) {
27 callback = ensureCallback(callback);
30 callback(new Error('Audio not supported'));
34 var audio = new window.Audio();
36 function onCanPlayThrough() {
37 audio.removeEventListener('canplaythrough', onCanPlayThrough, false);
39 // Run the test twice: once for "cold" time, once for "warm" time.
40 getPlayLatency(audio, function (err, coldTime) {
46 getPlayLatency(audio, function (err, warmTime) {
53 pass: coldTime <= MAX_LATENCY && warmTime <= MAX_LATENCY,
54 coldLatency: coldTime,
62 callback(new Error('Failed to load audio'));
65 var source = document.createElement('source');
66 source.src = cacheBust.url('assets/silence.wav');
67 source.addEventListener('error', onError, false);
69 audio.addEventListener('canplaythrough', onCanPlayThrough, false);
70 audio.addEventListener('error', onError, false);
71 audio.appendChild(source);
74 // Work around Webkit bug (present in Chrome <= 15, Safari <= 5, at
75 // time of writing) where the browser will decide it doesn't /need/
76 // to download all these pesky audio files.
77 window['audio__' + Math.random()] = audio;
80 return function (callback) {
81 callback = ensureCallback(callback);
83 timeout(5000, audioLatency, callback);