[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