| OpenAL Specification and Reference | ||
|---|---|---|
| <<< Previous | Extensions | Next >>> |
Maintainer: Mike Burrell.
Summary
--------
This is a proposal for a change to the OpenAL API which would allow an
OpenAL application developer ("programmer") to set a range over which an
OpenAL source will loop. Currently, the behaviour of OpenAL is to loop over
the entire buffer associated with the source when looping is enabled; the
proposed change would give the programmer more control over the looping
behaviour.
Applications
-------------
One suggested application of loop points would be for engine noises.
Besides the obvious use of having the sound loop only over the "running"
sound of the engine as opposed to the "starting" sound, changes in
attenuation of the engine can be reflected by dynamically changing the loop
points of the engine sound (if the engine sound were so well created).
Generally, this facility would be useful for two main types of sources:
* a long and generally repetitive sound which has a distinct
beginning to it. Examples would be an explosion, which might
include the sound of the actual explosion at the beginning, and then
go into a short looped sound describing the "settling of the dust".
Using a loop at the end in conjunction with a manual fade-out would
give much more control than having a static sample which is just to
run out;
* a sound which changes attenuation. An example would be an
automobile engine. While simply changing the pitch may (or may not)
be adequate for changes in engine speed, slight differences within a
loop may be emphasised by changing the loop points to reflect other
variables, such as gasoline content in the fuel mixture. These
changes would be hard to implement on the artist's side and can very
well be faked with other techniques (band filters or simple gain,
etc.), and so probably won't be as important as the first use.
Method of Operation
--------------------
Currently, when looping is active, the OpenAL mixer will loop over the
entire buffer. In other words, once it has reached the end of the buffer,
the mixer will reset it to the beginning of the buffer. It is proposed that
this change slightly, so that a beginning and an ending be specified, not
necessarily to correspond with the buffer's actual beginning and ending.
For example, if we were to draw a simple diagram of an automobile engine
sound, with the X-axis representing time:
0.00s 1.00s
-----------------------------------------------------------
| |
-----------------------------------------------------------
engine starts engine develops a rhythm end
looping over the entire buffer would not be practical, since the sound of
the engine starting up over and over again as the engine was "running" would
needless-to-say be very confusing for anyone listening.
One possible solution would be to have two distinct sounds: one of just the
engine running, and one of the engine starting up. However, getting the two
sounds in sync would require much unneeded annoyance, and would require two
separate sources beside.
By definining loop ends points in addition to buffer end points:
0.00s 0.22s 1.00s
-----------------------------------------------------------
| : |
-----------------------------------------------------------
engine starts engine develops a rhythm end
loop start loop end
the engine sound can be used without any of the disadvantages of having two
separate sounds. In this example, first full 1.00s of sound would be
played. After that, only the last 0.78s of the buffer would be looped,
which means that only the sound of the engine running (as opposed to the
engine starting) would be heard.
If the engine were in such a state that the programmer didn't want the last
0.10s of the sound to be heard at that instant, the end loop point can be
changed, so that the diagram would look like so:
0.00s 0.22s 0.90s 1.00s
-----------------------------------------------------------
| : : |
-----------------------------------------------------------
engine starts engine develops a rhythm end
loop start loop end
In this case, if the source is played, the first 0.90s would be played in
full. Then, the sample position would be reset to 0.22s and only the middle
0.68s defined between the two :colons: would be looped over.
The only type of loop supported is what's conventionally called a "forward"
or "linear" or "simple" loop. As soon as the buffer is played its end loop
point, it jumps back to its beginning loop point and continues playing
forward.
The first sample of the loop is played. The last sample of the loop is not
played. In other words, the loop on the range [begin, end). The loop runs
from the beginning _inclusive_ to the end _exclusive_. The end loop point
must be greater than the start loop point; the behaviour is undefined
otherwise. Also, the start point must be less than the length of the
buffer and the end point must be less than or equal to the length of the
buffer; the behaviour is undefined otherwise.
API Changes
------------
Two constants need to be added to the ALenum type. Suggested names are
AL_SOURCE_LOOPSTART and AL_SOURCE_LOOPEND. These could be given the values
0x1010 and 0x1011 respectively in the current OpenAL implementation.
These parameters would be taking parameters of type ALuint. The reasoning
behind this is that the size of the buffer is of type ALuint, and since the
proposed units for LOOPSTART and LOOPEND are in samples, the two types
should correspond. Since no alSource function currently exists to deal with
parameters of type ALuint, new functions need to be declared and defined.
They would have the following prototypes:
void alSourceu(ALuint sid, enum param, ALuint value);
void alGetSourceu(ALuint sid, enum param, ALuint *value);
They function similarly to their alSource and alGetSource siblings, so a
general description of their use isn't needed.
Implementation notes
---------------------
Two fields of type ALuint will be needed to be added to the internal
structure of a Source, representing the beginning and ending loop points
respectively. These two fields should also be able to describe whether or
not the loop points have been set.
At mix-time, if the loop points have not been set, the beginning loop point
should be treated as zero, and the ending loop point should be treated as
the length of the buffer. In other words, if the loop points have not been
set, they should be treated effectively as if they encompass the entire
buffer.
Example use
------------
If he had a Source called ex_source which already had an assigned buffer,
and which to set the loop to be between the 50th sample inclusive and the
400th sample exclusive, simply call:
alSourceu(ex_source, AL_SOURCE_LOOPSTART, 50);
alSourceu(ex_source, AL_SOURCE_LOOPEND, 400);
If the programmers wishes to work in units of time, conversions must take
place. For example, if the mixing rate is known and held in the variable
mixrate, we can use the following calls to set the loop between 0.10s and
0.60s:
alSourceu(ex_source, AL_SOURCE_LOOPSTART, (ALuint)(0.10 * mixrate));
alSourceu(ex_source, AL_SOURCE_LOOPEND, (ALuint)(0.60 * mixrate));
It is also possible to retrieve the current values:
ALuint start_point, end_point;
alGetSourceu(ex_source, AL_SOURCE_LOOPSTART, &start_point);
alGetSourceu(ex_source, AL_SOURCE_LOOPEND, &end_point);
| <<< Previous | Home | Next >>> |
| Compatibility Extensions | Up | Extension Process |