# XAudio

The SuperBLT XAudio 'eXtended Audio' API (coincedentally the same as the DirectX audio system) is an API
that allows BLT mods to use 3D audio effects. It is based upon OpenAL, currently
using OpenALSoft. HRTF support is planned.

XAudio works on the basis of sources and buffers:

## 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 `XAudio.Buffer:new(filename)`, where `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
like `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 `buff:get_length()`.

## Sources

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 `src:set_buffer(buffer)`, and
close it when you're done
- 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.

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
the `src:close()` method.

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 `XAudio.Source.PLAYING`,
`.PAUSED`, `.STOPPED`, `.INITIAL` or `.OTHER`.

You can set the volume of a source using `src:set_volume(val)` where `val` is the volume between `0` and `1`.

You can set the position, velocity and direction of a source using `src:set_position`, `src:set_velocity`,
and `src:set_direction`, respectively. These functions accept world positions either as vectors or as x,y,z sets
for their arguments.

You can set the minimum and maximum range at which the sound is audible by using `src:set_min_distance` and
`src:set_max_distance`. The minimum distance defines the range at which the sound will always play at full
volume and the maximum distance specifies the range at which the sound stops being audible.

## Unit Sources

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.

## Voiceline Manager

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)` (also accepting `XAudio.PLAYER`).

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.
