[openal] ALC_SOFT_HRTF proposal (update 2)

Chris Robinson chris.kcat at gmail.com
Wed Oct 7 06:54:54 EDT 2015


This update adds enumeration. The basic idea is that the app first 
queries the number of HRTF data sets available for a device, gets an 
indexed list of strings to display to the user, and requests one by 
index using a context creation or device reset attribute. For example:

ALCdevice *device = alcOpenDevice(NULL);
LPALCGETSTRINGISOFT alcGetStringiSOFT = alcGetProcAddress(
     device, "alcGetStringiSOFT"
);

ALCint hrtf_count;
alcGetIntegerv(device, ALC_NUM_HRTF_SPECIFIER_SOFT, 1, &hrtf_count);

printf("Available HRTFs:\n");
for(int i = 0;i < hrtf_count;++i)
{
     const ALCchar *name = alcGetStringiSOFT(device,
         ALC_HRTF_SPECIFIER_SOFT, i
     );
     printf("%d: %s\n", i, name);
}
printf("Please select an HRTF...");
int id = GetUserSelection();

ALCint attrs[] = {
     ALC_HRTF_SOFT, ALC_TRUE,
     ALC_HRTF_ID_SOFT, id,
     0
};
context = alcCreateContext(device, attrs);
...

This still feels a little weird since it doesn't seem like specific 
HRTFs should be a per-app selection. I'd think a user would want to set 
one that best suits them and have all apps use it when HRTF is used, 
rather than having to select it in each app.

But regardless, please let me know what you think. If there's any issues 
relating to the functionality of the extension, or if you're confused or 
concerned about something in the extension spec, please speak up.
-------------- next part --------------
Name

    ALC_SOFT_HRTF

Contributors

    Chris Robinson

Contact

    Chris Robinson (chris.kcat 'at' gmail.com)

Status

    In progress.

Dependencies

    This extension is written against the OpenAL 1.1 specification.

Overview

    This extension allows an application to request and determine the status
    of HRTF mixing. HRTF, or Head-Related Transfer Function, is a method of
    mixing 3D audio for "true" 3D panning, typically using filters designed to
    simulate how sound is affected by a listener's head as the sound waves
    travel between the ears.

    As a 3D sound API, OpenAL's design allows implementations to render audio
    using HRTF. In fact, a few well-known implementations can already do this.
    However, currently the OpenAL API has no concept of HRTF so there is no
    way to query if it is being used, and no way for an application to request
    it on behalf of the user. This aims to fix that.

Issues

    Q: If implementations can already use HRTF, why is an extension needed?
    A: Although implementations can use HRTF, there is no way for the app to
       know if it's being used. At the very least, an app may want to alert
       the user to whether HRTF is in-use or not, and why it's being used or
       not.

       Additionally, a user may not know how to enable HRTF through a given
       implementation's configuration, and it is not always possible for an
       implementation to detect when HRTF should be used.

       It should be noted that the request is only a hint, so if an
       implementation needs to ignore the request for whatever reason, it can,
       and still provide feedback to the app about why.

    Q: It is not unlikely for an implementation to be able to provide multiple
       different HRTFs for different purposes (head measurements, quality,
       etc). How is this handled?
    A: An enumeration API is introduced. Applications that don't care about
       specific HRTFs don't need to use it and can let OpenAL pick a default.

    Q: What is the purpose of alcResetDeviceSOFT?
    A: An app will undoubtedly want the ability to enable and disable HRTF at
       runtime (for example, in response to in-game option changes). The
       normal way of enabling HRTF would be with the attribute list to
       alcCreateContext, however this is clunky if audio playback is already
       started; the app would either need to destroy the current context and
       create a new one with the new parameters, or create a context just for
       the side-effect of changing the device properties and then not use it
       for anything.

       A method just to reset the device properties seems the most elegant
       solution, as it would not interrupt existing contexts and it would not
       rely on side-effects of function behaviors which may not be reliable.

