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(