This module corresponds to sections 4.1 (Basic Listener and Source
Attributes) and 4.3 (Source Objects) of the OpenAL Specification and
Reference (version 1.1).

Sources specify attributes like position, velocity, and a buffer with sample
data. By controlling a source's attributes the application can modify and
parameterize the static sample data provided by the buffer referenced by the
source. Sources define a localized sound, and encapsulate a set of attributes
applied to a sound at its origin, i.e. in the very first stage of the
processing on the way to the listener. Source related effects have to be
applied before listener related effects unless the output is invariant to any
collapse or reversal of order. OpenAL also provides additional functions to
manipulate and query the execution state of sources: the current playing
status of a source, including access to the current sampling position within
the associated buffer.

Source Attributes

Basic Source Attributes

sourcePosition contains the current location of the source in the world
coordinate system. Any 3-tuple of valid float values is allowed.
Implementation behavior on encountering NaN and infinity is not defined. The
initial position is (Vertex3 0 0 0).

sourceVelocity contains current velocity (speed and direction) of the
source in the world coordinate system. Any 3-tuple of valid float values is
allowed, and the initial velocity is (Vector3 0 0 0). sourceVelocity does
not affect sourcePosition. OpenAL does not calculate the velocity from
subsequent position updates, nor does it adjust the position over time based
on the specified velocity. Any such calculation is left to the application.
For the purposes of sound processing, position and velocity are independent
parameters affecting different aspects of the sounds.

sourceVelocity is taken into account by the driver to synthesize the
Doppler effect perceived by the listener for each source, based on the
velocity of both source and listener, and the Doppler related parameters.

sourceGain contains a scalar amplitude multiplier for the given source.
The initial value 1 means that the sound is unattenuated. A sourceGain
value of 0.5 is equivalent to an attenuation of 6dB. The value zero equals
silence (no output). Driver implementations are free to optimize this case
and skip mixing and processing stages where applicable. The implementation is
in charge of ensuring artifact-free (click-free) changes of gain values and
is free to defer actual modification of the sound samples, within the limits
of acceptable latencies.

A sourceGain larger than 1 (amplification) is permitted. However, the
implementation is free to clamp the total gain (effective gain per source
times listener gain) to 1 to prevent overflow.

If sourceRelative contains Listener, it indicates indicates that the
values specified by sourcePosition, sourceVelocity and direction are to
be interpreted relative to the listener position. The initial value is
World, indicating that those source attributes are to be interpreted
relative to the world, i.e. they are considered absolute.

Source Type

When first created, a source will be in the Undetermined state. If a
buffer is then attached using buffer, then the source will enter the
Static state. If the first buffer attached to a source is attached using
queueBuffers, then the source will enter the Streaming state. A source of
either state will be reset to state Undetermined by setting its buffer to
Nothing, and attaching any buffer to a streaming source will change the
state to Static. Attempting to queue a buffer on a static source will
result in an ALInvalidOperation error.

If loopingMode contains Looping, it indicates that the source will not
be in the Stopped state once it reaches the end of last buffer in the
buffer queue. Instead, the source will immediately promote to Initial and
Playing. The initial value is OneShot. loopingMode can be changed on a
source in any execution state. In particular, it can be changed on a
Playing source.

Current Buffer

buffer contains the current buffer object. Setting buffer to Just a
buffer object makes it the head entry in the source's queue. Setting
bufferfor a source in the Stopped or Initial state empties the entire
queue, then appends the one buffer specified (or none at all if Nothing
was specified).

