[openal] Programmatic access to sounds played through OpenAL

Chris Robinson chris.kcat at gmail.com
Sat Jul 18 06:32:49 EDT 2020


On Sat, 18 Jul 2020 01:58:04 -0700
Aleksei Petrenko <petrenko at usc.edu> wrote:

> My question is, is it possible to get programmatic access to the
> sounds played during every particular frame of the game?
> 
> An example to be more concrete. Let's say the normal framerate of the
> game is 60FPS. I am running the game 10 times faster than realtime,
> so at 600FPS (10x is not important, I want to run the game as fast as
> hardware allows, the exact speedup is not known). At some point, a
> game event triggers a sound that under normal circumstances would
> play for 1 second, so for 60 game ticks. In my fast simulation it
> only lasts 0.1 seconds, and the same 60 game ticks.

Hi.

With OpenAL Soft's ALC_SOFT_loopback extension, it should be possible
to do this, as long as you're able to modify your program's source. If
the ALC_SOFT_loopback extension is supported, you can get the
alcLoopbackOpenDeviceSOFT function (with alcGetProcAddress), and create
an ALCdevice using that. Specify the render format you want when calling
alcCreateContext, and the normal AL functions can be used as normal when
the context is made current.

At that point, you're in control of when and how fast samples are
mixed. Call alcRenderSamplesSOFT to render samples and fill in your
provided buffer. Ideally you'd render ~20ms worth of samples per call
(512 to 1024 sample frames at 44100hz), but any size can work and it
can be called as often as your CPU allows. So for example:

#include "alext.h"

LPALCLOOPBACKOPENDEVICESOFT alcLoopbackOpenDeviceSOFT;
LPALCRENDERSAMPLESSOFT alcRenderSamplesSOFT;

...sound initialization...
if(!alcIsExtensionPresent(NULL, "ALC_SOFT_loopback"))
{
    error("Loopback not supported");
    abort();
}

alcLoopbackOpenDeviceSOFT = alcGetProcAddress(NULL,
    "alcLoopbackOpenDeviceSOFT");
alcRenderSamplesSOFT = alcGetProcAddress(NULL, "alcRenderSamplesSOFT");

ALCdevice *device = alcLoopbackOpenDeviceSOFT(NULL);
ALCint attrs[] = {
    /* Standard 16-bit stereo 44.1khz. Can change as desired. */
    ALC_FORMAT_TYPE_SOFT, ALC_SHORT_SOFT,
    ALC_FORMAT_CHANNELS_SOFT, ALC_STEREO_SOFT,
    ALC_FREQUENCY, 44100,

    /* end-of-list */
    0
};
ALCcontext *context = alcCreateContext(device, attrs);
alcMakeContextCurrent(context);

...in main loop...
    ..make normal AL update calls..

    /* Ensure 'buffer' can hold 1024 sample frames when calling (4096
     * bytes for 16-bit stereo). */
    alcRenderSamplesSOFT(device, buffer, 1024);

    ..1024 sample frames are now in 'buffer'..
...

The above main loop can run faster than real-time. An AL call made after
rendering 44100 sample frames would act as if it was made after one
second of playback. If all the resulting samples are concatenated and
played back at normal speed, it would sound indistinguishable from
normal device playback. See
<https://openal-soft.org/openal-extensions/SOFT_loopback.txt> for more
information about the extension.


More information about the openal mailing list