diff options
author | juj <jujjyl@gmail.com> | 2013-11-15 14:17:03 -0800 |
---|---|---|
committer | juj <jujjyl@gmail.com> | 2013-11-15 14:17:03 -0800 |
commit | 0c4d11f4caaa960cf283a4c2112cbdf6a175cadd (patch) | |
tree | 1885312234a7ac521bce776ca644f5e18eb963c1 | |
parent | 26b6ce0fc6e8aa2207d2066fb1ecfc84679ca536 (diff) | |
parent | 9dfd2e2e00e5119767f22145a1ec05a5d5e1c277 (diff) |
Merge pull request #1806 from juj/sdl_audio_queueing
Sdl audio queueing
-rw-r--r-- | src/library_sdl.js | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/src/library_sdl.js b/src/library_sdl.js index c46364ff..f780e15a 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -1609,7 +1609,7 @@ var LibrarySDL = { } else if (SDL.audio.channels != 1 && SDL.audio.channels != 2) { // Unsure what SDL audio spec supports. Web Audio spec supports up to 32 channels. console.log('Warning: Using untested number of audio channels ' + SDL.audio.channels); } - if (SDL.audio.samples < 1024 || SDL.audio.samples > 524288 /* arbitrary cap */) { + if (SDL.audio.samples < 128 || SDL.audio.samples > 524288 /* arbitrary cap */) { throw 'Unsupported audio callback buffer size ' + SDL.audio.samples + '!'; } else if ((SDL.audio.samples & (SDL.audio.samples-1)) != 0) { throw 'Audio callback buffer size ' + SDL.audio.samples + ' must be a power-of-two!'; @@ -1620,6 +1620,10 @@ var LibrarySDL = { SDL.audio.bufferSize = totalSamples*SDL.audio.bytesPerSample; SDL.audio.buffer = _malloc(SDL.audio.bufferSize); + // To account for jittering in frametimes, always have multiple audio buffers queued up for the audio output device. + // This helps that we won't starve that easily if a frame takes long to complete. + SDL.audio.numSimultaneouslyQueuedBuffers = Module['SDL_numSimultaneouslyQueuedBuffers'] || 3; + // Create a callback function that will be routinely called to ask more audio data from the user application. SDL.audio.caller = function SDL_audio_caller() { if (!SDL.audio) { @@ -1636,6 +1640,7 @@ var LibrarySDL = { SDL.audio.mozBuffer = new Float32Array(totalSamples); SDL.audio.nextPlayTime = 0; SDL.audio.pushAudio = function SDL_audio_pushAudio(ptr, size) { + --SDL.audio.numAudioTimersPending; 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 // needs to be Float32 interleaved, so perform a sample conversion. @@ -1654,14 +1659,22 @@ var LibrarySDL = { // Compute when the next audio callback should be called. var curtime = Date.now() / 1000.0 - SDL.audio.startTime; +#if ASSERTIONS if (curtime > SDL.audio.nextPlayTime && SDL.audio.nextPlayTime != 0) { console.log('warning: Audio callback had starved sending audio by ' + (curtime - SDL.audio.nextPlayTime) + ' seconds.'); } +#endif 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. + // Schedule the next audio callback call to occur when the current one finishes. SDL.audio.timer = Browser.safeSetTimeout(SDL.audio.caller, 1000.0 * (playtime-curtime)); + ++SDL.audio.numAudioTimersPending; + // And also schedule extra buffers _now_ if we have too few in queue. + if (SDL.audio.numAudioTimersPending < SDL.audio.numSimultaneouslyQueuedBuffers) { + ++SDL.audio.numAudioTimersPending; + Browser.safeSetTimeout(SDL.audio.caller, 1.0); + } } } else { // Initialize Web Audio API if we haven't done so yet. Note: Only initialize Web Audio context ever once on the web page, @@ -1724,9 +1737,11 @@ var LibrarySDL = { // Schedule the generated sample buffer to be played out at the correct time right after the previously scheduled // sample buffer has finished. var curtime = SDL.audioContext['currentTime']; -// if (curtime > SDL.audio.nextPlayTime && SDL.audio.nextPlayTime != 0) { -// console.log('warning: Audio callback had starved sending audio by ' + (curtime - SDL.audio.nextPlayTime) + ' seconds.'); -// } +#if ASSERTIONS + if (curtime > SDL.audio.nextPlayTime && SDL.audio.nextPlayTime != 0) { + console.log('warning: Audio callback had starved sending audio by ' + (curtime - SDL.audio.nextPlayTime) + ' seconds.'); + } +#endif var playtime = Math.max(curtime, SDL.audio.nextPlayTime); SDL.audio.soundSource[SDL.audio.nextSoundSource]['start'](playtime); var buffer_duration = sizeSamplesPerChannel / SDL.audio.freq; @@ -1741,8 +1756,8 @@ var LibrarySDL = { ++SDL.audio.numAudioTimersPending; } - // If we are risking starving, immediately queue an extra second buffer. - if (secsUntilNextCall <= buffer_duration && SDL.audio.numAudioTimersPending <= 1) { + // If we are risking starving, immediately queue extra buffers. + if (secsUntilNextCall <= buffer_duration && SDL.audio.numAudioTimersPending < SDL.audio.numSimultaneouslyQueuedBuffers) { ++SDL.audio.numAudioTimersPending; Browser.safeSetTimeout(SDL.audio.caller, 1.0); } |