Preface
This is the reference manual of MoonAL, which is a Lua binding library for the OpenAL 3D Audio Library API, targeted to the OpenAL Soft implementation. [1]
It is assumed that the reader is familiar with both OpenAL and the Lua programming language.
For convenience of reference, this document contains external (deep) links to the Lua Reference Manual.
The following OpenAL documentation will also be referenced in this manual:
Getting and installing
For installation intructions, refer to the README file in the MoonAL official repository on GitHub.
Module organization
The MoonAL module is loaded using Lua’s require() and returns a table containing the functions it provides (as usual with Lua modules). This manual assumes that such table is named al, i.e. that it is loaded with:
al = require("moonal")
but nothing forbids the use of a different name.
Examples
Complete examples can be found in the examples/ directory of the release package.
License
MoonAL is released under the MIT/X11 license (same as Lua, and with the same only requirement to give proper credits to the original author). The copyright notice is in the LICENSE file in the base directory of the official repository on GitHub.
See also
MoonAL is part of MoonLibs, a collection of Lua libraries for graphics and audio programming.
Introduction
MoonAL is an (almost) one-to-one Lua binding library to the OpenAL API. It provide means to implement scripted OpenAL applications using Lua instead of C or C++, with all its pros and cons.
This section gives a brief overview, while the details of the bindings are given in the sections that follow.
As a general rule, OpenAL API functions are bound to by MoonAL functions whose names are snake_case versions of the original ones (e.g., alcOpenDevice( ) is bound to by al.open_device( )). This rule is loosely followed, though. For example, the OpenGL-style alGenXxx( ) functions that create objects are mapped in MoonAL to al.CreateXxx( ) functions that create a single function.
(Note that both AL and ALC functions bindings are contained in the al table).
If not stated otherwise, on error all MoonAL functions raise a Lua error. If needed, this behaviour can be overridden by wrapping function calls in the standard Lua pcall( ).
MoonAL binds OpenAL objects (device, context, etc.) to Lua userdata, which are returned by the creating or getter functions (al.open_device( ), al.create_context( ), etc) and are then used to refer to objects in Lua in the same way as one would use OpenAL handles in C.
In the rest of this manual we will refer to userdata bound to OpenAL objects as to just 'objects', or as 'MoonAL objects' (vs. 'OpenAL objects') when there is need for disambiguation.
Objects are garbage collected at exit (which includes on error), and automatically released at the OpenAL level, so there is no need to explicitly invoke the bindings to alDeleteXxx( ) at exit for cleanup.
Apart from at exit, however, objects are not automatically garbage collected [2] and one must release them explicitly when needed, e.g. to release resources when the application is not exiting and some objects are no longer needed.
Releasing an object causes the automatic (pre) destruction of all its children objects, and the invalidation of any reference to the object and to its children. [3]
OpenAL structs used to pass parameters and results across the OpenAL API are mapped in MoonAL to tables, having more or less the same contents as their C counterparts but again with snake_case named fields, while enumerations are mapped to/from sets of string literals, while flags bitmasks are represented as plain integers encoded in the same way as in C.
In addition to the bindings to the OpenAL API, which are described in the sections that follow, MoonAL also provides a few other utilities and object 'methods' that do not correspond to OpenAL functions. These are described mainly in the 'Miscellanea' subsections.
Objects
The following tree shows the MoonAL objects and their parent-child relationships.
device (ALCdevice)
└─ context (ALCcontext)
├─ listener (OpenAL Listener object, singleton)
├─ source (OpenAL Source object)
├─ buffer (OpenAL Buffer object)
├─ effect (EFX extension Effect object)
├─ filter (EFX extension Filter object)
└─ auxslot (EFX extension AuxiliaryEffectSlot object)
device
A device object is a logical representation of a physical audio device.
There are three kinds of devices - playback, capture, and loopback - and thus three different functions to open a device and create a corresponding device object (there is only one close function, though).
To query for the names (or 'specifiers') of the devices available on your system, use the following functions:
-
{playbackname}, {capturename} = available_devices( )
Lists the names (strings) of all the available playback devices and capture devices.
-
playbackname, capturename = default_devices( )
Returns the names (strings) of the default playback device and of the default capture device.
These are the devices that will be opened when calling the open functions without passing them the name parameters.
Playback device
-
device = open_device([name])
Opens a playback device, and returns the corresponding device object.
The optional name parameter (a string) is the device specifier.
If name is nil, the default device will be used.
Rfr: alcOpenDevice.
-
close_device(device)
Closes device, which may be of any kind (playback, capture, or loopback).
Also available as device:close( ) method.
Rfr: alcCloseDevice, alcCaptureCloseDevice.
-
name = device_name(device)
Returns the device name (a.k.a. 'specifier', a string).
Also available as device:name( ) method.
-
device_pause(device)
device_resume(device)
Also available as device:pause/resume( ) methods.
Rfr: alcDevicePauseSOFT, alcDeviceResumeSOFT ( ALC_SOFT_pause_device extension).
-
{specifier} = hrtf_specifiers(device)
Returns the list of of HRTF specifiers (strings) for device.
Note that the hrtf_id for the i-th specifier in the list is i - 1 (0-based index).
Rfr: ALC_HRTF_SPECIFIER_SOFT (ALC_SOFT_HRTF extension).
Capture device
-
device = capture_open_device([name], frequency, format, maxframes)
Opens a capture device and returns the corresponding device object.
The caller must specify the capture frequency in hertz, the format of the frames, and the size of the capture buffer in number of frames (maxframes).
(The buffer size in bytes is maxframes times the size of a frame, that depends on the given format).
Rfr: alcCaptureOpenDevice. -
close_device( )
-
device_name( )
-
capture_start(device)
capture_stop(device)
Also available as device:start/stop( ) methods.
Rfr: alcCaptureStart, alcCaptureStop.
-
data = capture_samples(device, nframes)
nframes: integer (number of frames to capture).
Returns the captured data as a binary string, or nil if the requested number of frames is not available.
Also available as device:samples( ) method.
Rfr: alcCaptureSamples.
Loopback device
Loopback devices require the ALC_SOFT_loopback extension.
-
device = loopback_open_device([name], maxframes, maxframesize)
The name parameter (a string) is the device specifier of the playback device to loop back. If name is nil, the default playback device will be used.
maxframes and maxframesize are the maximum values that the application will pass to render_samples( ).
Rfr: alcLoopbackOpenDeviceSOFT. -
close_device( )
-
data = render_samples(device, frames, framesize)
Returns frames * framesize bytes of data, as a binary string.
Also available as device:render( ) method.
Rfr: alcRenderSamplesSOFT.
context
A context object in MoonAL corresponds to a OpenAL context, which is basically a container for objects and state needed to render audio on a device.
(A context is bound to one and only one device, but more than one contexts may be bound to the same device.)
Note that, in MoonAL, the concept of 'current context' is almost (if not completely) removed from the API, and one has to explicitly indicate the context the API calls refer to, whereas in OpenAL most API calls implicitly refer to the current context.
-
context = create_context(device, [attributes])
Creates a context bound to the given device.
The optional attributes table can be passed to specify some of all of the context attributes (see the OpenAL documentation for more details).
Rfr: alcCreateContext.
-
delete_context(context)
Also available as context:delete( ) method.
Rfr: alcDestroyContext.
-
boolean = reset_context(context, [attributes])
Also available as context:reset( ) method.
Rfr: alcResetDeviceSOFT (ALC_SOFT_HRTF extension)
-
process_context(context)
suspend_context(context)
Also available as context:process/suspend( ) methods.
Rfr: alcProcessContext, alcSuspendContext.
-
device = context_device(context)
Also available as context:device( ) method.
Rfr: alcGetContextsDevice.
-
enable(context, capability)
disable(context, capability)
boolean = is_enabled(context, capability)
Also available as context:enable/disable/is_enabled( ) methods.
Rfr: alEnable, alDisable, alIsEnabled.
-
val, … = get_attribute(context, attribute)
Also available as context:get_attribute( ) method.
Rfr: alcGetInteger, alcGetString, etc.
-
defer_updates(context)
process_updates(context)
Also available as context:defer_updates/process_updates( ) methods.
Rfr: alDeferUpdatesSOFT, alProcessUpdatesSOFT (AL_SOFT_deferred_updates extension)
listener
In OpenAL there is a single listener per context.
The listener is automatically created (and deleted) with the context itself, and an handle to it (i.e. a listener object) can be retrieved with the context_listener( ) function, or with the equivalent context:listener( ) method.
The only use for the listener object is to set or get the listener parameters with the following functions or the equivalent methods:
source
-
source = create_source(context)
Rfr: alGenSources.
-
delete_source(source)
Also available as source:delete( ) method.
Rfr: alDeleteSources.
-
source_play(source | {source})
source_stop(source | {source})
source_pause(source | {source})
source_rewind(source | {source})
All these functions accept either a single source or a list of sources (from the same context).
Also available as source:play/stop/pause/rewind( ) methods.
Rfr: alSourcePlay, alSourceStop, alSourcePause, alSourceRewind.
buffer
-
buffer = create_buffer(context)
Rfr: alGenBuffers.
-
delete_buffer(buffer)
Also available as buffer:delete( ) method.
Rfr: alDeleteBuffers.
-
buffer_data(buffer, format, data, freq)
data: binary string,
Also available as buffer:data( ) method.
Rfr: alBufferData.
effect (EFX)
Use of effect objects requires the ALC_EXT_EFX extension.
-
effect = create_effect(context)
Rfr: alGenEffects.
-
delete_effect(effect)
Also available as effect:delete( ) method.
Rfr: alDeleteEffects.
-
effecttype = get_effect_type(effect)
set_effect_type(effect, effecttype)
Also available as effect:get_type/set_type( ) methods.
Rfr: alGetEffect, alEffect.
filter (EFX)
Use of filter objects requires the ALC_EXT_EFX extension.
-
filter = create_filter(context)
Rfr: alGenFilters.
-
delete_filter(filter)
Also available as filter:delete( ) method.
Rfr: alDeleteFilters.
-
filtertype = get_filter_type(filter)
set_filter_type(filter, filtertype)
Also available as filter:get_type/set_type( ) methods.
Rfr: alGetFilter, alFilter.
auxslot (EFX)
Use of auxslot objects requires the ALC_EXT_EFX extension.
-
auxslot = create_auxslot(context)
Rfr: alGenAuxiliaryEffectSlots.
-
delete_auxslot(auxslot)
Also available as auxslot:delete( ) method.
Rfr: alDeleteAuxiliaryEffectSlots.
Parameters
attributes = {
sync: boolean,
output_limiter: boolean,
frequency: integer,
refresh: integer,
mono_sources: integer,
stereo_sources: integer,
-- ALC_EXT_EFX extension:
max_auxiliary_sends: integer,
-- ALC_SOFT_HRTF extension:
hrtf: boolean,
hrtf_id: integer (see hrtf_specifiers),
-- ALC_SOFT_loopback extension:
format_type: type,
format_channels: channels,
} (Rfr: ALC_ALL_ATTRIBUTES)
attribute:
'sync': boolean
'output limiter': boolean
'frequency': integer
'refresh': integer
'mono sources': integer
'stereo sources': integer
-- ALC_EXT_EFX extension:
'max auxiliary sends': integer
-- ALC_SOFT_HRTF extension:
'hrtf': boolean
'hrtf id': integer (see hrtf_specifiers)
'hrtf specifier': string or nil
'hrtf status': hrtfstatus
-- ALC_SOFT_loopback extension:
'format type': type
'format channels': channels
-- ALC_SOFT_device_clock extension:
'device clock': integer
'device latency': integer
'device clock latency': integer, integer
context parameters:
'doppler factor': float
'doppler velocity': float
'speed of sound': float
'distance model': distancemodel
-- AL_SOFT_gain_clamp_ex extension:
'gain limit': float (query only)
-- AL_SOFT_deferred_updates extension:
'deferred updates': boolean (query only)
-- AL_SOFT_source_resampler extension:
'default resampler': resampler (query only)
'resampler names': {resampler} (query only)
listener parameters:
'meters per unit': float
'gain': float
'position': {float}[3]
'velocity': {float}[3]
'orientation': {float}[3], {float}[3] (at, up).
source parameters:
'relative': boolean
'cone inner angle': float
'cone outer angle': float
'pitch': float
'position': {float}[3]
'direction': {float}[3]
'velocity': {float}[3]
'looping': boolean
'buffer': buffer
'gain': float
'min gain': float
'max gain': float
'orientation': {float}[3], {float}[3] (at, up)
'state': sourcestate (query only)
'buffers queued': integer (query only)
'buffers processed': integer (query only)
'reference distance': float
'rolloff factor': float
'cone outer gain': float
'max distance': float
'sec offset': float
'sample offset': float
'byte offset': float
'type': sourcetype (query only)
'doppler factor': float
-- AL_EXT_STEREO_ANGLES extension:
'stereo angles', float, float
-- AL_EXT_source_distance_model extension:
'distance model': distancemodel
-- AL_EXT_SOURCE_RADIUS extension:
'radius': float
-- AL_SOFT_direct_channels extension:
'direct channels': boolean
-- AL_SOFT_source_resampler extension:
'resampler': resampler
-- AL_SOFT_source_spatialize extension:
'spatialize': spatializemode
-- AL_SOFT_source_length extension:
'byte length': integer (query only)
'sample length': integer (query only)
'sec length': float (query only)
-- AL_SOFT_source_latency extension:
'sec offset latency': double, double (query only)
'sample offset latency': integer, integer (query only)
-- ALC_SOFT_device_clock extension:
'sample offset clock': integer, integer (query only)
'sec offset clock': double, double (query only)
-- ALC_EXT_EFX extension:
'direct filter': directfilter
'auxiliary send filter': auxslot, integer, filter
'air absorption factor': float
'room rolloff factor': float
'cone outer gainhf': float
'direct filter gainhf auto': boolean
'auxiliary send filter gain auto': boolean
'auxiliary send filter gainhf auto': boolean
buffer parameters:
'frequency': integer (query only)
'bits': integer (query only)
'channels': integer (query only)
'size': integer (query only)
-- AL_SOFT_block_alignment extension:
'unpack block alignment': integer
'pack block alignment': integer
-- AL_SOFT_loop_points extension:
'loop points': integer, integer
effect parameters depend on the effecttype:
reverb -
chorus -
distortion -
echo -
flanger -
ring modulator -
compressor -
equalizer -
eaxreverb -
dedicated
reverb effect parameters: (rfr: AL_REVERB_XXX)
'density': float
'diffusion': float
'gain': float
'gainhf': float
'decay time': float
'decay hfratio': float
'reflections gain': float
'reflections delay': float
'late reverb gain': float
'late reverb delay': float
'air absorption gainhf': float
'room rolloff factor': float
'decay hflimit': integer
chorus effect parameters: (rfr: AL_CHORUS_XXX)
'waveform': choruswaveform
'rate': float
'depth': float
'feedback': float
'delay': float
'phase': integer
distortion effect parameters: (rfr: AL_DISTORTION_XXX)
'edge': float
'gain': float
'lowpass cutoff': float
'eqcenter': float
'eqbandwidth': float
echo effect parameters: (rfr: AL_ECHO_XXX)
'delay': float
'lrdelay': float
'damping': float
'feedback': float
'spread': float
flanger effect parameters: (rfr: AL_FLANGER_XXX)
'waveform': flangerwaveform
'rate': float
'depth': float
'feedback': float
'delay': float
'phase': integer
ring modulator effect parameters: (rfr: AL_RING_MODULATOR_XXX)
'waveform': ringmodulatorwaveform
'frequency': float
'highpass cutoff': float
compressor effect parameters: (rfr: AL_COMPRESSOR_XXX)
'onoff': compressoronoff
equalizer effect parameters: (rfr: AL_EQUALIZER_XXX)
'low gain': float
'low cutoff': float
'mid1 gain': float
'mid1 center': float
'mid1 width': float
'mid2 gain': float
'mid2 center': float
'mid2 width': float
'high gain': float
'high cutoff': float
eaxreverb effect parameters: (rfr: AL_EAXREVERB_XXX)
'density': float
'diffusion': float
'gain': float
'gainhf': float
'gainlf': float
'decay time': float
'decay hfratio': float
'decay lfratio': float
'decay hflimit': float
'reflections gain': float
'reflections delay': float
'late reverb gain': float
'late reverbdelay': float
'air absorption gainhf': float
'echo time': float
'echo depth': float
'modulation time': float
'modulation depth': float
'hfreference': float
'lfreference': float
'room rolloff factor': float
'late reverb pan': float
'reflections pan': {float}[3]
filter parameters depend on the filtertype:
lowpass -
highpass -
bandpass
lowpass filter parameters: (rfr: AL_LOWPASS_XXX)
'gain': float
'gainhf': float
highpass filter parameters: (rfr: AL_HIGHPASS_XXX)
'gain': float
'gainlf': float
bandpass filter parameters: (rfr: AL_BANDPASS_XXX)
'gain': float
'gainlf': float
'gainhf': float
auxslot parameters: (rfr: AL_EFFECTSLOT_XXX)
'gain': float
'auxiliary_send_auto': boolean
'effect': effect
Enums
OpenAL enums are mapped in MoonAL to sets of string literals (as is customary in Lua). Admitted literals are available in the al table (e.g. al.EFFECT_XXX for AL_EFFECT_XXX), and can also be inferred from the corresponding C enum names. For example, given the al.EFFECT_XXX hint for the effecttype enum type, the literals it admits are obtained by lowercasing the XXX part of the name and replacing any underscore with a space.
The example contained in the code snippets section should hopefully be clear enough.
If needed, the following function can be used to obtain the list of literals admitted by a particular enum type.
-
{literal} = al.enum(enumtype)
Returns a table listing the literals admitted by enumtype (given as a string, e.g. 'capability', 'format', etc).
Below is the list of the enum types, each with its hint, the list of string values it admits (if not too long), and a reference to the original OpenAL enum type where to look for semantic and usage information.
capability: al.XXX
Values: 'source distance model'.
channels: al.ALC_XXX_SOFT
Values: 'mono', 'stereo', 'quad', '5point1', '6point1', '7point1'.
choruswaveform: al.CHORUS_WAVEFORM_XXX
Values: 'sinusoid', 'triangle'.
compressoronoff: al.COMPRESSOR_XXX
Values: 'off', 'on'.
distancemodel: al.NONE, al.INVERSE_DISTANCE, al.INVERSE_DISTANCE_CLAMPED, etc.
Values: 'none', 'inverse', 'inverse clamped', 'linear', 'linear clamped', 'exponent', 'exponent clamped'.
effecttype: al.EFFECT_XXX
Values: 'null', 'reverb', 'chorus', 'distortion', 'echo', 'flanger', 'frequency shifter', 'vocal morpher', 'pitch shifter', 'ring modulator', 'autowah', 'compressor', 'equalizer', 'eaxreverb', 'dedicated dialogue', 'dedicated low frequency effect'.
filtertype: al.FILTER_XXX
Values: 'null', 'lowpass', 'highpass', 'bandpass'.
flangerwaveform: al.XXX
Values: 'sinusoid', 'triangle'.
format: al.FORMAT_XXX
Values: 'quad8 loki', 'quad16 loki', 'mono float32', 'stereo float32', 'mono double', 'stereo double', 'mono mulaw', 'stereo mulaw', 'mono alaw', 'stereo alaw', 'quad8', 'quad16', 'quad32', 'rear8', 'rear16', 'rear32', '51chn8', '51chn16', '51chn32', '61chn8', '61chn16', '61chn32', '71chn8', '71chn16', '71chn32', 'quad mulaw', 'rear mulaw', '51chn mulaw', '61chn mulaw', '71chn mulaw', 'mono ima4', 'stereo ima4', 'mono msadpcm', 'stereo msadpcm', 'bformat2d 8', 'bformat2d 16', 'bformat2d float32', 'bformat3d 8', 'bformat3d 16', 'bformat3d float32', 'bformat2d mulaw', 'bformat3d mulaw', 'mono8', 'mono16', 'stereo8', 'stereo16'.
hrtfstatus: al.ALC_HRTF_XXX_SOFT
Values: 'disabled', 'enabled', 'denied', 'required', 'headphones detected', 'unsupported format'.
resampler: al.XXX_RESAMPLER
Values: 'point', 'linear', 'fir4', 'bsinc'.
ringmodulatorwaveform: al.RING_MODULATOR_XXX
Values: 'sinusoid', 'sawtooth', 'square'.
sourcestate: al.XXX
Values: 'initial', 'playing', 'paused', 'stopped'.
sourcetype: al.XXX
Values: 'static', 'streaming', 'undetermined'.
spatializemode: al.SPATIALIZE_MODE_XXX
Values: 'off', 'on', 'auto'.
type: al.TYPE_XXX
Values: 'char', 'uchar', 'byte', 'ubyte', 'short', 'ushort', 'int', 'uint', 'long', 'ulong', 'float', 'double'.
Miscellanea
Version handling
The al table contains the following version related information:
-
al._VERSION: MoonAL version (a string).
The following functions can be used to retrieve the version and other information about of the OpenAL runtime (libopenal.so):
-
string = get_version( )
string = get_alc_version( )
string = get_efx_version( )
string = get_vendor( )
string = get_renderer( )
Rfr: AL_VERSION, ALC_MAJOR/MINOR_VERSION, ALC_EFX_MAJOR/MINOR_VERSION, AL_VENDOR, AL_RENDERER.
Extensions
-
{extname} = get_extensions(context)
Returns a table with the names (strings) of the available AL and ALC extensions.
-
boolean = is_extension_present(context, extname)
Returns true if the extension named extname (a string) is present, false otherwise.
Works both for AL and ALC extensions.
Data handling
This section describes additional utilities that can be used to encode data from Lua variables to binary strings and viceversa.
-
val1, …, valN = flatten(table)
Flattens out the given table and returns the terminal elements in the order they are found.
Similar to Lua’s table.unpack( ), but it also unpacks any nested table. Only the array part of the table and of nested tables is considered.
-
size = sizeof(type)
Returns the size in bytes of the given type.
-
data = pack(type, val1, …, valN)
data = pack(type, table)
Packs the numbers val1, …, valN, encoding them according to the given type, and returns the resulting binary string.
The values may also be passed in a (possibly nested) table. Only the array part of the table (and of nested tables) is considered.
-
framesize, channels = framesize(format, [alignment=0])
Returns the frame size in bytes and the number of channels for the given format.
(The alignment parameter is relevant only for IMA4 and MSADPCM formats).
Tracing utilities
-
trace_objects(boolean)
Enable/disable tracing of objects creation and destruction (which by default is disabled).
If enabled, a printf is generated whenever an object is created or deleted, indicating the object type and the value of its raw handle.
-
t = now( )
Returns the current time in seconds (a Lua number).
This is implemented with monotonic clock_gettime(3), if available, or with gettimeofday(3) otherwise.
-
dt = since(t)
Returns the time in seconds (a Lua number) elapsed since the time t, previously obtained with the now( ) function.
-
sleep(seconds)
Sleeps for seconds.