diff options
author | Jukka Jylänki <jujjyl@gmail.com> | 2013-06-16 18:30:27 +0300 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-09-24 16:56:44 -0700 |
commit | 257d5f4d0b4932817b2bbf9071134346ed7f6392 (patch) | |
tree | cc8882197e6acfe7a3675d560ae8327891e72965 /src/library_sdl.js | |
parent | 84c042143b57382e07d1af137d47fd36288b34dd (diff) |
Fix audio callback overflow problems by avoiding using Browser.safeSetTimeout, and instead calling safeSetInterval to control the timing drift explicitly.
Diffstat (limited to 'src/library_sdl.js')
-rw-r--r-- | src/library_sdl.js | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/src/library_sdl.js b/src/library_sdl.js index 55e9aa49..3851caaf 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -1523,6 +1523,7 @@ var LibrarySDL = { if (typeof(SDL.audio.audioOutput['mozSetup'])==='function') { // Primarily use Mozilla Audio Data API if available. SDL.audio.audioOutput['mozSetup'](SDL.audio.channels, SDL.audio.freq); // use string attributes on mozOutput for closure compiler SDL.audio.mozBuffer = new Float32Array(totalSamples); + SDL.audio.nextPlayTime = 0; SDL.audio.pushAudio = function(ptr, size) { var mozBuffer = SDL.audio.mozBuffer; // The input audio data for SDL audio is either 8-bit or 16-bit interleaved across channels, output for Mozilla Audio Data API @@ -1537,7 +1538,19 @@ var LibrarySDL = { mozBuffer[i] = ((v >= 0) ? v-128 : v+128) /128; } } + // Submit the audio data to audio device. SDL.audio.audioOutput['mozWriteAudio'](mozBuffer); + + // Compute when the next audio callback should be called. + var curtime = Date.now() / 1000.0 - SDL.audio.startTime; + if (curtime > SDL.audio.nextPlayTime && SDL.audio.nextPlayTime != 0) { + console.log('warning: Audio callback had starved sending audio by ' + (curtime - SDL.audio.nextPlayTime) + ' seconds.'); + } + var playtime = Math.max(curtime, SDL.audio.nextPlayTime); + var buffer_duration = SDL.audio.samples / SDL.audio.freq; + SDL.audio.nextPlayTime = playtime + buffer_duration; + // Schedule the next audio callback call. + SDL.audio.timer = Browser.safeSetTimeout(SDL.audio.caller, 1000.0 * (playtime-curtime)); } } else { // Initialize Web Audio API if we haven't done so yet. Note: Only initialize Web Audio context ever once on the web page, @@ -1598,14 +1611,10 @@ var LibrarySDL = { } var playtime = Math.max(curtime, SDL.audio.nextPlayTime); SDL.audio.soundSource[SDL.audio.nextSoundSource]['start'](playtime); - var buffer_duration = SDL.audio.soundSource[SDL.audio.nextSoundSource]['buffer']['duration']; + var buffer_duration = sizeSamplesPerChannel / SDL.audio.freq; SDL.audio.nextPlayTime = playtime + buffer_duration; SDL.audio.nextSoundSource = (SDL.audio.nextSoundSource + 1) % 4; - // Make sure we are always more than one sample block ahead of the current time to avoid starving. - if (curtime + buffer_duration + buffer_duration >= SDL.audio.nextPlayTime) { - // Immediately queue up an extra buffer to force the sound feeding to be ahead by more than one sample block: - Browser.safeSetTimeout(SDL.audio.caller, 1); - } + SDL.audio.timer = Browser.safeSetTimeout(SDL.audio.caller, 1000*(playtime-curtime)); } catch(e) { console.log('Web Audio API error playing back audio: ' + e.toString()); } @@ -1648,10 +1657,15 @@ var LibrarySDL = { if (!SDL.audio) { return; } - if (SDL.audio.paused !== pauseOn) { - SDL.audio.timer = pauseOn ? SDL.audio.timer && clearInterval(SDL.audio.timer) : Browser.safeSetInterval(SDL.audio.caller, 1000 * SDL.audio.samples / SDL.audio.freq); - // Immediately queue up a buffer to make the sound feeding to be ahead by one sample block. - Browser.safeSetTimeout(SDL.audio.caller, 1); + if (pauseOn) { + if (SDL.audio.timer !== undefined) { + clearTimeout(SDL.audio.timer); + SDL.audio.timer = undefined; + } + } else {// if (SDL.audio.timer === undefined) { + // Start the audio playback timer callback loop. + SDL.audio.timer = Browser.safeSetTimeout(SDL.audio.caller, 1); + SDL.audio.startTime = Date.now() / 1000.0; } SDL.audio.paused = pauseOn; }, |