2-Apr-1999 This is
the original spec, as sent to me by Terry Sikes (I'm
sorry for all those places where the source-code
tabulations were lost. ForntPage Express woes...):
Open Audio Library Requirements
Mission Statement: The Open Audio Library (OpenAL) is
intended to provide an open, cross-platform audio
capability suitable for professional game development
purposes (it may well be applicable to many other
application domains). It is a mid-level library primarily
intended to sit on top of existing low-level sound APIs.
Initial implementations will focus on sound output
capabilities (sampled, MIDI and CD audio), but the
architecture will be flexible enough to handle sound
input as well.
OpenAL uses a C API for portability and cross-language
capability.
OpenAL is thread safe on those platforms that support
threads.
OpenAL calls native libraries when possible.
OpenAL uses sound format(s) native to the target
platform. Possibly support for a single cross-platform
format could be provided later.
OpenAL provides mixing of sampled audio. Maximum
number of channels should be queryable.
OpenAL provides the following 2D capabilities for
mixed sampled sounds:
- Volume control
- Panning
- Looping
- Priority
OpenAL provides the following 3D capabilities for
mixed sampled sounds:
- Absolute volume control
- 3D position relative to listener
- Velocity relative to listener (Doppler)
- Looping
- Priority
OpenAL supports MIDI and CD audio playback.
All outputs may be queried for current status
information.
Open Audio API
This is a first cut at a possible 2D audio interface.
/* Types */
OA_ENGINE_STATE /* Struct containing state
information for sound */
/*
engine. */
OA_INIT_INFO /* Struct containing initialization
information. */
/*
In particular, it may provide/return information
*/
/*
about system latency/performance/outputs. */
OA_OUTPUT /* Struct containing all information
pertaining to */
/*
a particular sound output. Examples of sound */
/*
outputs include hardware mixers, software mixers,
*/
/*
and MIDI playback devices. */
OA_INPUT /* Struct containing all information
pertaining to */
/*
a particular sound input. Examples of sound
inputs */
/*
include audio samples and MIDI streams. */
OA_SOUND /* Struct containing in-memory
representation of */
/*
a sound */
/*
sample, as well as state information for that */
/*
sound. */
/* Initialize Open Audio system.
*/
INT32 oaInitEngine(OA_ENGINE_STATE &state,
OA_INIT_INFO &initInfo);
/* Open an audio output. Default behavior would
be to get the "best"
output device (possibly user preference) capable
of playing that type of
sound. Digital audio and MIDI would be initially
supported.
outputType could be MIDI or SAMPLED.
Perhaps we need something like:
oaSetOutputPreference(&output,
16_BIT_32_VOICE_MIN);
to specify specific minimum requirements etc.
Also, what are the issues
with multiple soundcards? Should we provide an
enumeration function?
*/
INT32 oaOpenOutput(OA_ENGINE_STATE &state,
OA_OUTPUT &output, INT32 outputType);
/* Clean up and release all resources associated
with this output.
*/
INT32 oaCloseOutput(OA_OUTPUT &output);
/* Set overall output volume.
0 is minimum, 10000 is maximum.
*/
INT32 oaOutputVolume(OA_OUTPUT &output, INT32
volume);
/* Set overall output pan.
-10000 is full left, 10000 is full right.
*/
INT32 oaOutputPan(OA_OUTPUT &output, INT32
panLevel);
/* Open a sound independent of a specific output.
Flags include:
OA_CACHE - cache sound into memory if applicable
This should probably be reference counted, so it
can't be destroyed while
sound instances are playing.
The final OA_OUTPUT handle
*/
INT32 oaOpenInput(OA_INPUT &soundInput, char
*soundPath, INT32 soundType, INT32 flags);
/* Hint that the sound input should be hardware
accelerated if possible
on a particular output device.
*/
INT32 oaOptimizeInput(OA_OUTPUT &output,
OA_INPUT &input);
/* Close a sound input.
*/
INT32 oaCloseInput(OA_INPUT &soundInput);
/* Create a sound instance, using a particular
input and output.
*/
INT32 oaCreateSound(OA_SOUND &sound,
OA_OUTPUT &output, OA_INPUT &input);
/* Play a sound on the mixer.
Priorities range from 0 (highest) to 32 (lowest)
Flag bits include OA_LOOP, flag indicating that
sound should be looped
until stopped.
*/
INT32 oaPlaySound(OA_SOUND &sound);
/* Change the volume of this sound.
volume of 0 is silent, 10000 is maximum (linear
scale).
*/
INT32 oaSetVolume(OA_SOUND &sound, INT32
volume);
/* Pan the sound.
panLevel of -10000 is fully panned left, 10000 is
fully right.
*/
INT32 oaSetPan(OA_SOUND &sound, INT32
panLevel);
/* Stop a sound that's currently playing.
*/
INT32 oaStopSound(OA_SOUND &sound);
/* Returns current volume of sound.
*/
INT32 oaGetVolume(OA_SOUND &sound);
/* Returns current pan position of sound.
*/
INT32 oaGetPan(OA_SOUND &sound);
/* Returns current mixer position in the sound in
ms.
-1 if sound is not playing.
*/
INT32 oaGetSoundPos(OA_SOUND &sound);
/* Returns length of the sound in ms.
*/
INT32 oaGetSoundLen(OA_SOUND &sound);
/* Returns current sound priority.
*/
INT32 oaGetSoundPriority(OA_SOUND &sound);
/* Check on sampled sound output status.
OA_SAMPLED_STATUS needs to be defined.
Some of the information returned should include:
Number of samples currently playing.
Number of total channels available.
What else?
*/
INT32 oaSampledOutputStatus(OA_OUTPUT
&output, OA_SAMPLED_STATUS &status);
/* Sound mixing engine.
Must be called with a certain frequency (as
reported by oaInit())
to ensure that artifacts aren't heard, and
maximum latency is
satisfied. Should be able to reside on separate
thread from rest
of program, in multithreaded environments.
*/
INT32 oaSoundEngine(OA_ENGINE_STATE &state); |
Usage Example
#define
CHANNEL_COUNT 4
INT32 channels[CHANNEL_COUNT] = { /* Rest of
mixer channels */
3, 4, 2, 2 /* to floating pool. */
/* Channel 0 is floating pool, */
/* channel assignments are one based. */
}
int main(int argc, char *argv[]) {
OA_STATE state;
OA_INIT_INFO initInfo;
OA_OUTPUT mixer;
OA_INPUT dingFile;
OA_SOUND ding;
.
.
.
/* Somewhere during initialization... */
status = oaInit(&state, &initInfo);
status = oaOpenOutput(&state, &mixer,
OA_WAVE_OUTPUT);
status = oaDefineChannels(&mixer,
&channels, CHANNEL_COUNT);
status = oaOpenInput(&dingFile,
"ding.wav", OA_WAVE_SOUND, OA_CACHE);
status = oaOptimizeInput(&dingFile,
&mixer); /* Hardware mix if possible */
status = oaCreateSound(&ding, &mixer,
&dingFile); /* Error if mismatch. */
/* Sets prio 16, */
/* channel floating pool */
/* by default. */
status = oaPriority(&ding, 24);
status = oaChannel(&ding, 3);
oaSetVolume(&ding, 7000);
status = oaPlaySound(&ding); /* prio 24,
channel 3 */
.
.
.
/* Perhaps on another thread... */
status = oaSoundEngine(&state);
.
.
.
OA_OUTPUT midi;
OA_SOUND jam;
/* Play MIDI */
status = oaOpenOutput(&state, &midi,
OA_MIDI_OUTPUT);
status = oaOpenInput(&jamFile,
"jam.mid", OA_MIDI_SOUND, 0);
status = oaCreateSound(&jam, &midi,
&jamFile);
oaSetVolume(&jam, 5000);
status = oaPlaySound(&jam);
.
.
.
return (0);
} |
|