For a source in the Playing or Paused state, setting buffer will result
in the ALInvalidOperation error state being set. buffer can be applied only
to sources in the Initial and Stopped states. Specifying an invalid
buffer name (either because the buffer name doesn't exist or because that
buffer can't be attached to the specified source) will result in an
ALInvalidValue error while specifying an invalid source name results in an
ALInvalidName error. Setting buffer to Nothing is a legal way to release
the current buffer queue on a source in the Initial or Stopped state,
whether the source has just one entry (current buffer) or more. Setting
buffer to Nothing still causes an ALInvalidOperation for any source in
the Playing or Paused state, consequently it cannot be used to mute or
stop a source. The initial value is Nothing.

Queue State Queries

buffersQueued contains the number of buffers in the queue of a given
source. This includes those not yet played, the one currently playing, and
the ones that have been played already. It will contain 0 if buffer has
been set to Nothing.

buffersProcessed contains the number of buffers that have been played
by a given source. Indirectly, this gives the index of the buffer currently
playing. It can be used to determine how much slots are needed for unqueuing
them. On a source in the Stopped state, all buffers are processed. On a
source in the Initial state, no buffers are processed, all buffers are
pending. It will contain 0 if buffer has been set to Nothing.

Bounds on Gain

gainBounds contains two scalar amplitude thresholds between 0 and 1
(included): The minimum guaranteed gain for this source and the maximum gain
permitted, with initial values 0 and 1, respectively At the end of the
processing of various attenuation factors such as distance based attenuation
and sourceGain, the effective gain calculated is compared to these values:

If the effective gain is lower than the minimum gain, the minimum gain is
applied. This happens before the listenerGain is applied. If a zero minimum
gain is set, then the effective gain will not be corrected.

If the effective gain is higher than the maximum gain, the maximum gain is
applied. This happens before the listenerGain is applied. If the
listenerGain times the maximum gain still exceeds the maximum gain the
implementation can handle, the implementation is free to clamp. If a zero
maximum gain is set, then the source is effectively muted. The implementation
is free to optimize for this situation, but no optimization is required or
recommended as setting sourceGain to zero is the proper way to mute a
source.

Distance Model Attributes

referenceDistance is used for distance attenuation calculations based on
inverse distance with rolloff. Depending on the distance model it will also
act as a distance threshold below which gain is clamped. See
Sound.OpenAL.AL.Attenuation for details. The initial value is 1.

rolloffFactor is used for distance attenuation calculations based on
inverse distance with rolloff. For distances smaller than maxDistance (and,
depending on the distance model, larger than referenceDistance), this will
scale the distance attenuation over the applicable range. See
Sound.OpenAL.AL.Attenuation for details how the attenuation is computed as
a function of the distance. The initial value is 1.

In particular, rolloffFactor can be set to zero for those sources that are
supposed to be exempt from distance attenuation. The implementation is
encouraged to optimize this case, bypassing distance attenuation calculation
entirely on a persource basis.

maxDistance is used for distance attenuation calculations based on
inverse distance with rolloff, if the inverse clamped distance model is
used. In this case, distances greater than maxDistance will be clamped to
maxDistance. maxDistance based clamping is applied before minimum gain
clamping (see gainBounds), so if the effective gain at maxDistance is
larger than the minimum gain, the minimum gain will have no effect. No
culling is supported. The initial value is the largest representable
ALfloat.

Frequency Shift by Pitch

pitch contains the desired pitch shift, where 1 (the initial value)
equals identity. Each reduction by 50 percent equals a pitch shift of -12
semitones (one octave reduction). Each doubling equals a pitch shift of 12
semitones (one octave increase). Zero is not a legal value. Implementations
may clamp the actual output pitch range to any values subject to the
implementation's own limits.

Direction and Cone

Each source can be directional, depending on the settings for coneAngles.
There are three zones defined: the inner cone, the outside zone, and the
transitional zone in between. The angle-dependent gain for a directional
source is constant inside the inner cone, and changes over the transitional
zone to the value specified outside the outer cone. sourceGain is applied
for the inner cone, with an application selectable coneOuterGain factor to
define the gain in the outer zone. In the transitional zone
implementation-dependent interpolation between sourceGain and sourceGain
times coneOuterGain is applied.

If direction does not contain the zero vector (Vector3 0 0 0), the
source is directional. The sound emission is presumed to be symmetric around
the direction vector (cylinder symmetry). Sources are not oriented in full 3
degrees of freedom, only two angles are effectively needed.

The zero vector is the initial value, indicating that a source is not
directional. Specifying a non-zero vector will make the source directional.
Specifying a zero vector for a directional source will effectively mark it as
nondirectional.

coneAngles contains the inner and outer angles of the sound cone, in
degrees. The default of 360 for the inner cone angle means that it covers the
entire world, which is equivalent to an omni-directional source. The default
of 360 for the outer cone angle means that it covers the entire world. If the
inner angle is also 360, then the zone for angle-dependent attenuation is
zero.

coneOuterGain contains the factor with which sourceGain is multiplied
to determine the effective gain outside the cone defined by the outer angle.
The effective gain applied outside the outer cone is sourceGain times
coneOuterGain. Changing sourceGain affects all directions, i.e. the
source is attenuated in all directions, for any position of the listener. The
application has to change coneOuterGain as well if a different behavior is
desired.

Offset

secOffset contains the playback position, expressed in seconds (the value
will loop back to zero for looping sources).

When setting secOffset on a source which is already playing, the playback
will jump to the new offset unless the new offset is out of range, in which
case an ALInvalidValue error is set. If the source is not playing, then the
offset will be applied on the next play call.

The position is relative to the beginning of all the queued buffers for the
source, and any queued buffers traversed by a set call will be marked as
processed.

This value is based on byte position, so a pitch-shifted source will have an
exaggerated playback speed. For example, you can be 0.5 seconds into a buffer
having taken only 0.25 seconds to get there if the pitch is set to 2.

sampleOffset contains the playback position, expressed in samples (the
value will loop back to zero for looping sources). For a compressed format,
this value will represent an exact offset within the uncompressed data.

When setting sampleOffset on a source which is already playing, the
playback will jump to the new offset unless the new offset is out of range,
in which case an ALInvalidValue error is set. If the source is not playing,
then the offset will be applied on the next play call. A stop, rewind,
or a second play call will reset the offset to the beginning of the buffer.

The position is relative to the beginning of all the queued buffers for the
source, and any queued buffers traversed by a set call will be marked as
processed.

byteOffset contains the playback position, expressed in bytes (the value
will loop back to zero for looping sources). For a compressed format, this
value may represent an approximate offset within the compressed data buffer.

When setting byteOffset on a source which is already playing, the playback
will jump to the new offset unless the new offset is out of range, in which
case an ALInvalidValue error is set. If the source is not playing, then the
offset will be applied on the next play call. A stop, rewind, or a
second play call will reset the offset to the beginning of the buffer.

The position is relative to the beginning of all the queued buffers for the
source, and any queued buffers traversed by a set call will be marked as
processed.

Queuing Buffers with a Source

OpenAL does not specify a built-in streaming mechanism. There is no mechanism
to stream data into a buffer object. Instead, the API has a more flexible and
versatile mechanism to queue buffers for sources. There are many ways to use
this feature, with streaming being only one of them.

Streaming is replaced by queuing static buffers. This effectively moves any
multi-buffer caching into the application and allows the application to
select how many buffers it wants to use, the size of the buffers, and whether
these are re-used in cycle, pooled, or thrown away.

Looping (over a finite number of repetitions) can be implemented by
explicitly repeating buffers in the queue. Infinite loops can (theoretically)
be accomplished by sufficiently large repetition counters. If only a single
buffer is supposed to be repeated infinitely, using the respective source
attribute loopingMode is recommended.

Loop Points for restricted looping inside a buffer can in many cases be
replaced by splitting the sample into several buffers and queuing the sample
fragments (including repetitions) accordingly.

Buffers can be queued, unqueued after they have been used, and either be
deleted, or refilled and queued again. Splitting large samples over several
buffers maintained in a queue has distinct advantages over approaches that
require explicit management of samples and sample indices.

The application can queue up one or multiple buffer names using
queueBuffers. The buffers will be queued in the sequence in which they
appear in the list.

This command is legal on a source in any playback state (to allow for
streaming, queuing has to be possible on a Playing source).

All buffers in a queue must have the same format and attributes. An attempt
to mix formats or other buffer attributes will result in a failure and an
ALInvalidValue error will be thrown. If the queue operation fails, the source
queue will remain unchanged (even if some of the buffers could have been
queued).

Once a queue entry for a buffer has been appended to a queue and is pending
processing, it should not be changed. Removal of a given queue entry is not
possible unless either the source is stopped (in which case then entire queue
is considered processed), or if the queue entry has already been processed
(Playing or Paused source). A playing source will enter the Stopped
state if it completes playback of the last buffer in its queue (the same
behavior as when a single buffer has been attached to a source and has
finished playback).

The unqueueBuffers command removes a number of buffers entries that have
finished processing, in the order of appearance, from the queue. The
operation will fail with an ALInvalidValue error if more buffers are
requested than available, leaving the destination arguments unchanged.

Managing Source Execution

The execution state of a source can be queried. OpenAL provides a set of
functions that initiate state transitions causing sources to start and stop
execution.

Each source can be in one of four possible execution states: Initial,
Playing, Paused, Stopped. Sources that are either Playing or Paused
are considered active. Sources that are Stopped or Initial are considered
inactive. Only Playing sources are included in the processing. The
implementation is free to skip those processing stages for sources that have
no effect on the output (e.g. mixing for a source muted by zero gain, but not
sample offset increments). Depending on the current state of a source certain
(e.g. repeated) state transition commands are legal NOPs: they will be
ignored, no error is generated.

Contains the current execution state of the given source. The initial state
of any source is Initial.

Note that the Initial state is not necessarily identical to the initial
state in which a source is created, because the other source attributes are
not automatically reset to their initial values. Initial merely indicates
that the source can be executed using the play command. A Stopped or
Initial source can be reset into the default configuration by using a
sequence of source commands as necessary. As the application has to specify
all relevant state anyway to create a useful source configuration, no reset
command is provided.

play applied to an Initial source will promote the source to Playing,
thus the data found in the buffer will be fed into the processing, starting
at the beginning. play applied to a Playing source will restart the
source from the beginning. It will not affect the configuration, and will
leave the source in Playing state, but reset the sampling offset to the
beginning. play applied to a Paused source will resume processing using
the source state as preserved at the pause operation. play applied to a
Stopped source will propagate it to Initial then to Playing
immediately.

pause applied to an Initial source is a legal NOP. pause applied to a
Playing source will change its state to Paused. The source is exempt from
processing, its current state is preserved. pause applied to a Paused
source is a legal NOP. pause applied to a Stopped source is a legal NOP.

stop applied to an Initial source is a legal NOP. stop applied to a
Playing source will change its state to Stopped. The source is exempt
from processing, its current state is preserved. stop applied to a Paused
source will change its state to Stopped, with the same consequences as on a
Playing source. stop applied to a Stopped source is a legal NOP.

rewind applied to an Initial source is a legal NOP. rewind applied to
a Playing source will change its state to Stopped then Initial. The
source is exempt from processing: its current state is preserved, with the
exception of the sampling offset, which is reset to the beginning. rewind
applied to a Paused source will change its state to Initial, with the
same consequences as on a Playing source. rewind applied to an Stopped
source promotes the source to Initial, resetting the sampling offset to the
beginning.