modules/emscripten/src/library_openal.js in webruby-0.1.2 vs modules/emscripten/src/library_openal.js in webruby-0.2.1

- old
+ new

@@ -4,11 +4,132 @@ $AL__deps: ['$Browser'], $AL: { contexts: [], currentContext: null, QUEUE_INTERVAL: 25, - QUEUE_LOOKAHEAD: 100 + QUEUE_LOOKAHEAD: 100, + + updateSources: function(context) { + for (var i = 0; i < context.src.length; i++) { + AL.updateSource(context.src[i]); + } + }, + + updateSource: function(src) { +#if OPENAL_DEBUG + var idx = AL.currentContext.src.indexOf(src); +#endif + if (src.state !== 0x1012 /* AL_PLAYING */) { + return; + } + + var currentTime = AL.currentContext.ctx.currentTime; + var startTime = src.bufferPosition; + + for (var i = src.buffersPlayed; i < src.queue.length; i++) { + var entry = src.queue[i]; + + var startOffset = startTime - currentTime; + var endTime = startTime + entry.buffer.duration; + + // Clean up old buffers. + if (currentTime >= endTime) { + // Update our location in the queue. + src.bufferPosition = endTime; + src.buffersPlayed = i + 1; + + // Stop / restart the source when we hit the end. + if (src.buffersPlayed >= src.queue.length) { + if (src.loop) { + AL.setSourceState(src, 0x1012 /* AL_PLAYING */); + } else { + AL.setSourceState(src, 0x1014 /* AL_STOPPED */); + } + } + } + // Process all buffers that'll be played before the next tick. + else if (startOffset < (AL.QUEUE_LOOKAHEAD / 1000) && !entry.src) { + // If the start offset is negative, we need to offset the actual buffer. + var offset = Math.abs(Math.min(startOffset, 0)); + + entry.src = AL.currentContext.ctx.createBufferSource(); + entry.src.buffer = entry.buffer; + entry.src.connect(src.gain); + entry.src.start(startTime, offset); + +#if OPENAL_DEBUG + console.log('updateSource queuing buffer ' + i + ' for source ' + idx + ' at ' + startTime + ' (offset by ' + offset + ')'); +#endif + } + + startTime = endTime; + } + }, + + setSourceState: function(src, state) { +#if OPENAL_DEBUG + var idx = AL.currentContext.src.indexOf(src); +#endif + if (state === 0x1012 /* AL_PLAYING */) { + if (src.state !== 0x1013 /* AL_PAUSED */) { + src.state = 0x1012 /* AL_PLAYING */; + // Reset our position. + src.bufferPosition = AL.currentContext.ctx.currentTime; + src.buffersPlayed = 0; +#if OPENAL_DEBUG + console.log('setSourceState resetting and playing source ' + idx); +#endif + } else { + src.state = 0x1012 /* AL_PLAYING */; + // Use the current offset from src.bufferPosition to resume at the correct point. + src.bufferPosition = AL.currentContext.ctx.currentTime - src.bufferPosition; +#if OPENAL_DEBUG + console.log('setSourceState resuming source ' + idx + ' at ' + src.bufferPosition.toFixed(4)); +#endif + } + AL.stopSourceQueue(src); + AL.updateSource(src); + } else if (state === 0x1013 /* AL_PAUSED */) { + if (src.state === 0x1012 /* AL_PLAYING */) { + src.state = 0x1013 /* AL_PAUSED */; + // Store off the current offset to restore with on resume. + src.bufferPosition = AL.currentContext.ctx.currentTime - src.bufferPosition; + AL.stopSourceQueue(src); +#if OPENAL_DEBUG + console.log('setSourceState pausing source ' + idx + ' at ' + src.bufferPosition.toFixed(4)); +#endif + } + } else if (state === 0x1014 /* AL_STOPPED */) { + if (src.state !== 0x1011 /* AL_INITIAL */) { + src.state = 0x1014 /* AL_STOPPED */; + src.buffersPlayed = src.queue.length; + AL.stopSourceQueue(src); +#if OPENAL_DEBUG + console.log('setSourceState stopping source ' + idx); +#endif + } + } else if (state == 0x1011 /* AL_INITIAL */) { + if (src.state !== 0x1011 /* AL_INITIAL */) { + src.state = 0x1011 /* AL_INITIAL */; + src.bufferPosition = 0; + src.buffersPlayed = 0; +#if OPENAL_DEBUG + console.log('setSourceState initializing source ' + idx); +#endif + } + } + }, + + stopSourceQueue: function(src) { + for (var i = 0; i < src.queue.length; i++) { + var entry = src.queue[i]; + if (entry.src) { + entry.src.stop(0); + entry.src = null; + } + } + } }, alcProcessContext: function(context) {}, alcSuspendContext: function(context) {}, @@ -39,11 +160,11 @@ return 0; }, alcDestroyContext: function(context) { // Stop playback, etc - clearInterval(context.interval); + clearInterval(AL.contexts[context - 1].interval); }, alcCloseDevice: function(device) { // Stop playback, etc }, @@ -83,143 +204,19 @@ var context = { ctx: ctx, err: 0, src: [], buf: [], - interval: setInterval(function() { _updateSources(context); }, AL.QUEUE_INTERVAL) + interval: setInterval(function() { AL.updateSources(context); }, AL.QUEUE_INTERVAL) }; AL.contexts.push(context); return AL.contexts.length; } else { return 0; } }, - updateSources__deps: ['updateSource'], - updateSources: function(context) { - for (var i = 0; i < context.src.length; i++) { - _updateSource(context.src[i]); - } - }, - - updateSource__deps: ['setSourceState'], - updateSource: function(src) { -#if OPENAL_DEBUG - var idx = AL.currentContext.src.indexOf(src); -#endif - if (src.state !== 0x1012 /* AL_PLAYING */) { - return; - } - - var currentTime = AL.currentContext.ctx.currentTime; - var startTime = src.bufferPosition; - - for (var i = src.buffersPlayed; i < src.queue.length; i++) { - var entry = src.queue[i]; - - var startOffset = startTime - currentTime; - var endTime = startTime + entry.buffer.duration; - - // Clean up old buffers. - if (currentTime >= endTime) { - // Update our location in the queue. - src.bufferPosition = endTime; - src.buffersPlayed = i + 1; - - // Stop / restart the source when we hit the end. - if (src.buffersPlayed >= src.queue.length) { - if (src.loop) { - _setSourceState(src, 0x1012 /* AL_PLAYING */); - } else { - _setSourceState(src, 0x1014 /* AL_STOPPED */); - } - } - } - // Process all buffers that'll be played before the next tick. - else if (startOffset < (AL.QUEUE_LOOKAHEAD / 1000) && !entry.src) { - // If the start offset is negative, we need to offset the actual buffer. - var offset = Math.abs(Math.min(startOffset, 0)); - - entry.src = AL.currentContext.ctx.createBufferSource(); - entry.src.buffer = entry.buffer; - entry.src.connect(src.gain); - entry.src.start(startTime, offset); - -#if OPENAL_DEBUG - console.log('updateSource queuing buffer ' + i + ' for source ' + idx + ' at ' + startTime + ' (offset by ' + offset + ')'); -#endif - } - - startTime = endTime; - } - }, - - setSourceState__deps: ['updateSource', 'stopSourceQueue'], - setSourceState: function(src, state) { -#if OPENAL_DEBUG - var idx = AL.currentContext.src.indexOf(src); -#endif - if (state === 0x1012 /* AL_PLAYING */) { - if (src.state !== 0x1013 /* AL_PAUSED */) { - src.state = 0x1012 /* AL_PLAYING */; - // Reset our position. - src.bufferPosition = AL.currentContext.ctx.currentTime; - src.buffersPlayed = 0; -#if OPENAL_DEBUG - console.log('setSourceState resetting and playing source ' + idx); -#endif - } else { - src.state = 0x1012 /* AL_PLAYING */; - // Use the current offset from src.bufferPosition to resume at the correct point. - src.bufferPosition = AL.currentContext.ctx.currentTime - src.bufferPosition; -#if OPENAL_DEBUG - console.log('setSourceState resuming source ' + idx + ' at ' + src.bufferPosition.toFixed(4)); -#endif - } - _stopSourceQueue(src); - _updateSource(src); - } else if (state === 0x1013 /* AL_PAUSED */) { - if (src.state === 0x1012 /* AL_PLAYING */) { - src.state = 0x1013 /* AL_PAUSED */; - // Store off the current offset to restore with on resume. - src.bufferPosition = AL.currentContext.ctx.currentTime - src.bufferPosition; - _stopSourceQueue(src); -#if OPENAL_DEBUG - console.log('setSourceState pausing source ' + idx + ' at ' + src.bufferPosition.toFixed(4)); -#endif - } - } else if (state === 0x1014 /* AL_STOPPED */) { - if (src.state !== 0x1011 /* AL_INITIAL */) { - src.state = 0x1014 /* AL_STOPPED */; - src.buffersPlayed = src.queue.length; - _stopSourceQueue(src); -#if OPENAL_DEBUG - console.log('setSourceState stopping source ' + idx); -#endif - } - } else if (state == 0x1011 /* AL_INITIAL */) { - if (src.state !== 0x1011 /* AL_INITIAL */) { - src.state = 0x1011 /* AL_INITIAL */; - src.bufferPosition = 0; - src.buffersPlayed = 0; -#if OPENAL_DEBUG - console.log('setSourceState initializing source ' + idx); -#endif - } - } - }, - - stopSourceQueue: function(src) { - for (var i = 0; i < src.queue.length; i++) { - var entry = src.queue[i]; - if (entry.src) { - entry.src.stop(0); - entry.src = null; - } - } - }, - alGetError: function() { if (!AL.currentContext) { return 0xA004 /* AL_INVALID_OPERATION */; } else { // Reset error on get. @@ -238,11 +235,10 @@ alDeleteSources: function(count, sources) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alDeleteSources called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } for (var i = 0; i < count; ++i) { var sourceIdx = {{{ makeGetValue('sources', 'i*4', 'i32') }}} - 1; delete AL.currentContext.src[sourceIdx]; @@ -252,11 +248,10 @@ alGenSources: function(count, sources) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alGenSources called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } for (var i = 0; i < count; ++i) { var gain = AL.currentContext.ctx.createGain(); gain.connect(AL.currentContext.ctx.destination); @@ -312,11 +307,10 @@ alSourcei: function(source, param, value) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alSourcei called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; if (!src) { #if OPENAL_DEBUG @@ -334,11 +328,11 @@ if (value == 0) { src.queue = []; } else { src.queue = [{ buffer: buffer }]; } - _updateSource(src); + AL.updateSource(src); break; case 0x202 /* AL_SOURCE_RELATIVE */: if (value === 1 /* AL_TRUE */) { if (src.panner) { src.panner = null; @@ -381,11 +375,10 @@ alSourcef: function(source, param, value) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alSourcef called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; if (!src) { #if OPENAL_DEBUG @@ -434,11 +427,10 @@ alSource3f: function(source, param, v1, v2, v3) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alSource3f called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; if (!src) { #if OPENAL_DEBUG @@ -475,11 +467,10 @@ alSourceQueueBuffers: function(source, count, buffers) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alSourceQueueBuffers called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; if (!src) { #if OPENAL_DEBUG @@ -503,20 +494,19 @@ var bufferIdx = {{{ makeGetValue('buffers', 'i*4', 'i32') }}}; var buffer = AL.currentContext.buf[bufferIdx - 1]; src.queue.push({ buffer: buffer, src: null }); } - _updateSource(src); + AL.updateSource(src); }, alSourceUnqueueBuffers__deps: ["updateSource"], alSourceUnqueueBuffers: function(source, count, buffers) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alSourceUnqueueBuffers called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; if (!src) { #if OPENAL_DEBUG @@ -542,20 +532,19 @@ } } src.buffersPlayed--; } - _updateSource(src); + AL.updateSource(src); }, alDeleteBuffers: function(count, buffers) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alDeleteBuffers called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } if (count > AL.currentContext.buf.length) { AL.currentContext.err = 0xA003 /* AL_INVALID_VALUE */; return; @@ -595,11 +584,10 @@ alGenBuffers: function(count, buffers) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alGenBuffers called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } for (var i = 0; i < count; ++i) { AL.currentContext.buf.push(null); {{{ makeSetValue('buffers', 'i*4', 'AL.currentContext.buf.length', 'i32') }}}; @@ -609,11 +597,10 @@ alBufferData: function(buffer, format, data, size, freq) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alBufferData called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } if (buffer > AL.currentContext.buf.length) { #if OPENAL_DEBUG console.error("alBufferData called with an invalid buffer"); @@ -674,71 +661,67 @@ alSourcePlay: function(source) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alSourcePlay called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; if (!src) { #if OPENAL_DEBUG console.error("alSourcePlay called with an invalid source"); #endif AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */; return; } - _setSourceState(src, 0x1012 /* AL_PLAYING */); + AL.setSourceState(src, 0x1012 /* AL_PLAYING */); }, alSourceStop__deps: ['setSourceState'], alSourceStop: function(source) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alSourceStop called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; if (!src) { #if OPENAL_DEBUG console.error("alSourceStop called with an invalid source"); #endif AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */; return; } - _setSourceState(src, 0x1014 /* AL_STOPPED */); + AL.setSourceState(src, 0x1014 /* AL_STOPPED */); }, alSourcePause__deps: ['setSourceState'], alSourcePause: function(source) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alSourcePause called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; if (!src) { #if OPENAL_DEBUG console.error("alSourcePause called with an invalid source"); #endif AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */; return; } - _setSourceState(src, 0x1013 /* AL_PAUSED */); + AL.setSourceState(src, 0x1013 /* AL_PAUSED */); }, alGetSourcei__deps: ['updateSource'], alGetSourcei: function(source, param, value) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alGetSourcei called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; if (!src) { #if OPENAL_DEBUG @@ -752,11 +735,11 @@ // we currently proccess and update a source's buffer queue every // ~QUEUE_INTERVAL milliseconds. However, this interval is not precise, // so we also forcefully update the source when alGetSourcei is queried // to aid in the common scenario of application calling alGetSourcei(AL_BUFFERS_PROCESSED) // to recycle buffers. - _updateSource(src); + AL.updateSource(src); switch (param) { case 0x202 /* AL_SOURCE_RELATIVE */: {{{ makeSetValue('value', '0', 'src.panner ? 1 : 0', 'i32') }}}; break; @@ -798,11 +781,10 @@ alGetSourcef: function(source, param, value) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alGetSourcef called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; if (!src) { #if OPENAL_DEBUG @@ -859,10 +841,9 @@ alListenerfv: function(param, values) { if (!AL.currentContext) { #if OPENAL_DEBUG console.error("alListenerfv called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } switch (param) { case 0x1004 /* AL_POSITION */: AL.currentContext.ctx.listener.setPosition(