diff options
author | Jukka Jylänki <jujjyl@gmail.com> | 2013-08-30 16:09:17 +0300 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-09-24 16:56:45 -0700 |
commit | 87eda4836bfce1a232f96b07d6c6e16dab42e66b (patch) | |
tree | 9b896d54984e9ef90f75092b89c923aa0b5918b6 | |
parent | 4afa3453f3fde6ae5069ec9a9c683a1b3018edb1 (diff) |
Fix bug where resuming SDL audio multiple times could cause multiple audio event loops to be accumulated. Add a mechanism for avoiding buffer starving a bit better with Web Audio.
-rw-r--r-- | src/library_sdl.js | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/src/library_sdl.js b/src/library_sdl.js index ecfc84cc..4079d3ef 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -1571,6 +1571,8 @@ var LibrarySDL = { // The pushAudio function with a new audio buffer whenever there is new audio data to schedule to be played back on the device. SDL.audio.pushAudio=function(ptr,sizeBytes) { try { + --SDL.audio.numAudioTimersPending; + var sizeSamples = sizeBytes / SDL.audio.bytesPerSample; // How many samples fit in the callback buffer? var sizeSamplesPerChannel = sizeSamples / SDL.audio.channels; // How many samples per a single channel fit in the cb buffer? if (sizeSamplesPerChannel != SDL.audio.samples) { @@ -1619,7 +1621,20 @@ var LibrarySDL = { var buffer_duration = sizeSamplesPerChannel / SDL.audio.freq; SDL.audio.nextPlayTime = playtime + buffer_duration; SDL.audio.nextSoundSource = (SDL.audio.nextSoundSource + 1) % 4; - SDL.audio.timer = Browser.safeSetTimeout(SDL.audio.caller, 1000*(playtime-curtime)); + var secsUntilNextCall = playtime-curtime; + + // Queue the next audio frame push to be performed when the previously queued buffer has finished playing. + if (SDL.audio.numAudioTimersPending == 0) { + var preemptBufferFeedMSecs = buffer_duration/2.0; + SDL.audio.timer = Browser.safeSetTimeout(SDL.audio.caller, Math.max(0.0, 1000.0*secsUntilNextCall-preemptBufferFeedMSecs)); + ++SDL.audio.numAudioTimersPending; + } + + // If we are risking starving, immediately queue an extra second buffer. + if (secsUntilNextCall <= buffer_duration && SDL.audio.numAudioTimersPending <= 1) { + ++SDL.audio.numAudioTimersPending; + Browser.safeSetTimeout(SDL.audio.caller, 1.0); + } } catch(e) { console.log('Web Audio API error playing back audio: ' + e.toString()); } @@ -1665,12 +1680,14 @@ var LibrarySDL = { if (pauseOn) { if (SDL.audio.timer !== undefined) { clearTimeout(SDL.audio.timer); + SDL.audio.numAudioTimersPending = 0; SDL.audio.timer = undefined; } - } else {// if (SDL.audio.timer === undefined) { + } else if (!SDL.audio.timer) { // Start the audio playback timer callback loop. + SDL.audio.numAudioTimersPending = 1; SDL.audio.timer = Browser.safeSetTimeout(SDL.audio.caller, 1); - SDL.audio.startTime = Date.now() / 1000.0; + SDL.audio.startTime = Date.now() / 1000.0; // Only used for Mozilla Audio Data API. Not needed for Web Audio API. } SDL.audio.paused = pauseOn; }, |