Managing Rendering Contexts

All operations of the AL core API affect a current AL context. Within the scope of AL, the ALC is implied - it is not visible as a handle or function parameter. Only one AL Context per INprocess can be current at a time. Applications maintaining multiple AL Contexts, whether threaded or not, have to set the current context accordingly. Applications can have multiple threads that share one more or contexts. In other words, AL and ALC are threadsafe.

The default AL Context interoperates with a hardware device driver. The application manages hardware and driver resources by communicating through the ALC API, and configures and uses such Contexts by issuing AL API calls. A default AL Context processes AL calls and sound data to generate sound output. Such a Context is called a Rendering Context. There might be non-rendering contexts in the future.

The word "rendering" was chosen intentionally to emphasize the primary objective of the AL API - spatialized sound - and the underlying concept of AL as a sound synthesis pipeline that simulates sound propagation by specifying spatial arrangements of listeners, filters, and sources. If used in describing an application that uses both OpenGL and AL, "sound rendering context" and "graphics rendering context" should be used for clarity. Throughout this document, "rendering" is used to describe spatialized audio synthesis (avoiding ambiguous words like "processing", as well as proprietary and restrictive terms like "wavetracing").

Context Attributes

The application can choose to specify certain attributes for a context. Attributes not specified explicitely are set to implementation dependend defaults.

Table 1. Context Attributes

NameDescription
ALC_FREQUENCYFrequency for mixing output buffer, in units of Hz.
ALC_REFRESHRefresh intervalls, in units of Hz.
ALC_SYNCFlag, indicating a synchronous context.

NoteAnnotation (Refresh Control)
 

Applications might have a fixed, or bounded, schedule for state changes (e.g. synchronously with the GL framerate). In this case it is desirable to specify the mixahead interval (milliseconds), or refresh rate (Hz), for the mixing thread. This is especially important for a synchronous context, where the application has to specify the refresh interval it intends to keep.

NoteRFC / Mixing Buffer Configuration
 

ALC_RESOLUTION was originally used to specify the accuracy of the mixing output buffer. For the time being this is not supported, but could be added if mixing path and result accuracy control is desirable to scale resource requirements. A full ALC_FORMAT (including channel and other attributes) does not make sense for rendering contexts, but will be necessary for PBuffers (mix to memory).

NoteRFC / LOKI extensions
 


       ALC_SOURCES_HINT_LOKI, /* # of sources to pre-allocate */
       ALC_BUFFERS_HINT_LOKI, /* # of buffers to pre-allocate */

       ALC_CD_LOKI,           /* demand CD/DVD control */
      
      

Creating a Context

A context is created using alcCreateContext. The device parameter has to be a valid device. The attribute list can be NULL, or a zero terminated list of integer pairs composed of valid ALC attribute tokens and requested values.

ALCcontext * alcCreateContext ( const ALCdevice * deviceHandle , int * attrList );

Context creation will fail if the application requests attributes that, by themselves, can not be provided. Context creation will fail if the combination of specified attributes can not be provided. Context creation will fail if a specified attribute, or the combination of attributes, does not match the default values for unspecified attributes.

Selecting a Context for Operation

To make a Context current with respect to AL Operation (state changes by issueing commands), alcMakeContextCurrent is used. The context parameter can be NULL or a valid context pointer. The operation will apply to the device that the context was created for.

boolean alcMakeContextCurrent ( ALCcontext * context );

For each OS process (usually this means for each application), only one context can be current at any given time. All AL commands apply to the current context. Commands that affect objects shared among contexts (e.g. buffers) have side effects on other contexts.

NoteAnnotation (No Explicit Device)
 

An ALC context is bound to the device it was created for. The context carries this information, thus removing the need to specify the device explicitely. Contexts can not be made current for any other device aside from the one they were created for.

NoteAnnotation (No Multiple Current)
 

There is only one current context per process, even in multithreaded applications, even if multiple devices are used.

NoteAnnotation (Current NULL)
 

The implementation is encouraged to exploit optimizations possible if the application sets the current context to NULL, indicating that no state changes are intended for the time being. The application should not set the current context to NULL if more state changes are pending on the most recent, or another context created for the same device.

NoteAnnotation (Shared Objects)
 

Buffers are shared among contexts. As mutiple contexts can exist at the same time, the state of shared objects is also shared among contexts.

NoteRFC / Buffer Deletion
 

Buffers that have not yet been processed in another context can not be deleted from any other context.

Initiate Context Processing