New Procedures and Functions

    const ALCchar *alcGetStringiSOFT(ALCdevice *device, ALCenum paramName,
                                     ALCsizei index);

    ALCboolean alcResetDeviceSOFT(ALCdevice *device, const ALCint *attrList);

New Tokens

    Accepted as part of the <attrList> parameter of alcCreateContext and
    alcDeviceResetSOFT, and as the <paramName> parameter of alcGetIntegerv:

        ALC_HRTF_SOFT                            0x1992

    Accepted as part of the <attrList> parameter of alcCreateContext and
    alcDeviceResetSOFT:

        ALC_HRTF_ID_SOFT                         0x1996

    Accepted as part of the <attrList> parameter of alcCreateContext and
    alcDeviceResetSOFT, for the ALC_HRTF_SOFT attribute:

        ALC_DONT_CARE_SOFT                       0x0002

    Accepted as the <paramName> parameter of alcGetIntegerv:

        ALC_HRTF_STATUS_SOFT                     0x1993
        ALC_NUM_HRTF_SPECIFIER_SOFT              0x1994

    Accepted as the <paramName> parameter of alcGetString and
    alcGetStringiSOFT:

        ALC_HRTF_SPECIFIER_SOFT                  0x1995

    Possible results from a ALC_HRTF_STATUS_SOFT query:

        ALC_HRTF_DISABLED_SOFT                   0x0000
        ALC_HRTF_ENABLED_SOFT                    0x0001
        ALC_HRTF_DENIED_SOFT                     0x0002
        ALC_HRTF_REQUIRED_SOFT                   0x0003
        ALC_HRTF_HEADPHONES_DETECTED_SOFT        0x0004
        ALC_HRTF_UNSUPPORTED_FORMAT_SOFT         0x0005


