diff options
Diffstat (limited to 'src/library_openal.js')
-rw-r--r-- | src/library_openal.js | 505 |
1 files changed, 467 insertions, 38 deletions
diff --git a/src/library_openal.js b/src/library_openal.js index eb152f62..bdbb2dca 100644 --- a/src/library_openal.js +++ b/src/library_openal.js @@ -5,6 +5,10 @@ var LibraryOpenAL = { $AL: { contexts: [], currentContext: null, + + stringCache: {}, + alcStringCache: {}, + QUEUE_INTERVAL: 25, QUEUE_LOOKAHEAD: 100, @@ -170,8 +174,8 @@ var LibraryOpenAL = { }, alcOpenDevice: function(deviceName) { - if (typeof(AudioContext) == "function" || - typeof(webkitAudioContext) == "function") { + if (typeof(AudioContext) !== "undefined" || + typeof(webkitAudioContext) !== "undefined") { return 1; // non-null pointer -- we just simulate one device } else { return 0; @@ -201,12 +205,15 @@ var LibraryOpenAL = { } if (ctx) { + var gain = ctx.createGain(); + gain.connect(ctx.destination); var context = { ctx: ctx, err: 0, src: [], buf: [], - interval: setInterval(function() { AL.updateSources(context); }, AL.QUEUE_INTERVAL) + interval: setInterval(function() { AL.updateSources(context); }, AL.QUEUE_INTERVAL), + gain: gain }; AL.contexts.push(context); return AL.contexts.length; @@ -232,6 +239,42 @@ var LibraryOpenAL = { return _alGetError(); }, + alcGetIntegerv: function(device, param, size, data) { + if (size == 0 || !data) { + AL.currentContext.err = 0xA003 /* AL_INVALID_VALUE */; + return; + } + + switch(param) { + case 0x1000 /* ALC_MAJOR_VERSION */: + {{{ makeSetValue('data', '0', '1', 'i32') }}}; + break; + case 0x1001 /* ALC_MINOR_VERSION */: + {{{ makeSetValue('data', '0', '1', 'i32') }}}; + break; + case 0x1002 /* ALC_ATTRIBUTES_SIZE */: + if (!device) { + AL.currentContext.err = 0xA001 /* ALC_INVALID_DEVICE */; + return 0; + } + {{{ makeSetValue('data', '0', '1', 'i32') }}}; + break; + case 0x1003 /* ALC_ALL_ATTRIBUTES */: + if (!device) { + AL.currentContext.err = 0xA001 /* ALC_INVALID_DEVICE */; + return 0; + } + {{{ makeSetValue('data', '0', '0', 'i32') }}}; + break; + default: +#if OPENAL_DEBUG + console.log("alcGetIntegerv with param " + param + " not implemented yet"); +#endif + AL.currentContext.err = 0xA003 /* ALC_INVALID_ENUM */; + break; + } + }, + alDeleteSources: function(count, sources) { if (!AL.currentContext) { #if OPENAL_DEBUG @@ -254,7 +297,7 @@ var LibraryOpenAL = { } for (var i = 0; i < count; ++i) { var gain = AL.currentContext.ctx.createGain(); - gain.connect(AL.currentContext.ctx.destination); + gain.connect(AL.currentContext.gain); AL.currentContext.src.push({ state: 0x1011 /* AL_INITIAL */, queue: [], @@ -294,6 +337,34 @@ var LibraryOpenAL = { this._velocity = val; if (this.panner) this.panner.setVelocity(val[0], val[1], val[2]); }, + get direction() { + return this._direction || [0, 0, 0]; + }, + set direction(val) { + this._direction = val; + if (this.panner) this.panner.setOrientation(val[0], val[1], val[2]); + }, + get coneOuterGain() { + return this._coneOuterGain || 0.0; + }, + set coneOuterGain(val) { + this._coneOuterGain = val; + if (this.panner) this.panner.coneOuterGain = val; + }, + get coneInnerAngle() { + return this._coneInnerAngle || 360.0; + }, + set coneInnerAngle(val) { + this._coneInnerAngle = val; + if (this.panner) this.panner.coneInnerAngle = val; + }, + get coneOuterAngle() { + return this._coneOuterAngle || 360.0; + }, + set coneOuterAngle(val) { + this._coneOuterAngle = val; + if (this.panner) this.panner.coneOuterAngle = val; + }, gain: gain, panner: null, buffersPlayed: 0, @@ -303,6 +374,18 @@ var LibraryOpenAL = { } }, + alIsSource: function(sourceId) { + if (!AL.currentContext) { + return false; + } + + if (!AL.currentContext.src[sourceId - 1]) { + return false; + } else { + return true; + } + }, + alSourcei__deps: ['updateSource'], alSourcei: function(source, param, value) { if (!AL.currentContext) { @@ -320,6 +403,12 @@ var LibraryOpenAL = { return; } switch (param) { + case 0x1001 /* AL_CONE_INNER_ANGLE */: + src.coneInnerAngle = value; + break; + case 0x1002 /* AL_CONE_OUTER_ANGLE */: + src.coneOuterAngle = value; + break; case 0x1007 /* AL_LOOPING */: src.loop = (value === 1 /* AL_TRUE */); break; @@ -406,12 +495,15 @@ var LibraryOpenAL = { case 0x1021 /* AL_ROLLOFF_FACTOR */: src.rolloffFactor = value; break; - // case 0x1022 /* AL_CONE_OUTER_GAIN */: - // break; - // case 0x1001 /* AL_CONE_INNER_ANGLE */: - // break; - // case 0x1002 /* AL_CONE_OUTER_ANGLE */: - // break; + case 0x1022 /* AL_CONE_OUTER_GAIN */: + src.coneOuterGain = value; + break; + case 0x1001 /* AL_CONE_INNER_ANGLE */: + src.coneInnerAngle = value; + break; + case 0x1002 /* AL_CONE_OUTER_ANGLE */: + src.coneOuterAngle = value; + break; case 0x1020 /* AL_REFERENCE_DISTANCE */: src.refDistance = value; break; @@ -443,6 +535,9 @@ var LibraryOpenAL = { case 0x1004 /* AL_POSITION */: src.position = [v1, v2, v3]; break; + case 0x1005 /* AL_DIRECTION */: + src.direction = [v1, v2, v3]; + break; case 0x1006 /* AL_VELOCITY */: src.velocity = [v1, v2, v3]; break; @@ -594,6 +689,21 @@ var LibraryOpenAL = { } }, + alIsBuffer: function(bufferId) { + if (!AL.currentContext) { + return false; + } + if (bufferId > AL.currentContext.buf.length) { + return false; + } + + if (!AL.currentContext.buf[bufferId - 1]) { + return false; + } else { + return true; + } + }, + alBufferData: function(buffer, format, data, size, freq) { if (!AL.currentContext) { #if OPENAL_DEBUG @@ -633,6 +743,7 @@ var LibraryOpenAL = { } try { AL.currentContext.buf[buffer - 1] = AL.currentContext.ctx.createBuffer(channels, size / (bytes * channels), freq); + AL.currentContext.buf[buffer - 1].bytesPerSample = bytes; } catch (e) { AL.currentContext.err = 0xA003 /* AL_INVALID_VALUE */; return; @@ -657,6 +768,41 @@ var LibraryOpenAL = { } }, + alGetBufferi: function(buffer, param, value) + { + if (!AL.currentContext) { +#if OPENAL_DEBUG + console.error("alGetBufferi called without a valid context"); +#endif + return; + } + var buf = AL.currentContext.buf[buffer - 1]; + if (!buf) { +#if OPENAL_DEBUG + console.error("alGetBufferi called with an invalid buffer"); +#endif + AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */; + return; + } + switch (param) { + case 0x2001 /* AL_FREQUENCY */: + {{{ makeSetValue('value', '0', 'buf.sampleRate', 'i32') }}}; + break; + case 0x2002 /* AL_BITS */: + {{{ makeSetValue('value', '0', 'buf.bytesPerSample * 8', 'i32') }}}; + break; + case 0x2003 /* AL_CHANNELS */: + {{{ makeSetValue('value', '0', 'buf.numberOfChannels', 'i32') }}}; + break; + case 0x2004 /* AL_SIZE */: + {{{ makeSetValue('value', '0', 'buf.length * buf.bytesPerSample * buf.numberOfChannels', 'i32') }}}; + break; + default: + AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */; + break; + } + }, + alSourcePlay__deps: ['setSourceState'], alSourcePlay: function(source) { if (!AL.currentContext) { @@ -743,6 +889,12 @@ var LibraryOpenAL = { case 0x202 /* AL_SOURCE_RELATIVE */: {{{ makeSetValue('value', '0', 'src.panner ? 1 : 0', 'i32') }}}; break; + case 0x1001 /* AL_CONE_INNER_ANGLE */: + {{{ makeSetValue('value', '0', 'src.coneInnerAngle', 'i32') }}}; + break; + case 0x1002 /* AL_CONE_OUTER_ANGLE */: + {{{ makeSetValue('value', '0', 'src.coneOuterAngle', 'i32') }}}; + break; case 0x1009 /* AL_BUFFER */: if (!src.queue.length) { {{{ makeSetValue('value', '0', '0', 'i32') }}}; @@ -809,12 +961,15 @@ var LibraryOpenAL = { case 0x1021 /* AL_ROLLOFF_FACTOR */: {{{ makeSetValue('value', '0', 'src.rolloffFactor', 'float') }}} break; - // case 0x1022 /* AL_CONE_OUTER_GAIN */: - // break; - // case 0x1001 /* AL_CONE_INNER_ANGLE */: - // break; - // case 0x1002 /* AL_CONE_OUTER_ANGLE */: - // break; + case 0x1022 /* AL_CONE_OUTER_GAIN */: + {{{ makeSetValue('value', '0', 'src.coneOuterGain', 'float') }}} + break; + case 0x1001 /* AL_CONE_INNER_ANGLE */: + {{{ makeSetValue('value', '0', 'src.coneInnerAngle', 'float') }}} + break; + case 0x1002 /* AL_CONE_OUTER_ANGLE */: + {{{ makeSetValue('value', '0', 'src.coneOuterAngle', 'float') }}} + break; case 0x1020 /* AL_REFERENCE_DISTANCE */: {{{ makeSetValue('value', '0', 'src.refDistance', 'float') }}} break; @@ -830,6 +985,49 @@ var LibraryOpenAL = { } }, + alGetSourcefv: function(source, param, values) { + if (!AL.currentContext) { +#if OPENAL_DEBUG + console.error("alGetSourcefv called without a valid context"); +#endif + return; + } + var src = AL.currentContext.src[source - 1]; + if (!src) { +#if OPENAL_DEBUG + console.error("alGetSourcefv called with an invalid source"); +#endif + AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */; + return; + } + switch (param) { + case 0x1004 /* AL_POSITION */: + var position = src.position; + {{{ makeSetValue('values', '0', 'position[0]', 'float') }}} + {{{ makeSetValue('values', '4', 'position[1]', 'float') }}} + {{{ makeSetValue('values', '8', 'position[2]', 'float') }}} + break; + case 0x1005 /* AL_DIRECTION */: + var direction = src.direction; + {{{ makeSetValue('values', '0', 'direction[0]', 'float') }}} + {{{ makeSetValue('values', '4', 'direction[1]', 'float') }}} + {{{ makeSetValue('values', '8', 'direction[2]', 'float') }}} + break; + case 0x1006 /* AL_VELOCITY */: + var velocity = src.velocity; + {{{ makeSetValue('values', '0', 'velocity[0]', 'float') }}} + {{{ makeSetValue('values', '4', 'velocity[1]', 'float') }}} + {{{ makeSetValue('values', '8', 'velocity[2]', 'float') }}} + break; + default: +#if OPENAL_DEBUG + console.error("alGetSourcefv with param " + param + " not implemented yet"); +#endif + AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */; + break; + } + }, + alDistanceModel: function(model) { if (model !== 0 /* AL_NONE */) { #if OPENAL_DEBUG @@ -838,6 +1036,136 @@ var LibraryOpenAL = { } }, + alGetListenerf: function(pname, values) { + if (!AL.currentContext) { +#if OPENAL_DEBUG + console.error("alGetListenerf called without a valid context"); +#endif + return; + } + switch (pname) { + case 0x100A /* AL_GAIN */: + {{{ makeSetValue('value', '0', 'AL.currentContext.gain.gain', 'float') }}} + break; + default: +#if OPENAL_DEBUG + console.error("alGetListenerf with param " + pname + " not implemented yet"); +#endif + AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */; + break; + } + + }, + + alGetListenerfv: function(pname, values) { + if (!AL.currentContext) { +#if OPENAL_DEBUG + console.error("alGetListenerfv called without a valid context"); +#endif + return; + } + switch (pname) { + case 0x1004 /* AL_POSITION */: + var position = AL.currentContext.ctx.listener._position || [0,0,0]; + {{{ makeSetValue('values', '0', 'position[0]', 'float') }}} + {{{ makeSetValue('values', '4', 'position[1]', 'float') }}} + {{{ makeSetValue('values', '8', 'position[2]', 'float') }}} + break; + case 0x1006 /* AL_VELOCITY */: + var velocity = AL.currentContext.ctx.listener._velocity || [0,0,0]; + {{{ makeSetValue('values', '0', 'velocity[0]', 'float') }}} + {{{ makeSetValue('values', '4', 'velocity[1]', 'float') }}} + {{{ makeSetValue('values', '8', 'velocity[2]', 'float') }}} + break; + case 0x100F /* AL_ORIENTATION */: + var orientation = AL.currentContext.ctx.listener._orientation || [0,0,0,0,0,0]; + {{{ makeSetValue('values', '0', 'orientation[0]', 'float') }}} + {{{ makeSetValue('values', '4', 'orientation[1]', 'float') }}} + {{{ makeSetValue('values', '8', 'orientation[2]', 'float') }}} + {{{ makeSetValue('values', '12', 'orientation[3]', 'float') }}} + {{{ makeSetValue('values', '16', 'orientation[4]', 'float') }}} + {{{ makeSetValue('values', '20', 'orientation[5]', 'float') }}} + break; + default: +#if OPENAL_DEBUG + console.error("alGetListenerfv with param " + pname + " not implemented yet"); +#endif + AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */; + break; + } + }, + + alGetListeneri: function(pname, value) { + if (!AL.currentContext) { +#if OPENAL_DEBUG + console.error("alGetListeneri called without a valid context"); +#endif + return; + } + switch (pname) { + default: +#if OPENAL_DEBUG + console.error("alGetListeneri with param " + pname + " not implemented yet"); +#endif + AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */; + break; + } + }, + + alListenerf: function(param, value) { + if (!AL.currentContext) { +#if OPENAL_DEBUG + console.error("alListenerf called without a valid context"); +#endif + return; + } + switch (param) { + case 0x100A /* AL_GAIN */: + AL.currentContext.gain.value = value; + break; + default: +#if OPENAL_DEBUG + console.error("alListenerf with param " + param + " not implemented yet"); +#endif + AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */; + break; + } + }, + + alEnable: function(param) { + if (!AL.currentContext) { +#if OPENAL_DEBUG + console.error("alEnable called without a valid context"); +#endif + return; + } + switch (param) { + default: +#if OPENAL_DEBUG + console.error("alEnable with param " + param + " not implemented yet"); +#endif + AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */; + break; + } + }, + + alDisable: function(param) { + if (!AL.currentContext) { +#if OPENAL_DEBUG + console.error("alDisable called without a valid context"); +#endif + return; + } + switch (pname) { + default: +#if OPENAL_DEBUG + console.error("alDisable with param " + param + " not implemented yet"); +#endif + AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */; + break; + } + }, + alListenerfv: function(param, values) { if (!AL.currentContext) { #if OPENAL_DEBUG @@ -847,32 +1175,32 @@ var LibraryOpenAL = { } switch (param) { case 0x1004 /* AL_POSITION */: - AL.currentContext.ctx.listener.setPosition( - {{{ makeGetValue('values', '0', 'float') }}}, - {{{ makeGetValue('values', '4', 'float') }}}, - {{{ makeGetValue('values', '8', 'float') }}} - ); + var x = {{{ makeGetValue('values', '0', 'float') }}}; + var y = {{{ makeGetValue('values', '4', 'float') }}}; + var z = {{{ makeGetValue('values', '8', 'float') }}}; + AL.currentContext.ctx.listener._position = [x, y, z]; + AL.currentContext.ctx.listener.setPosition(x, y, z); break; case 0x1006 /* AL_VELOCITY */: - AL.currentContext.ctx.listener.setVelocity( - {{{ makeGetValue('values', '0', 'float') }}}, - {{{ makeGetValue('values', '4', 'float') }}}, - {{{ makeGetValue('values', '8', 'float') }}} - ); + var x = {{{ makeGetValue('values', '0', 'float') }}}; + var y = {{{ makeGetValue('values', '4', 'float') }}}; + var z = {{{ makeGetValue('values', '8', 'float') }}}; + AL.currentContext.ctx.listener._velocity = [x, y, z]; + AL.currentContext.ctx.listener.setVelocity(x, y, z); break; case 0x100F /* AL_ORIENTATION */: - AL.currentContext.ctx.listener.setOrientation( - {{{ makeGetValue('values', '0', 'float') }}}, - {{{ makeGetValue('values', '4', 'float') }}}, - {{{ makeGetValue('values', '8', 'float') }}}, - {{{ makeGetValue('values', '12', 'float') }}}, - {{{ makeGetValue('values', '16', 'float') }}}, - {{{ makeGetValue('values', '20', 'float') }}} - ); + var x = {{{ makeGetValue('values', '0', 'float') }}}; + var y = {{{ makeGetValue('values', '4', 'float') }}}; + var z = {{{ makeGetValue('values', '8', 'float') }}}; + var x2 = {{{ makeGetValue('values', '12', 'float') }}}; + var y2 = {{{ makeGetValue('values', '16', 'float') }}}; + var z2 = {{{ makeGetValue('values', '20', 'float') }}}; + AL.currentContext.ctx.listener._orientation = [x, y, z, x2, y2, z2]; + AL.currentContext.ctx.listener.setOrientation(x, y, z, x2, y2, z2); break; default: #if OPENAL_DEBUG - console.log("alListenerfv with param " + param + " not implemented yet"); + console.error("alListenerfv with param " + param + " not implemented yet"); #endif AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */; break; @@ -888,15 +1216,116 @@ var LibraryOpenAL = { }, alGetString: function(param) { - return allocate(intArrayFromString('NA'), 'i8', ALLOC_NORMAL); + if (AL.stringCache[param]) return AL.stringCache[param]; + var ret; + switch (param) { + case 0 /* AL_NO_ERROR */: + ret = 'No Error'; + break; + case 0xA001 /* AL_INVALID_NAME */: + ret = 'Invalid Name'; + break; + case 0xA002 /* AL_INVALID_ENUM */: + ret = 'Invalid Enum'; + break; + case 0xA003 /* AL_INVALID_VALUE */: + ret = 'Invalid Value'; + break; + case 0xA004 /* AL_INVALID_OPERATION */: + ret = 'Invalid Operation'; + break; + case 0xA005 /* AL_OUT_OF_MEMORY */: + ret = 'Out of Memory'; + break; + case 0xB001 /* AL_VENDOR */: + ret = 'Emscripten'; + break; + case 0xB002 /* AL_VERSION */: + ret = '1.1'; + break; + case 0xB003 /* AL_RENDERER */: + ret = 'WebAudio'; + break; + case 0xB004 /* AL_EXTENSIONS */: + ret = ''; + break; + default: + AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */; + return 0; + } + + ret = allocate(intArrayFromString(ret), 'i8', ALLOC_NORMAL); + + AL.stringCache[param] = ret; + + return ret; }, alGetProcAddress: function(fname) { return 0; }, - alcGetString: function(param) { - return allocate(intArrayFromString('NA'), 'i8', ALLOC_NORMAL); + alcGetString: function(device, param) { + if (AL.alcStringCache[param]) return AL.alcStringCache[param]; + var ret; + switch (param) { + case 0 /* ALC_NO_ERROR */: + ret = 'No Error'; + break; + case 0xA001 /* ALC_INVALID_DEVICE */: + ret = 'Invalid Device'; + break; + case 0xA002 /* ALC_INVALID_CONTEXT */: + ret = 'Invalid Context'; + break; + case 0xA003 /* ALC_INVALID_ENUM */: + ret = 'Invalid Enum'; + break; + case 0xA004 /* ALC_INVALID_VALUE */: + ret = 'Invalid Value'; + break; + case 0xA005 /* ALC_OUT_OF_MEMORY */: + ret = 'Out of Memory'; + break; + case 0x1004 /* ALC_DEFAULT_DEVICE_SPECIFIER */: + if (typeof(AudioContext) == "function" || + typeof(webkitAudioContext) == "function") { + ret = 'Device'; + } else { + return 0; + } + break; + case 0x1005 /* ALC_DEVICE_SPECIFIER */: + if (typeof(AudioContext) == "function" || + typeof(webkitAudioContext) == "function") { + ret = 'Device\0'; + } else { + ret = '\0'; + } + break; + case 0x311 /* ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER */: + return 0; + break; + case 0x310 /* ALC_CAPTURE_DEVICE_SPECIFIER */: + ret = '\0' + break; + case 0x1006 /* ALC_EXTENSIONS */: + if (!device) { + AL.currentContext.err = 0xA001 /* ALC_INVALID_DEVICE */; + return 0; + } + ret = ''; + break; + default: + AL.currentContext.err = 0xA003 /* ALC_INVALID_ENUM */; + return 0; + } + + ret = allocate(intArrayFromString(ret), 'i8', ALLOC_NORMAL); + + AL.alcStringCache[param] = ret; + + return ret; }, alcGetProcAddress: function(device, fname) { |