The SuperBLT XAudio 'eXtended Audio' API (coincedentally the same as the DirectX audio system, although that was not intended) is an API that allows BLT mods to use 3D audio effects. It is based upon OpenAL, currently using OpenALSoft. HRTF support is planned.
First, make sure you call
blt.xaudio.setup() before you do anything with XAudio. It doesn't matter if you
call it many times, but it very much matters if you don't call it at all.
XAudio works on the basis of sources and buffers:
A piece of audio can be loaded from an OGG file into a buffer. The memory used in the buffer is shared between all sources playing it, so once a source is loaded it's memory consumption does not change.
Buffers are cached, so if you create two buffers with the same filename there will be no difference in memory consumption as if you'd only created one. Additionally, buffers are retained when starting/stopping a heist to speed up loading.
A buffer is created with
filename is the path to a OGG file you
want to load (note the path is the same type as used in dofile, so you should use something
ModPath .. "sounds/myfile.ogg").
When you're done with a buffer, close it with
buff:close(). This tells the system you're done with it. Note
it does not actually destroy the buffer and free up it's memory use (done in case you want to use the buffer
later on) - for that, use
buff:close(true) (note this only has an effect if this is done on the last buffer
object referencing the physical buffer).
You can also find the length in seconds of a buffer with
close([force]): Closes this buffer. If you don't close it, the buffer will be automatically be closed when the game exits (however, that is not a reason not to close it.). If the
forceparameter is supplied, it must be a boolean. And if it's
true, the buffer will be unloaded (assuming there is not another instance of the object open). If not specified or
false, the buffer will remain cached to speed up loading for when the source is next loaded.
get_length(): Gets the length of the represented audio track, in seconds.
A basic source is an instance of
XAudio.Source. You probably won't use these basic sources very much, if
at all. They are Lua objects (via
blt_class), and can be subclassed and extended to perform custom tasks.
There are two basic ways to use a source:
- Create a source with
XAudio.Source:new(), load buffers into it with
close it when you're done. Try to avoid this whenever possible for performance reasons.
- Create a source and supply a buffer as you create it with
XAudio.Source:new(buffer). The source
will immediately start playing the supplied buffer, and will automatically close itself when it is finished. After
creating one of these, you don't have to pay any further attention to it. This is the recomended way of
Note at at present, using OpenALsoft, there is a maximum of 256 sources you can use at any one time. Don't pay too much attention to this particular number, as in the future when hardware acceleration is supported it will vary depending on your motherboard/soundcard drivers.
This means that you should not hold onto open sources. Using the second method presented above will likely clear your mod from having any issues with this, as it is unlikely more than 256 sounds will need to be played at any one time.
If you do have to use the former method for whatever reason, be absolutely sure you close your sources with
You can check if a source is closed with the
src:is_closed() method, and note that trying to call almost any
other method on a closed source will result in a Lua error.
You can get the current state of a source using
src:get_state(). This will return
You can set the volume of a source using
val is the volume between
You can set the position, velocity and direction of a source using
src:set_direction, respectively. These functions accept world positions either as vectors or as x,y,z sets
for their arguments.
Please note that if you play a sterio track, the source's position will be ignored and it will play without any 3D audio effects.
close(): Destroy this audio source. Do this as soon as possible, as there is a limit to how many sources can be open at any one time. This does not affect the underlying buffer.
set_buffer(buffer): Sets this source to play the supplied buffer. This does not start the source playing, only selects which source should be played. It is an error to call this while the source is active (playing or paused states).
set_single_sound(enable): Sets whether this source is in single-sound mode. You wouldn't normally use this - rather, pass the desired buffer to the constructor.
trueif this source is in either it's playing or paused state. When a source is active, some methods (such as set_buffer) are disabled.
trueif the source is closed,
get_steate(): Returns the current state of this source. This returns one of
set_position(pos | x,y,z): Sets the position of this audio source, in world units. You can either supply a single vector as an argument, or supply seperate X, Y and Z coordinates.
set_velocity(pos | x,y,z): Sets the velocity of this object. This is used to calculate the change in pitch due to the doppler effect, although it may be used for other stuff later. Try to set it if you can, but don't worry if you can't.
set_direction(pos | x,y,z): Sets the direction (facing) of this source. Currently not used, but it may be in the future.
set_volume(volume): Sets a volume multiplier for this source, between
1(no attenuation, default).
set_type(type): Sets the type of this sound. This determines which volume slider controls this source. Valid values are
get_type(): Gets the type of this source - see
get_volume(): Gets the volume set with
set_volume. This does not include the game's volume sliders.
get_raw_volume(): Gets the raw volume (the value sent to OpenAL) - this includes both the volume set with
set_volume, and the value of the appropriate volume slider (see
update(t, dt, paused): Updates the audio source. You shouldn't call this yourself, but you're welcome to override it in subclasses. It is called every tick by XAudio.
A unit source is similar to a basic source, only it is attached to a unit - if you attach a unit source to a cop, then the source will move to follow the cop around.
A unit source is created in a very similar way to a basic source - use
XAudio.UnitSource:new(unit, buffer) to create
the unit source. If you want the source to follow the player, provide
XAudio.PLAYER as the unit argument.
A voiceline manager is a utility to help you with making units speak (and ensuring they don't say two lines at
the same time). They can be created with
XAudio.VoicelineManager:new(unit, buffer) (also accepting
You must constantly call
vm:update(). This function starts new sounds playing, so not calling it will result
in no sounds coming out. Stopping calling it will result in all currently-playing sounds continue to the end, however.
When you've created one, use
vm:play(buffer[, channel]) to play a sound. Voiceline manager support using multiple
channels - it will happily play two sounds at once if they're one seperate channels. If
channel is not
speicifed, it defaults to
XAudio.VoicelineManager.DEFAULT. Trying to play a sound while another sound is busy
playing on the same channel will result in it being queued until the first source is done.