aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJukka Jylänki <jujjyl@gmail.com>2013-08-30 16:09:17 +0300
committerAlon Zakai <alonzakai@gmail.com>2013-09-24 16:56:45 -0700
commit87eda4836bfce1a232f96b07d6c6e16dab42e66b (patch)
tree9b896d54984e9ef90f75092b89c923aa0b5918b6
parent4afa3453f3fde6ae5069ec9a9c683a1b3018edb1 (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.js23
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;
},