[Openal-devel] Initial AL_SOFT_buffer_samples proposal
Chris Robinson
chris.kcat at gmail.com
Thu Mar 17 09:34:32 PDT 2011
This is an extension to bring out some of the capabilities I mentioned in the
OpenAL Soft 1.13 release message. It adds a flexible method for specifying,
updating, and retrieving buffer data. It is currently a SOFT proposal, but if
anyone else is interested in implementing it, changing it to EXT would be a
good idea.
One thing to note is that this encapsulates AL_EXT_FLOAT32, AL_EXT_MCFORMATS,
and, to a limited extent, AL_EXT_DOUBLE. It also provides the same
capabilities offered by AL_SOFT_buffer_sub_data (that is, updating a playing
buffer).
The one thing I'm not really sure about is what kind of data the 'rear'
formats are supposed to specify. Is it supposed to be a single back-center
channel (which seems a bit silly since you can place a source behind the
listener for the same effect), or is it interleaved back-left,back-right
(which I haven't really heard of before)? Or something else?
Anyway, here's the current draft. Let me know your thoughts. :)
Name
AL_SOFT_buffer_samples
Contributors
Chris Robinson
Contact
Chris Robinson (chris.kcat 'at' gmail.com)
Status
In progress
Dependencies
This extension is for OpenAL 1.1.
This extension interacts with AL_SOFT_loop_points.
This extension interacts with AL_SOFT_buffer_sub_data.
This extension trivially interacts with AL_EXT_FLOAT32.
This extension trivially interacts with AL_EXT_MCFORMATS.
Overview
This extension provides a more flexible mechanism for loading buffer data,
as well as a method to retrieve buffer data. Unextended OpenAL only
provides a method to specify a single buffer format when loading data,
which defines the data given by the application. The AL is given leeway in
converting the data, so that it is possible or more efficient to use
internally. However, there are some drawbacks to this approach:
* The conversion done by the implementation is hidden from the app. This
makes it difficult for the app to know what kind of precision it will
have, and impossible to request a storage precision.
* The formats allowed are typically only what can be handled by the
hardware or mixer, which places the burden of conversion on the
application.
If the application could specify the internal storage format, as well as
use separate enum values to specify the incoming data format, it would
allow to add more standard formats (32-bit int and float, for example),
with no undue burden placed on the implementation beyond needing some
conversion routines. This is because the internal formats can be
restricted to a sane subset the implementation can handle, and the input
data would be converted to it.
Issues
Q: Should this extension be an EXT or SOFT?
A: For the time being, SOFT. However, if there's interest from other
implementations, it can be changed to EXT.
Q: How should an application query the supported storage formats?
A: Using alIsBufferFormatSupportedSOFT. Traditionally, checking for
supported formats was done by calling alGetEnumValue with the
stringified format enum, but this was a sub-par solution. An explicit
query returning a true/false boolean is much cleaner.
Q: Can an internal format's channel configuration differ from the input
channel configuration (eg, AL_QUAD16 storage with AL_STEREO input)?
A: Not in this extension. It will result in an AL_INVALID_ENUM error. A
future extension should be expected to lift this restriction and define
what kind of channel mapping should occur.
Q: How are sample lengths and offsets specified?
A: Using sample frames related to the buffer's storage format.
Q: What can be said about AL_BYTE_OFFSET and the like, which normally
would be adjusted to the specified input format?
A: They are adjusted according to the storage format of the buffer. Given
that the application explicitly requests the storage format, there is
no need to base it on anything else.
Q: Should this extension be allowed to modify playing buffers?
A: alBufferSubSamplesSOFT and alGetBufferSamplesSOFT can be called on
playing buffers, but not alBufferSamplesSOFT. As a consequence, it
shares the AL_BYTE_RW_OFFSETS_SOFT and AL_SAMPLE_RW_OFFSETS_SOFT source
properties with AL_SOFT_buffer_sub_data.
New Procedures and Functions
void alBufferSamplesSOFT(ALuint buffer, ALuint samplerate,
ALenum internalformat, ALsizei frames,
ALenum channels, ALenum type,
const ALvoid *data);
void alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei frames,
ALenum channels, ALenum type,
const ALvoid *data);
void alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei frames,
ALenum channels, ALenum type, ALvoid *data);
ALboolean alIsBufferFormatSupportedSOFT(ALenum format);
New Tokens
Accepted by the <internalformat> parameter of alBufferSamplesSOFT (values
are shared with standard OpenAL, AL_EXT_FLOAT32, and AL_EXT_MCFORMATS):
AL_MONO8 0x1100
AL_MONO16 0x1101
AL_MONO32F 0x10010
AL_STEREO8 0x1102
AL_STEREO16 0x1103
AL_STEREO32F 0x10011
AL_QUAD8 0x1204
AL_QUAD16 0x1205
AL_QUAD32F 0x1206
AL_REAR8 0x1207
AL_REAR16 0x1208
AL_REAR32F 0x1209
AL_5POINT1_8 0x120A
AL_5POINT1_16 0x120B
AL_5POINT1_32F 0x120C
AL_6POINT1_8 0x120D
AL_6POINT1_16 0x120E
AL_6POINT1_32F 0x120F
AL_7POINT1_8 0x1210
AL_7POINT1_16 0x1211
AL_7POINT1_32F 0x1212
Accepted by the <channels> parameter of alBufferSamplesSOFT,
alBufferSubSamplesSOFT, and alGetBufferSamplesSOFT:
AL_MONO ???
AL_STEREO ???
AL_QUAD ???
AL_REAR ???
AL_5POINT1 ???
AL_6POINT1 ???
AL_7POINT1 ???
Accepted by the <type> parameter of alBufferSamplesSOFT,
alBufferSubSamplesSOFT, and alGetBufferSamplesSOFT:
AL_BYTE ???
AL_UNSIGNED_BYTE ???
AL_SHORT ???
AL_UNSIGNED_SHORT ???
AL_INT ???
AL_UNSIGNED_INT ???
AL_FLOAT ???
AL_DOUBLE ???
Accepted by the <paramName> parameter of alGetSourceiv and alGetSourcefv
(these are the same as in AL_SOFT_buffer_sub_data):
AL_BYTE_RW_OFFSETS_SOFT 0x1031
AL_SAMPLE_RW_OFFSETS_SOFT 0x1032
Additions to Specification
A New Way To Specify Buffer Data
To remove a buffer's sample data and replace it with new data, the
function
void alBufferSamplesSOFT(ALuint buffer, ALuint samplerate,
ALenum internalformat, ALsizei frames,
ALenum channels, ALenum type,
const ALvoid *data);
should be used. The named <buffer> must be a buffer ID returned by
alGenBuffers, and not currently be attached or queued on a source. The
given <samplerate> is the number of samples per second the data plays at,
and the <internalformat> is the storage format used (see table 1.0). The
number of sample frames to load is specified by <frames>.
The <channels> and <type> parameters specify the channel configuration and
sample type of the provided data (see Table 1.1 and 1.2), and will be
converted to the internal storage format as needed. The channel
configuration, however, must match the channel configuration of the
storage format or an AL_INVALID_ENUM error is generated.
The <data> pointer should hold enough data as specified by the <channels>,
<type>, and <frames> parameters. It may also be NULL, in which case the
stored data will be undefined.
If AL_SOFT_loop_points is supported, a successful call will reset the
start and end loop points to 0 and <frames> respectively.
Table 1.0. Storage formats
Format Configuration Size and type
------------- ------------- -------------
AL_MONO8 Mono 8-bit int
AL_MONO16 Mono 16-bit int
AL_MONO32F Mono 32-bit float
AL_STEREO8 Stereo 8-bit int
AL_STEREO16 Stereo 16-bit int
AL_STEREO32F Stereo 32-bit float
AL_QUAD8 Quad 8-bit int
AL_QUAD16 Quad 16-bit int
AL_QUAD32F Quad 32-bit float
AL_REAR8 Rear 8-bit int
AL_REAR16 Rear 16-bit int
AL_REAR32F Rear 32-bit float
AL_5POINT1_8 5.1 8-bit int
AL_5POINT1_16 5.1 16-bit int
AL_5POINT1_32F 5.1 32-bit float
AL_6POINT1_8 6.1 8-bit int
AL_6POINT1_16 6.1 16-bit int
AL_6POINT1_32F 6.1 32-bit float
AL_7POINT1_8 7.1 8-bit int
AL_7POINT1_16 7.1 16-bit int
AL_7POINT1_32F 7.1 32-bit float
These specify the channel configuration and precision of the buffer's
internal storage. The details of these formats (eg, signedness of
samples, channel order, and whether or not the data is interleaved) is
implementation defined.
Table 1.1. Interleaved channel configurations
Name Configuration Order
----------- ------------- ----------------------------------------------
AL_MONO Mono mono
AL_STEREO Stereo front-left, front-right
AL_QUAD Quad front-left, front-right, rear-left, rear-right
AL_REAR Rear rear-left, rear-right (???)
AL_5POINT1 5.1 front-left, front-right, front-center, lfe,
rear-left, rear-right
AL_6POINT1 6.1 front-left, front-right, front-center, lfe,
rear-center, side-left, side-right
AL_7POINT1 7.1 front-left, front-right, front-center, lfe,
rear-left, rear-right, side-left, side-right
Channel configurations that can be loaded into a buffer. As long as the
base configuration (Mono, Stereo, etc) matches the storage, the data can
be loaded, and the sample data will be re-ordered and de-interleaved as
needed.
Table 1.2. Sample types
Type Data type Nominal value range
----------------- --------- -------------------------
AL_BYTE ALbyte -128...+127
AL_UNSIGNED_BYTE ALubyte 0...+255
AL_SHORT ALshort -32768...+32767
AL_UNSIGNED_SHORT ALushort 0...+65535
AL_INT ALint -2147483648...+2147483647
AL_UNSIGNED_INT ALuint 0...+4294967295
AL_FLOAT ALfloat -1.0...+1.0
AL_DOUBLE ALdouble -1.0...+1.0
Data types and value ranges of loadable sample formats. These values are
normalized, so the ALubyte range of 0...255 corresponds to the same range
of ALshort's -32768...+32767. ALfloat and ALdouble samples may specify
values outside of their nominal range, but will be clamped as needed by
the implementation (eg, when converting to a non-float type).
To query if a storage format is supported by the implementation, use the
function
ALboolean alIsBufferFormatSupportedSOFT(ALenum format);
The function returns AL_FALSE if the given <format> is not a recognized
storage format. Otherwise, if it returns AL_TRUE it may be specified as
the <internalformat> for alBufferSamplesSOFT.
To update a buffer with new data, call
void alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei frames,
ALenum channels, ALenum type,
const ALvoid *data);
<buffer> is the ID of the buffer to modify. <offset> is the first sample
frame in the internal storage to be modified, and <frames> is the number
of sample frames to modify. They must not extend beyond the existing
internal storage length. The <channels> and <type> specify the channel
configuration and sample type of the provided data, and will be converted
to the internal format previously specified. As with alBufferSamplesSOFT,
the channel configuration must match the storage format's channel
configuration or an AL_INVALID_ENUM error is generated.
When modifying a buffer that's playing on a source, an application must
take care to not modify the section that is currently being played. The
read-only source attributes
AL_BYTE_RW_OFFSETS_SOFT
AL_SAMPLE_RW_OFFSETS_SOFT
may be used to retrieve the read and write cursor offsets (see Table 2.0
and 2.1). Behavior is undefined if an attempt is made to modify buffer
data between the read and write offsets.
Table 2.0. Source AL_SAMPLE_RW_OFFSETS_SOFT Attribute
Name Signature Values Default
------------------------- --------- ----------- -------
AL_SAMPLE_RW_OFFSETS_SOFT fv, iv [0.0f, any] N/A
Query only. Queries the current read and write cursor offsets, expressed
in samples (the values will loop back to 0 for looping sources). For a
compressed format, these values will represent an exact offset within the
uncompressed data.
The two offset values are relative to the beginning of all the queued
buffers for the source. The first value returned in the array is the
offset to the sample currently being read by the AL. The second value is
the offset an application may safely write to with an
alBufferSubSamplesSOFT call.
If the source is not in an AL_PLAYING state, the read and write offsets
will be the identical.
Table 2.1. Source AL_BYTE_RW_OFFSETS_SOFT Attribute
Name Signature Values Default
----------------------- --------- ----------- -------
AL_BYTE_RW_OFFSETS_SOFT fv, iv [0.0f, any] N/A
Query only. Queries the current read and write cursor offsets, expressed
in bytes (the values will loop back to 0 for looping sources). For a
compressed format, these values may represent an approximate offset within
the compressed data buffer.
The two offset values are relative to the beginning of all the queued
buffers for the source. The first value returned in the array is the
offset to the data block currently being read by the AL. The second value
is the byte offset an application may safely write to.
If the source is not in an AL_PLAYING state, the read and write offsets
will be the identical.
To retrieve a buffer's sample data, use
void alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei frames,
ALenum channels, ALenum type, ALvoid *data);
This function will read the number of sample frames, given by <frames>,
starting at <offset>, and convert them to the channel configuration and
sample type specified, before writing to the provided <data> buffer
pointer. An AL_INVALID_VALUE error is generated if <offset> and <frames>
reach beyond the the internal storage. The channel configuration must
match the internal storage format's channel configuration, or else an
AL_INVALID_ENUM error is generated.
Errors
The error AL_INVALID_OPERATION is generated if alBufferSamplesSOFT is
called with a buffer that's attached or queued on a source.
The error AL_INVALID_ENUM is generated if the configuration specified by
<channels> does not match the buffer's storage format's channel
configuration.
The error AL_INVALID_VALUE is generated if alBufferSubSamplesSOFT or
alGetBufferSamplesSOFT is called with values for <offset> and <frames>
that specify a segment that is beyond the range of the buffer.
More information about the Openal-devel
mailing list