From 93993c5e3aa6872a86f359a3fd629dd35989d001 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sun, 27 Feb 2022 17:04:01 -0600 Subject: [PATCH] added OpenAL module --- include/onyx_library.h | 2 +- modules/openal/build.sh | 3 + modules/openal/module.onyx | 557 ++++++++++++++++++++++++++++++++++ modules/openal/onyx_openal.c | 240 +++++++++++++++ modules/openal/onyx_openal.so | Bin 0 -> 86464 bytes 5 files changed, 801 insertions(+), 1 deletion(-) create mode 100644 modules/openal/build.sh create mode 100644 modules/openal/module.onyx create mode 100644 modules/openal/onyx_openal.c create mode 100755 modules/openal/onyx_openal.so diff --git a/include/onyx_library.h b/include/onyx_library.h index c0c0335a..4361c753 100644 --- a/include/onyx_library.h +++ b/include/onyx_library.h @@ -97,4 +97,4 @@ typedef struct WasmFuncDefinition { #define PTR WASM_I32 #endif -#define ONYX_PTR(p) (p != 0 ? (runtime->wasm_memory_data(runtime->wasm_memory) + p) : NULL) +#define ONYX_PTR(p) ((void*) (p != 0 ? (runtime->wasm_memory_data(runtime->wasm_memory) + p) : NULL)) diff --git a/modules/openal/build.sh b/modules/openal/build.sh new file mode 100644 index 00000000..32d64a11 --- /dev/null +++ b/modules/openal/build.sh @@ -0,0 +1,3 @@ +#/bin/sh + +gcc -shared -fPIC modules/openal/onyx_openal.c -lopenal -I include -I lib/common/include -o ./modules/openal/onyx_openal.so \ No newline at end of file diff --git a/modules/openal/module.onyx b/modules/openal/module.onyx new file mode 100644 index 00000000..353e3629 --- /dev/null +++ b/modules/openal/module.onyx @@ -0,0 +1,557 @@ +package openal + +#library "onyx_openal" + +ALCdevice :: #distinct u64 +ALCcontext :: #distinct u64 +ALCextfunc :: #distinct u64 + +#foreign "onyx_openal" { + alGenBuffers :: (n: i32, buffers: ^u32) -> void --- + alDeleteBuffers :: (n: i32, buffers: ^u32) -> void --- + alIsBuffer :: (buffer: u32) -> bool --- + alBufferData :: (buffer: u32, format: i32, data: rawptr, size: i32, freq: i32) -> void --- + alBufferf :: (buffer: u32, param: i32, value: f32) -> void --- + alBuffer3f :: (buffer: u32, param: i32, v1, v2, v3: f32) -> void --- + alBufferfv :: (buffer: u32, param: i32, values: ^f32) -> void --- + alBufferi :: (buffer: u32, param: i32, value: i32) -> void --- + alBuffer3i :: (buffer: u32, param: i32, v1, v2, v3: i32) -> void --- + alBufferiv :: (buffer: u32, param: i32, values: ^i32) -> void --- + alGetBufferf :: (buffer: u32, param: i32, value: ^f32) -> void --- + alGetBuffer3f :: (buffer: u32, param: i32, v1, v2, v3: ^f32) -> void --- + alGetBufferfv :: (buffer: u32, param: i32, values: ^f32) -> void --- + alGetBufferi :: (buffer: u32, param: i32, value: ^i32) -> void --- + alGetBuffer3i :: (buffer: u32, param: i32, v1, v2, v3: ^i32) -> void --- + alGetBufferiv :: (buffer: u32, param: i32, values: ^i32) -> void --- + + alGenSources :: (n: i32, sources: ^u32) -> void --- + alDeleteSources :: (n: i32, sources: ^u32) -> void --- + alIsSource :: (source: u32) -> bool --- + alSourcef :: (source: u32, param: i32, value: f32) -> void --- + alSource3f :: (source: u32, param: i32, v1, v2, v3: f32) -> void --- + alSourcefv :: (source: u32, param: i32, values: ^f32) -> void --- + alSourcei :: (source: u32, param: i32, value: i32) -> void --- + alSource3i :: (source: u32, param: i32, v1, v2, v3: i32) -> void --- + alSourceiv :: (source: u32, param: i32, values: ^i32) -> void --- + alGetSourcef :: (source: u32, param: i32, value: ^f32) -> void --- + alGetSource3f :: (source: u32, param: i32, v1, v2, v3: ^f32) -> void --- + alGetSourcefv :: (source: u32, param: i32, values: ^f32) -> void --- + alGetSourcei :: (source: u32, param: i32, value: ^i32) -> void --- + alGetSource3i :: (source: u32, param: i32, v1, v2, v3: ^i32) -> void --- + alGetSourceiv :: (source: u32, param: i32, values: ^i32) -> void --- + alSourcePlay :: (source: u32) -> void --- + alSourcePlayv :: (n: i32, sources: ^u32) -> void --- + alSourcePause :: (source: u32) -> void --- + alSourcePausev :: (n: i32, sources: ^u32) -> void --- + alSourceStop :: (source: u32) -> void --- + alSourceStopv :: (n: i32, sources: ^u32) -> void --- + alSourceRewind :: (source: u32) -> void --- + alSourceRewindv :: (n: i32, sources: ^u32) -> void --- + alSourceQueueBuffers :: (source: u32, n: i32, buffers: ^u32) -> void --- + alSourceUnqueueBuffers :: (source: u32, n: i32, buffers: ^u32) -> void --- + + alListenerf :: (param: i32, value: f32) -> void --- + alListener3f :: (param: i32, v1, v2, v3: f32) -> void --- + alListenerfv :: (param: i32, values: ^f32) -> void --- + alListeneri :: (param: i32, value: i32) -> void --- + alListener3i :: (param: i32, v1, v2, v3: i32) -> void --- + alListeneriv :: (param: i32, values: ^i32) -> void --- + alGetListenerf :: (param: i32, value: ^f32) -> void --- + alGetListener3f :: (param: i32, v1, v2, v3: ^f32) -> void --- + alGetListenerfv :: (param: i32, values: ^f32) -> void --- + alGetListeneri :: (param: i32, value: ^i32) -> void --- + alGetListener3i :: (param: i32, v1, v2, v3: ^i32) -> void --- + alGetListeneriv :: (param: i32, values: ^i32) -> void --- + + alEnable :: (capability: i32) -> void --- + alDisable :: (capability: i32) -> void --- + alIsEnabled :: (capability: i32) -> bool --- + alGetBoolean :: (param: i32) -> bool --- + alGetDouble :: (param: i32) -> f64 --- + alGetFloat :: (param: i32) -> f32 --- + alGetInteger :: (param: i32) -> i32 --- + alGetBooleanv :: (param: i32, data: ^bool) -> void --- + alGetDoublev :: (param: i32, data: ^f64) -> void --- + alGetFloatv :: (param: i32, data: ^f32) -> void --- + alGetIntegerv :: (param: i32, data: ^i32) -> void --- + alDistanceModel :: (value: i32) -> void --- + alDopplerFactor :: (value: f32) -> void --- + alSpeedOfSound :: (value: f32) -> void --- + + alGetError :: () -> i32 --- + + alcCreateContext :: (device: ALCdevice, attrlist: ^i32) -> ALCcontext --- + alcMakeContextCurrent :: (context: ALCcontext) -> bool --- + alcProcessContext :: (context: ALCcontext) -> void --- + alcSuspendContext :: (context: ALCcontext) -> void --- + alcDestroyContext :: (context: ALCcontext) -> void --- + alcGetCurrentContext :: () -> ALCcontext --- + alcGetContextsDevice :: (context: ALCcontext) -> ALCdevice --- + alcGetError :: (device: ALCdevice) -> i32 --- + + alcOpenDevice :: (name: cstr) -> ALCdevice --- + alcCloseDevice :: (device: ALCdevice) -> bool --- + + alcIsExtensionPresent :: (device: ALCdevice, extName: cstr) -> bool --- + alcGetProcAddress :: (device: ALCdevice, funcName: cstr) -> ALCextfunc --- + alcGetEnumValue :: (device: ALCdevice, enumName: cstr) -> i32 --- + alcGetIntegerv :: (device: ALCdevice, param: i32, size: i32, data: ^i32) -> void --- + + alcCaptureOpenDevice :: (name: cstr, freq: u32, format: i32, buffersize: i32) -> ALCdevice --- + alcCaptureCloseDevice :: (device: ALCdevice) -> bool --- + alcCaptureStart :: (device: ALCdevice) -> void --- + alcCaptureStop :: (device: ALCdevice) -> void --- + alcCaptureSamples :: (device: ALCdevice, buf: rawptr, samples: i32) -> void --- + + // This returns a C-allocated string, which is not supported at the moment. + // alGetString :: (device: ALCdevice, param:i32) -> cstr --- + // alcGetString :: (device: ALCdevice, param:i32) -> cstr --- +} + +AL_FALSE :: 0 + +AL_TRUE :: 1 + + +/** + * Relative source. + * Type: ALboolean + * Range: [AL_TRUE, AL_FALSE] + * Default: AL_FALSE + * + * Specifies if the Source has relative coordinates. + */ +AL_SOURCE_RELATIVE :: 0x202 + + +/** + * Inner cone angle, in degrees. + * Type: ALint, ALfloat + * Range: [0 - 360] + * Default: 360 + * + * The angle covered by the inner cone, where the source will not attenuate. + */ +AL_CONE_INNER_ANGLE :: 0x1001 + +/** + * Outer cone angle, in degrees. + * Range: [0 - 360] + * Default: 360 + * + * The angle covered by the outer cone, where the source will be fully + * attenuated. + */ +AL_CONE_OUTER_ANGLE :: 0x1002 + +/** + * Source pitch. + * Type: ALfloat + * Range: [0.5 - 2.0] + * Default: 1.0 + * + * A multiplier for the frequency (sample rate) of the source's buffer. + */ +AL_PITCH :: 0x1003 + +/** + * Source or listener position. + * Type: ALfloat[3], ALint[3] + * Default: {0, 0, 0} + * + * The source or listener location in three dimensional space. + * + * OpenAL, like OpenGL, uses a right handed coordinate system, where in a + * frontal default view X (thumb) points right, Y points up (index finger), and + * Z points towards the viewer/camera (middle finger). + * + * To switch from a left handed coordinate system, flip the sign on the Z + * coordinate. + */ +AL_POSITION :: 0x1004 + +/** + * Source direction. + * Type: ALfloat[3], ALint[3] + * Default: {0, 0, 0} + * + * Specifies the current direction in local space. + * A zero-length vector specifies an omni-directional source (cone is ignored). + */ +AL_DIRECTION :: 0x1005 + +/** + * Source or listener velocity. + * Type: ALfloat[3], ALint[3] + * Default: {0, 0, 0} + * + * Specifies the current velocity in local space. + */ +AL_VELOCITY :: 0x1006 + +/** + * Source looping. + * Type: ALboolean + * Range: [AL_TRUE, AL_FALSE] + * Default: AL_FALSE + * + * Specifies whether source is looping. + */ +AL_LOOPING :: 0x1007 + +/** + * Source buffer. + * Type: ALuint + * Range: any valid Buffer. + * + * Specifies the buffer to provide sound samples. + */ +AL_BUFFER :: 0x1009 + +/** + * Source or listener gain. + * Type: ALfloat + * Range: [0.0 - ] + * + * A value of 1.0 means unattenuated. Each division by 2 equals an attenuation + * of about -6dB. Each multiplicaton by 2 equals an amplification of about + * +6dB. + * + * A value of 0.0 is meaningless with respect to a logarithmic scale; it is + * silent. + */ +AL_GAIN :: 0x100A + +/** + * Minimum source gain. + * Type: ALfloat + * Range: [0.0 - 1.0] + * + * The minimum gain allowed for a source, after distance and cone attenation is + * applied (if applicable). + */ +AL_MIN_GAIN :: 0x100D + +/** + * Maximum source gain. + * Type: ALfloat + * Range: [0.0 - 1.0] + * + * The maximum gain allowed for a source, after distance and cone attenation is + * applied (if applicable). + */ +AL_MAX_GAIN :: 0x100E + +/** + * Listener orientation. + * Type: ALfloat[6] + * Default: {0.0, 0.0, -1.0, 0.0, 1.0, 0.0} + * + * Effectively two three dimensional vectors. The first vector is the front (or + * "at") and the second is the top (or "up"). + * + * Both vectors are in local space. + */ +AL_ORIENTATION :: 0x100F + +/** + * Source state (query only). + * Type: ALint + * Range: [AL_INITIAL, AL_PLAYING, AL_PAUSED, AL_STOPPED] + */ +AL_SOURCE_STATE :: 0x1010 + +/** Source state value. */ +AL_INITIAL :: 0x1011 +AL_PLAYING :: 0x1012 +AL_PAUSED :: 0x1013 +AL_STOPPED :: 0x1014 + +/** + * Source Buffer Queue size (query only). + * Type: ALint + * + * The number of buffers queued using alSourceQueueBuffers, minus the buffers + * removed with alSourceUnqueueBuffers. + */ +AL_BUFFERS_QUEUED :: 0x1015 + +/** + * Source Buffer Queue processed count (query only). + * Type: ALint + * + * The number of queued buffers that have been fully processed, and can be + * removed with alSourceUnqueueBuffers. + * + * Looping sources will never fully process buffers because they will be set to + * play again for when the source loops. + */ +AL_BUFFERS_PROCESSED :: 0x1016 + +/** + * Source reference distance. + * Type: ALfloat + * Range: [0.0 - ] + * Default: 1.0 + * + * The distance in units that no attenuation occurs. + * + * At 0.0, no distance attenuation ever occurs on non-linear attenuation models. + */ +AL_REFERENCE_DISTANCE :: 0x1020 + +/** + * Source rolloff factor. + * Type: ALfloat + * Range: [0.0 - ] + * Default: 1.0 + * + * Multiplier to exaggerate or diminish distance attenuation. + * + * At 0.0, no distance attenuation ever occurs. + */ +AL_ROLLOFF_FACTOR :: 0x1021 + +/** + * Outer cone gain. + * Type: ALfloat + * Range: [0.0 - 1.0] + * Default: 0.0 + * + * The gain attenuation applied when the listener is outside of the source's + * outer cone. + */ +AL_CONE_OUTER_GAIN :: 0x1022 + +/** + * Source maximum distance. + * Type: ALfloat + * Range: [0.0 - ] + * Default: +inf + * + * The distance above which the source is not attenuated any further with a + * clamped distance model, or where attenuation reaches 0.0 gain for linear + * distance models with a default rolloff factor. + */ +AL_MAX_DISTANCE :: 0x1023 + +/** Source buffer position, in seconds */ +AL_SEC_OFFSET :: 0x1024 +/** Source buffer position, in sample frames */ +AL_SAMPLE_OFFSET :: 0x1025 +/** Source buffer position, in bytes */ +AL_BYTE_OFFSET :: 0x1026 + +/** + * Source type (query only). + * Type: ALint + * Range: [AL_STATIC, AL_STREAMING, AL_UNDETERMINED] + * + * A Source is Static if a Buffer has been attached using AL_BUFFER. + * + * A Source is Streaming if one or more Buffers have been attached using + * alSourceQueueBuffers. + * + * A Source is Undetermined when it has the NULL buffer attached using + * AL_BUFFER. + */ +AL_SOURCE_TYPE :: 0x1027 + +/** Source type value. */ +AL_STATIC :: 0x1028 +AL_STREAMING :: 0x1029 +AL_UNDETERMINED :: 0x1030 + +/** Buffer format specifier. */ +AL_FORMAT_MONO8 :: 0x1100 +AL_FORMAT_MONO16 :: 0x1101 +AL_FORMAT_STEREO8 :: 0x1102 +AL_FORMAT_STEREO16 :: 0x1103 + +/** Buffer frequency (query only). */ +AL_FREQUENCY :: 0x2001 +/** Buffer bits per sample (query only). */ +AL_BITS :: 0x2002 +/** Buffer channel count (query only). */ +AL_CHANNELS :: 0x2003 +/** Buffer data size (query only). */ +AL_SIZE :: 0x2004 + +/** + * Buffer state. + * + * Not for public use. + */ +AL_UNUSED :: 0x2010 +AL_PENDING :: 0x2011 +AL_PROCESSED :: 0x2012 + + +/** No error. */ +AL_NO_ERROR :: 0 + +/** Invalid name paramater passed to AL call. */ +AL_INVALID_NAME :: 0xA001 + +/** Invalid enum parameter passed to AL call. */ +AL_INVALID_ENUM :: 0xA002 + +/** Invalid value parameter passed to AL call. */ +AL_INVALID_VALUE :: 0xA003 + +/** Illegal AL call. */ +AL_INVALID_OPERATION :: 0xA004 + +/** Not enough memory. */ +AL_OUT_OF_MEMORY :: 0xA005 + + +/** Context string: Vendor ID. */ +AL_VENDOR :: 0xB001 +/** Context string: Version. */ +AL_VERSION :: 0xB002 +/** Context string: Renderer ID. */ +AL_RENDERER :: 0xB003 +/** Context string: Space-separated extension list. */ +AL_EXTENSIONS :: 0xB004 + + +/** + * Doppler scale. + * Type: ALfloat + * Range: [0.0 - ] + * Default: 1.0 + * + * Scale for source and listener velocities. + */ +AL_DOPPLER_FACTOR :: 0xC000 + +/** + * Doppler velocity (deprecated). + * + * A multiplier applied to the Speed of Sound. + */ +AL_DOPPLER_VELOCITY :: 0xC001 + +/** + * Speed of Sound, in units per second. + * Type: ALfloat + * Range: [0.0001 - ] + * Default: 343.3 + * + * The speed at which sound waves are assumed to travel, when calculating the + * doppler effect. + */ +AL_SPEED_OF_SOUND :: 0xC003 + +/** + * Distance attenuation model. + * Type: ALint + * Range: [AL_NONE, AL_INVERSE_DISTANCE, AL_INVERSE_DISTANCE_CLAMPED, + * AL_LINEAR_DISTANCE, AL_LINEAR_DISTANCE_CLAMPED, + * AL_EXPONENT_DISTANCE, AL_EXPONENT_DISTANCE_CLAMPED] + * Default: AL_INVERSE_DISTANCE_CLAMPED + * + * The model by which sources attenuate with distance. + * + * None - No distance attenuation. + * Inverse - Doubling the distance halves the source gain. + * Linear - Linear gain scaling between the reference and max distances. + * Exponent - Exponential gain dropoff. + * + * Clamped variations work like the non-clamped counterparts, except the + * distance calculated is clamped between the reference and max distances. + */ +AL_DISTANCE_MODEL :: 0xD000 + +/** Distance model value. */ +AL_INVERSE_DISTANCE :: 0xD001 +AL_INVERSE_DISTANCE_CLAMPED :: 0xD002 +AL_LINEAR_DISTANCE :: 0xD003 +AL_LINEAR_DISTANCE_CLAMPED :: 0xD004 +AL_EXPONENT_DISTANCE :: 0xD005 +AL_EXPONENT_DISTANCE_CLAMPED :: 0xD006 + + + +/** Context attribute: Hz. */ +ALC_FREQUENCY :: 0x1007 + +/** Context attribute: Hz. */ +ALC_REFRESH :: 0x1008 + +/** Context attribute: AL_TRUE or AL_FALSE. */ +ALC_SYNC :: 0x1009 + +/** Context attribute: requested Mono (3D) Sources. */ +ALC_MONO_SOURCES :: 0x1010 + +/** Context attribute: requested Stereo Sources. */ +ALC_STEREO_SOURCES :: 0x1011 + +/** No error. */ +ALC_NO_ERROR :: 0 + +/** Invalid device handle. */ +ALC_INVALID_DEVICE :: 0xA001 + +/** Invalid context handle. */ +ALC_INVALID_CONTEXT :: 0xA002 + +/** Invalid enum parameter passed to an ALC call. */ +ALC_INVALID_ENUM :: 0xA003 + +/** Invalid value parameter passed to an ALC call. */ +ALC_INVALID_VALUE :: 0xA004 + +/** Out of memory. */ +ALC_OUT_OF_MEMORY :: 0xA005 + + +/** Runtime ALC version. */ +ALC_MAJOR_VERSION :: 0x1000 +ALC_MINOR_VERSION :: 0x1001 + +/** Context attribute list properties. */ +ALC_ATTRIBUTES_SIZE :: 0x1002 +ALC_ALL_ATTRIBUTES :: 0x1003 + +/** String for the default device specifier. */ +ALC_DEFAULT_DEVICE_SPECIFIER :: 0x1004 +/** + * String for the given device's specifier. + * + * If device handle is NULL, it is instead a null-char separated list of + * strings of known device specifiers (list ends with an empty string). + */ +ALC_DEVICE_SPECIFIER :: 0x1005 +/** String for space-separated list of ALC extensions. */ +ALC_EXTENSIONS :: 0x1006 + + +/** Capture extension */ +ALC_EXT_CAPTURE :: 1 +/** + * String for the given capture device's specifier. + * + * If device handle is NULL, it is instead a null-char separated list of + * strings of known capture device specifiers (list ends with an empty string). + */ +ALC_CAPTURE_DEVICE_SPECIFIER :: 0x310 +/** String for the default capture device specifier. */ +ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER :: 0x311 +/** Number of sample frames available for capture. */ +ALC_CAPTURE_SAMPLES :: 0x312 + + +/** Enumerate All extension */ +ALC_ENUMERATE_ALL_EXT :: 1 +/** String for the default extended device specifier. */ +ALC_DEFAULT_ALL_DEVICES_SPECIFIER :: 0x1012 +/** + * String for the given extended device's specifier. + * + * If device handle is NULL, it is instead a null-char separated list of + * strings of known extended device specifiers (list ends with an empty string). + */ +ALC_ALL_DEVICES_SPECIFIER :: 0x1013 diff --git a/modules/openal/onyx_openal.c b/modules/openal/onyx_openal.c new file mode 100644 index 00000000..52d2673e --- /dev/null +++ b/modules/openal/onyx_openal.c @@ -0,0 +1,240 @@ +#define ONYX_LIBRARY_NAME onyx_openal +#include "onyx_library.h" +#include +#include + +#define P(i, k) (params->data[i].of.k) + +ONYX_DEF(alGenBuffers, (INT, PTR), ()) { + alGenBuffers(params->data[0].of.i32, ONYX_PTR(params->data[1].of.i32)); + return NULL; +} + +ONYX_DEF(alDeleteBuffers, (INT, PTR), ()) { + alDeleteBuffers(params->data[0].of.i32, ONYX_PTR(params->data[1].of.i32)); + return NULL; +} + +ONYX_DEF(alIsBuffer, (INT), (BOOL)) { + results->data[0] = WASM_I32_VAL(alIsBuffer(params->data[0].of.i32)); + return NULL; +} + +ONYX_DEF(alBufferData, (INT, INT, PTR, INT, INT), ()) { + alBufferData( + params->data[0].of.i32, + params->data[1].of.i32, + ONYX_PTR(params->data[2].of.i32), + params->data[3].of.i32, + params->data[4].of.i32); + return NULL; +} + +ONYX_DEF(alBufferf, (INT, INT, FLOAT), ()) { alBufferf(P(0, i32), P(1, i32), P(2, f32)); return NULL; } +ONYX_DEF(alBuffer3f, (INT, INT, FLOAT, FLOAT, FLOAT), ()) { alBuffer3f(P(0, i32), P(1, i32), P(2, f32), P(3, f32), P(4, f32)); return NULL; } +ONYX_DEF(alBufferfv, (INT, INT, PTR), ()) { alBufferfv(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } +ONYX_DEF(alBufferi, (INT, INT, INT), ()) { alBufferi(P(0, i32), P(1, i32), P(2, i32)); return NULL; } +ONYX_DEF(alBuffer3i, (INT, INT, INT, INT, INT), ()) { alBuffer3i(P(0, i32), P(1, i32), P(2, i32), P(3, i32), P(4, i32)); return NULL; } +ONYX_DEF(alBufferiv, (INT, INT, PTR), ()) { alBufferiv(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } +ONYX_DEF(alGetBufferf, (INT, INT, PTR), ()) { alGetBufferf(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } +ONYX_DEF(alGetBuffer3f, (INT, INT, PTR, PTR, PTR), ()) { alGetBuffer3f(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32)), ONYX_PTR(P(3, i32)), ONYX_PTR(P(4, i32))); return NULL; } +ONYX_DEF(alGetBufferfv, (INT, INT, PTR), ()) { alGetBufferfv(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } +ONYX_DEF(alGetBufferi, (INT, INT, PTR), ()) { alGetBufferi(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } +ONYX_DEF(alGetBuffer3i, (INT, INT, PTR, PTR, PTR), ()) { alGetBuffer3i(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32)), ONYX_PTR(P(3, i32)), ONYX_PTR(P(4, i32))); return NULL; } +ONYX_DEF(alGetBufferiv, (INT, INT, PTR), ()) { alGetBufferiv(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } + +ONYX_DEF(alGenSources, (INT, PTR), ()) { + alGenSources(params->data[0].of.i32, ONYX_PTR(params->data[1].of.i32)); + return NULL; +} + +ONYX_DEF(alDeleteSources, (INT, PTR), ()) { + alDeleteSources(params->data[0].of.i32, ONYX_PTR(params->data[1].of.i32)); + return NULL; +} + +ONYX_DEF(alIsSource, (INT), (BOOL)) { + results->data[0] = WASM_I32_VAL(alIsSource(params->data[0].of.i32)); + return NULL; +} + +ONYX_DEF(alSourcef, (INT, INT, FLOAT), ()) { alSourcef(P(0, i32), P(1, i32), P(2, f32)); return NULL; } +ONYX_DEF(alSource3f, (INT, INT, FLOAT, FLOAT, FLOAT), ()) { alSource3f(P(0, i32), P(1, i32), P(2, f32), P(3, f32), P(4, f32)); return NULL; } +ONYX_DEF(alSourcefv, (INT, INT, PTR), ()) { alSourcefv(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } +ONYX_DEF(alSourcei, (INT, INT, INT), ()) { alSourcei(P(0, i32), P(1, i32), P(2, i32)); return NULL; } +ONYX_DEF(alSource3i, (INT, INT, INT, INT, INT), ()) { alSource3i(P(0, i32), P(1, i32), P(2, i32), P(3, i32), P(4, i32)); return NULL; } +ONYX_DEF(alSourceiv, (INT, INT, PTR), ()) { alSourceiv(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } +ONYX_DEF(alGetSourcef, (INT, INT, PTR), ()) { alGetSourcef(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } +ONYX_DEF(alGetSource3f, (INT, INT, PTR, PTR, PTR), ()) { alGetSource3f(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32)), ONYX_PTR(P(3, i32)), ONYX_PTR(P(4, i32))); return NULL; } +ONYX_DEF(alGetSourcefv, (INT, INT, PTR), ()) { alGetSourcefv(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } +ONYX_DEF(alGetSourcei, (INT, INT, PTR), ()) { alGetSourcei(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } +ONYX_DEF(alGetSource3i, (INT, INT, PTR, PTR, PTR), ()) { alGetSource3i(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32)), ONYX_PTR(P(3, i32)), ONYX_PTR(P(4, i32))); return NULL; } +ONYX_DEF(alGetSourceiv, (INT, INT, PTR), ()) { alGetSourceiv(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } + +ONYX_DEF(alSourcePlay, (INT), ()) { alSourcePlay(P(0, i32)); return NULL; } +ONYX_DEF(alSourcePlayv, (INT, PTR), ()) { alSourcePlayv(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } +ONYX_DEF(alSourcePause, (INT), ()) { alSourcePause(P(0, i32)); return NULL; } +ONYX_DEF(alSourcePausev, (INT, PTR), ()) { alSourcePausev(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } +ONYX_DEF(alSourceStop, (INT), ()) { alSourceStop(P(0, i32)); return NULL; } +ONYX_DEF(alSourceStopv, (INT, PTR), ()) { alSourceStopv(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } +ONYX_DEF(alSourceRewind, (INT), ()) { alSourceRewind(P(0, i32)); return NULL; } +ONYX_DEF(alSourceRewindv, (INT, PTR), ()) { alSourceRewindv(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } +ONYX_DEF(alSourceQueueBuffers, (INT, INT, PTR), ()) { alSourceQueueBuffers(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } +ONYX_DEF(alSourceUnqueueBuffers, (INT, INT, PTR), ()) { alSourceUnqueueBuffers(P(0, i32), P(1, i32), ONYX_PTR(P(2, i32))); return NULL; } + +ONYX_DEF(alListenerf, (INT, FLOAT), ()) { alListenerf(P(0, i32), P(1, f32)); return NULL; } +ONYX_DEF(alListener3f, (INT, FLOAT, FLOAT, FLOAT), ()) { alListener3f(P(0, i32), P(1, f32), P(2, f32), P(3, f32)); return NULL; } +ONYX_DEF(alListenerfv, (INT, PTR), ()) { alListenerfv(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } +ONYX_DEF(alListeneri, (INT, INT), ()) { alListeneri(P(0, i32), P(1, i32)); return NULL; } +ONYX_DEF(alListener3i, (INT, INT, INT, INT), ()) { alListener3i(P(0, i32), P(1, i32), P(2, i32), P(3, i32)); return NULL; } +ONYX_DEF(alListeneriv, (INT, PTR), ()) { alListeneriv(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } + +ONYX_DEF(alGetListenerf, (INT, PTR), ()) { alGetListenerf(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } +ONYX_DEF(alGetListener3f, (INT, PTR, PTR, PTR), ()) { alGetListener3f(P(0, i32), ONYX_PTR(P(1, i32)), ONYX_PTR(P(2, i32)), ONYX_PTR(P(3, i32))); return NULL; } +ONYX_DEF(alGetListenerfv, (INT, PTR), ()) { alGetListenerfv(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } +ONYX_DEF(alGetListeneri, (INT, PTR), ()) { alGetListeneri(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } +ONYX_DEF(alGetListener3i, (INT, PTR, PTR, PTR), ()) { alGetListener3i(P(0, i32), ONYX_PTR(P(1, i32)), ONYX_PTR(P(2, i32)), ONYX_PTR(P(3, i32))); return NULL; } +ONYX_DEF(alGetListeneriv, (INT, PTR), ()) { alGetListeneriv(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } + +ONYX_DEF(alEnable, (INT), ()) { alEnable(P(0, i32)); return NULL; } +ONYX_DEF(alDisable, (INT), ()) { alDisable(P(0, i32)); return NULL; } +ONYX_DEF(alIsEnabled, (INT), (BOOL)) { results->data[0] = WASM_I32_VAL(alIsEnabled(P(0, i32))); return NULL; } +ONYX_DEF(alGetBoolean, (INT), (BOOL)) { results->data[0] = WASM_I32_VAL(alGetBoolean(P(0, i32))); return NULL; } +ONYX_DEF(alGetDouble, (INT), (DOUBLE)) { results->data[0] = WASM_F64_VAL(alGetDouble(P(0, i32))); return NULL; } +ONYX_DEF(alGetFloat, (INT), (FLOAT)) { results->data[0] = WASM_F32_VAL(alGetFloat(P(0, i32))); return NULL; } +ONYX_DEF(alGetInteger, (INT), (INT)) { results->data[0] = WASM_I32_VAL(alGetInteger(P(0, i32))); return NULL; } +ONYX_DEF(alGetBooleanv, (INT, PTR), ()) { alGetBooleanv(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } +ONYX_DEF(alGetDoublev, (INT, PTR), ()) { alGetDoublev(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } +ONYX_DEF(alGetFloatv, (INT, PTR), ()) { alGetFloatv(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } +ONYX_DEF(alGetIntegerv, (INT, PTR), ()) { alGetIntegerv(P(0, i32), ONYX_PTR(P(1, i32))); return NULL; } +ONYX_DEF(alDistanceModel, (INT), ()) { alDistanceModel(P(0, i32)); return NULL; } +ONYX_DEF(alDopplerFactor, (FLOAT), ()) { alDistanceModel(P(0, f32)); return NULL; } +ONYX_DEF(alSpeedOfSound, (FLOAT), ()) { alDistanceModel(P(0, f32)); return NULL; } + +ONYX_DEF(alGetError, (), (INT)) { results->data[0] = WASM_I32_VAL(alGetError()); return NULL; } + +ONYX_DEF(alcCreateContext, (LONG, PTR), (LONG)) { wasm_val_init_ptr(&results->data[0], alcCreateContext((ALCdevice *) P(0, i64), ONYX_PTR(P(1, i32)))); return NULL; } +ONYX_DEF(alcMakeContextCurrent, (LONG), (BOOL)) { results->data[0] = WASM_I32_VAL(alcMakeContextCurrent((ALCcontext *) P(0, i64))); return NULL; } +ONYX_DEF(alcProcessContext, (LONG), ()) { alcProcessContext((ALCcontext *) P(0, i64)); return NULL; } +ONYX_DEF(alcSuspendContext, (LONG), ()) { alcSuspendContext((ALCcontext *) P(0, i64)); return NULL; } +ONYX_DEF(alcDestroyContext, (LONG), ()) { alcDestroyContext((ALCcontext *) P(0, i64)); return NULL; } +ONYX_DEF(alcGetCurrentContext, (), (LONG)) { wasm_val_init_ptr(&results->data[0], alcGetCurrentContext()); return NULL; } +ONYX_DEF(alcGetContextsDevice, (LONG), (LONG)) { wasm_val_init_ptr(&results->data[0], alcGetContextsDevice((ALCcontext *) P(0, i64))); return NULL; } +ONYX_DEF(alcGetError, (LONG), (INT)) { results->data[0] = WASM_I32_VAL(alcGetError((ALCdevice *) P(0, i64))); return NULL; } +ONYX_DEF(alcOpenDevice, (PTR), (LONG)) { wasm_val_init_ptr(&results->data[0], alcOpenDevice(ONYX_PTR(P(0, i32)))); return NULL; } +ONYX_DEF(alcCloseDevice, (LONG), (BOOL)) { results->data[0] = WASM_I32_VAL(alcCloseDevice((ALCdevice *) P(0, i64))); return NULL; } + +ONYX_DEF(alcIsExtensionPresent, (LONG, PTR), (BOOL)) { results->data[0] = WASM_I32_VAL(alcIsExtensionPresent((ALCdevice *) P(0, i64), ONYX_PTR(P(1, i32)))); return NULL; } +ONYX_DEF(alcGetProcAddress, (LONG, PTR), (LONG)) { wasm_val_init_ptr(&results->data[0], alcGetProcAddress((ALCdevice *) P(0, i64), ONYX_PTR(P(1, i32)))); return NULL; } +ONYX_DEF(alcGetEnumValue, (LONG, PTR), (INT)) { results->data[0] = WASM_I32_VAL(alcGetEnumValue((ALCdevice *) P(0, i64), ONYX_PTR(P(1, i32)))); return NULL; } +ONYX_DEF(alcGetIntegerv, (LONG, INT, INT, PTR), ()) { alcGetIntegerv((ALCdevice *) P(0, i64), P(1, i32), P(2, i32), ONYX_PTR(P(3, i32))); return NULL; } + +ONYX_DEF(alcCaptureOpenDevice, (PTR, INT, INT, INT), (LONG)) { + wasm_val_init_ptr(&results->data[0], alcCaptureOpenDevice(ONYX_PTR(P(0, i32)), P(1, i32), P(2, i32), P(3, i32))); + return NULL; +} +ONYX_DEF(alcCaptureCloseDevice, (LONG), (BOOL)) { results->data[0] = WASM_I32_VAL(alcCaptureCloseDevice((ALCdevice *) P(0, i64))); return NULL; } +ONYX_DEF(alcCaptureStart, (LONG), ()) { alcCaptureStart((ALCdevice *) P(0, i64)); return NULL; } +ONYX_DEF(alcCaptureStop, (LONG), ()) { alcCaptureStop((ALCdevice *) P(0, i64)); return NULL; } +ONYX_DEF(alcCaptureSamples, (LONG, PTR, INT), ()) { alcCaptureSamples((ALCdevice *) P(0, i64), ONYX_PTR(P(1, i32)), P(2, i32)); return NULL; } + + +ONYX_LIBRARY { + ONYX_FUNC(alGenBuffers) + ONYX_FUNC(alDeleteBuffers) + ONYX_FUNC(alIsBuffer) + ONYX_FUNC(alBufferData) + ONYX_FUNC(alBufferf) + ONYX_FUNC(alBuffer3f) + ONYX_FUNC(alBufferfv) + ONYX_FUNC(alBufferi) + ONYX_FUNC(alBuffer3i) + ONYX_FUNC(alBufferiv) + ONYX_FUNC(alGetBufferf) + ONYX_FUNC(alGetBuffer3f) + ONYX_FUNC(alGetBufferfv) + ONYX_FUNC(alGetBufferi) + ONYX_FUNC(alGetBuffer3i) + ONYX_FUNC(alGetBufferiv) + + ONYX_FUNC(alGenSources) + ONYX_FUNC(alDeleteSources) + ONYX_FUNC(alIsSource) + ONYX_FUNC(alSourcef) + ONYX_FUNC(alSource3f) + ONYX_FUNC(alSourcefv) + ONYX_FUNC(alSourcei) + ONYX_FUNC(alSource3i) + ONYX_FUNC(alSourceiv) + ONYX_FUNC(alGetSourcef) + ONYX_FUNC(alGetSource3f) + ONYX_FUNC(alGetSourcefv) + ONYX_FUNC(alGetSourcei) + ONYX_FUNC(alGetSource3i) + ONYX_FUNC(alGetSourceiv) + ONYX_FUNC(alSourcePlay) + ONYX_FUNC(alSourcePlayv) + ONYX_FUNC(alSourcePause) + ONYX_FUNC(alSourcePausev) + ONYX_FUNC(alSourceStop) + ONYX_FUNC(alSourceStopv) + ONYX_FUNC(alSourceRewind) + ONYX_FUNC(alSourceRewindv) + ONYX_FUNC(alSourceQueueBuffers) + ONYX_FUNC(alSourceUnqueueBuffers) + + ONYX_FUNC(alListenerf) + ONYX_FUNC(alListener3f) + ONYX_FUNC(alListenerfv) + ONYX_FUNC(alListeneri) + ONYX_FUNC(alListener3i) + ONYX_FUNC(alListeneriv) + ONYX_FUNC(alGetListenerf) + ONYX_FUNC(alGetListener3f) + ONYX_FUNC(alGetListenerfv) + ONYX_FUNC(alGetListeneri) + ONYX_FUNC(alGetListener3i) + ONYX_FUNC(alGetListeneriv) + + ONYX_FUNC(alEnable) + ONYX_FUNC(alDisable) + ONYX_FUNC(alIsEnabled) + ONYX_FUNC(alGetBoolean) + ONYX_FUNC(alGetDouble) + ONYX_FUNC(alGetFloat) + ONYX_FUNC(alGetInteger) + ONYX_FUNC(alGetBooleanv) + ONYX_FUNC(alGetDoublev) + ONYX_FUNC(alGetFloatv) + ONYX_FUNC(alGetIntegerv) + ONYX_FUNC(alDistanceModel) + ONYX_FUNC(alDopplerFactor) + ONYX_FUNC(alSpeedOfSound) + + ONYX_FUNC(alGetError) + + ONYX_FUNC(alcCreateContext) + ONYX_FUNC(alcMakeContextCurrent) + ONYX_FUNC(alcProcessContext) + ONYX_FUNC(alcSuspendContext) + ONYX_FUNC(alcDestroyContext) + ONYX_FUNC(alcGetCurrentContext) + ONYX_FUNC(alcGetContextsDevice) + ONYX_FUNC(alcGetError) + + ONYX_FUNC(alcOpenDevice) + ONYX_FUNC(alcCloseDevice) + + ONYX_FUNC(alcIsExtensionPresent) + ONYX_FUNC(alcGetProcAddress) + ONYX_FUNC(alcGetEnumValue) + ONYX_FUNC(alcGetIntegerv) + + ONYX_FUNC(alcCaptureOpenDevice) + ONYX_FUNC(alcCaptureCloseDevice) + ONYX_FUNC(alcCaptureStart) + ONYX_FUNC(alcCaptureStop) + ONYX_FUNC(alcCaptureSamples) + + NULL +}; \ No newline at end of file diff --git a/modules/openal/onyx_openal.so b/modules/openal/onyx_openal.so new file mode 100755 index 0000000000000000000000000000000000000000..77bd206581031ccb2a6666bc0c8390c82b41958a GIT binary patch literal 86464 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