The current context is the only context accessible to state changes by AL commands (aside from state changes affecting shared objects). However, multiple contexts can be processed at the same time. To indicate that a context should be processed (i.e. that internal execution state like offset increments are supposed to be performed), the application has to use alcProcessContext.

void alcProcessContext( ALCcontext * context );

Repeated calls to alcProcessContext are legal, and do not affect a context that is already marked as processing. The default state of a context created by alcCreateContext is that it is not marked as processing.

NoteAnnotation (Sync and async implementations)
 

Unfortunately, the exact semantics of alcProcessContext is not independend of the implementation. Ideally it should be completely transparent to the application whether the sound driver is threaded or synced. Unfortunately a synced context has to have its execution initiated by the application, which requires calls of alcProcessContext timed in accordance to the drivers mixahead, or the rendering buffer will underflow. For a threaded driver, the implementation is free to consider alcProcessContext a NOP once the context has been marked as processing.

One consequence is that an application that was developed using a threaded implementation of AL might not work properly with a synchronous implementation of AL (on the other hand, an AL application that works using a synchronous implementation is guaranteed to work with a threaded implementation.

Enforcing alcProcessContext calls would defeat the purpose of a threaded implementation. Permitting the AL implementation to e.g. schedule optimizations based on alcProcessContext calls would similarly obfuscate the exact semantincs. Consequently, the application coder has to accept this implementation dependency, and has to rely on the ALC_SYNC attribute to explicitely request a synchronous implementation. The implementation can expect the application to be aware of the additonal constraints imposed on alcProcessContext in this case.

NoteAnnotation (Multiple Contexts and SYNC refresh)
 

The application can request SYNC contexts or threaded contexts, however, the implementation is not obliged to provide both, or provide a mixture of both on the same device.

NoteRFC/ Implications for Networking
 

What does alcProcessContext imply for networking? For AL, will we add alFlush/alFinish?

Suspend Context Processing

The application can suspend any context from processing (including the current one). To indicate that a context should be suspended from processing (i.e. that internal execution state like offset increments is not supposed to be changed), the application has to use alcSuspendContext.

void alcSuspendContext( ALCcontext * context );

Repeated calls to alcSuspendContext are legal, and do not affect a context that is already marked as suspended. The default state of a context created by alcCreateContext is that it is marked as suspended.

NoteAnnotation (Sync and async implementations)
 

Unfortunately, the exact semantics of alcSuspendContext is also not independend of the implementation. For a threaded implementation, alcSuspendContext is necessary to ensure a context is not processed. For a synchronous implementation, omitting alcProcessContext calls will ultimately have the same effect, but will also generate rendering buffer underflow errors. Again, the application coder that requests a synchronous context using ALC_SYNC has to make sure that alcSuspendContext is used accordingly.

NoteAnnotation (Suspending vs. Muting a context)
 

By setting Listener GAIN to zero, an application can mute a context, and expect the implementation to bypass all rendering. However, the context is still processing, and the internal execution state is still updated accordingly. Suspending a context, whether muted or not, will incidentally suspend rendering as well. However, it is the application's responsibility to prevent artifacts (e.g. by proper GAIN control to fade in and out). It is recommended to mute a context before suspending.

NoteAnnotation (Current Context Suspended)
 

It is possible to make a suspended context current, or suspend the current context. In this case, the implementation is still obliged to immediately verify AL commands as they are issued, and generate errors accordingly. The implementation is permitted to postpone propagating the actual state changes until the context is marked for processing again, with the exception of dereferencing data (e.g. buffer contents). For efficiency reasons (memory usage), most if not all AL commands applied to a suspended context will usually be applied immediately. State changes will have to be applied in the sequence they were requested. It is possible to use suspension of a current context as an explicit locking (to enforce apparent synchronicity), but execution is still guaranteed to be in sequence, and the implementation is not expected to optimize this operation. A typical use would be setting up the initial configuration while loading a scene.

NoteAnnotation (Release of Hardware Resources)
 

The specification does not guarantee that the implementation will release hardware resources used by a suspended context. This might well depend on the details of the hardware and driver. Neither a muted context nor a suspended context can be expected to free device resources. If all contexts for a given device are suspended, and no context of this device is current, the implementation is expected to release all hardware resources if possible.

Destroying a Context

void alcDestroyContext ( ALCcontext * context );

The correct way to destroy a context is to first release it using alcMakeCurrent and NULL. Applications should not attempt to destroy a current context.