Additions to Specification

    Resetting a device

    After a device is opened for playback, an application may reset it to
    attempt changing the playback properties. To reset the device, use the
    function

    ALCboolean alcResetDeviceSOFT(ALCdevice *device, const ALCint *attrList);

    The device parameter is a handle to a valid playback device as returned by
    alcOpenDevice, otherwise the call fails and an ALC_INVALID_DEVICE error is
    generated. The attrList is the same as what could be passed to
    alcCreateContext. The AL is allowed to ignore attributes and attribute
    value combinations the device cannot support, for example if the device
    doesn't support the requested ALC_FREQUENCY value, another value it does
    support may be set.

    On success the function returns ALC_TRUE, and on failure the function
    returns ALC_FALSE. Note that a return of ALC_TRUE does not indicate any
    attributes were honored, just that the device was successfully reset. If
    you need to know what the attributes are after a reset, query the device
    using alcGetIntegerv with the relevant attributes.


    HRTF mixing

    An application may request mixing using a Head-Related Transfer Function,
    or HRTF. HRTF can provide better spatial acuity when using headphones by
    using special filters designed to replicate how sounds are affected by the
    shape of the listener's head as they come in from a given direction. To
    request HRTF, specify the ALC_HRTF_SOFT attribute to alcCreateContext or
    alcResetDeviceSOFT with the value ALC_TRUE.

    ALCint attrs[] = {
        ALC_HRTF_SOFT, ALC_TRUE, /* request HRTF */
        0 /* end of list */
    };
    context = alcCreateContext(device, attrs);

    Specifying the value ALC_FALSE will request no HRTF mixing. The default
    value of ALC_DONT_CARE_SOFT will allow the AL to determine for itself
    whether HRTF should be used or not, depending on the detected device port
    or form factor, format, etc.

    Requesting HRTF mixing may cause the AL to reconfigure the device for a
    specific output mode and restrict the usable frequency values.

    A word of warning: although HRTF can sound great with headphones, it may
    result in increased resource usage and it may not sound very good with
    ordinary speakers, particularly if the user has surround sound output.
    Consequently, it is not a good idea to unconditionally request HRTF
    mixing. A good rule of thumb is to not specify an ALC_HRTF_SOFT attribute
    by default (or instead use the ALC_DONT_CARE_SOFT value), letting the AL
    autoselect it as appropriate, unless the user indicates otherwise.


    HRTF enumeration and selection

    Each AL device has a list of HRTFs it has access to. Applications may
    query this list by first querying the ALC_NUM_HRTF_SPECIFIER_SOFT property
    using the alcGetIntegerv function with a given device.

    ALCint hrtf_count;
    alcGetIntegerv(device, ALC_NUM_HRTF_SPECIFIER_SOFT, 1, &hrtf_count);

    This query acts as an enumeration point, allowing the device to refresh
    the list of HRTFs it may use.

    To get a human-readable string for each HRTF, use the function

    const ALCchar *alcGetStringiSOFT(ALCdevice *device, ALCenum paramName,
                                     ALCsizei index);

    The device handle must be the same one that previously queried the number
    of HRTF specifiers, have <paramName> set to ALC_HRTF_SPECIFIER_SOFT, and
    specify an index between 0 (inclusive) and the previously-queried HRTF
    count (exclusive). The returned string will be an implementation-defined
    UTF-8 encoded specifier for the given HRTF index, designed for display to
    the user. The returned strings are valid until the next enumeration point.

    Selecting an HRTF is done by specifying the ALC_HRTF_ID_SOFT attribute to
    alcCreateContext or alcResetDeviceSOFT with the index of the desired HRTF.

    ALCint attrs[] = {
        ALC_HRTF_SOFT, ALC_TRUE, /* request HRTF */
        ALC_HRTF_ID_SOFT, index,
        0 /* end of list */
    };
    context = alcCreateContext(device, attrs);

    If the specified HRTF cannot be used, the AL may select another instead.
    Note: the ALC_HRTF_ID_SOFT attribute is separate from the ALC_HRTF_SOFT
    attribute. ALC_HRTF_ID_SOFT merely suggests which HRTF to use if it's
    used, while ALC_HRTF_SOFT specifies how OpenAL should decide to use HRTF.

    To query which HRTF is being used, call alcGetString with the
    ALC_HRTF_SPECIFIER_SOFT parameter on the device. Rather than querying the
    ID value, which can change in between enumerations, the application
    instead queries the string specifier which remains constant for the
    device. The returned string remains valid until the device is reset,
    closed, or has a new context created on it.


    HRTF status query

    An easy way to query HRTF status is to simply call alcGetIntegerv with the
    ALC_HRTF_SOFT attribute. This will respond with ALC_TRUE if HRTF is in use
    on the device, or ALC_FALSE if not (note that it will not give back
    ALC_DONT_CARE_SOFT even if that was specified during context creation or
    device reset).

    More detailed status info can be obtained by calling alcGetIntegerv with
    the ALC_HRTF_STATUS_SOFT parameter. This may respond with one of the
    following values:

    ALC_HRTF_DISABLED_SOFT - HRTF is disabled (generic response).
    ALC_HRTF_ENABLED_SOFT - HRTF is enabled (generic response).
    ALC_HRTF_DENIED_SOFT - HRTF is disabled because it's not allowed on the
                           device. This may be caused by invalid resource
                           permissions, or other user configuration that
                           disallows HRTF.
    ALC_HRTF_REQUIRED_SOFT - HRTF is enabled because it must be used on the
                             device. This may be caused by a device that can
                             only use HRTF, or other user configuration that
                             forces HRTF to be used.
    ALC_HRTF_HEADPHONES_DETECTED_SOFT - HRTF is enabled automatically because
                                        the device reported headphones.
    ALC_HRTF_UNSUPPORTED_FORMAT_SOFT - HRTF is disabled because the device
                                       does not support it with the current
                                       format. Typically this is caused by
                                       non-stereo output or an incompatible
                                       output frequency.

    This is not an exhaustive list; extensions may add more status values in
    the future, so an application must be prepared to handled unknown
    status values.

Errors


More information about the openal mailing list