Name AL_SOFT_callback_buffer Contributors Chris Robinson Contact Chris Robinson (chris.kcat 'at' gmail.com) Status Complete Dependencies This extension is for OpenAL 1.1. Overview This extension provides a mechanism for applications to provide sample data to the audio device in real-time. Standard OpenAL sources can read samples from a pre-loaded static buffer, or from a queue of prepared buffers that can be fed in over time. In both cases, an application needs to prepare all or some of the audio samples ahead of time to ensure proper continuous playback. A callback mechanism allows applications to generate audio as needed, without having to prepare samples ahead of time, and to implement their own streaming interface instead of having to fill, queue, and manage multiple OpenAL buffers per stream. Issues Q: What restrictions are there on the callback? A: The callback *MUST* be real-time safe! This means it can't block, do file I/O, allocate or free memory, or call any function that may do similar (this includes most external decoders). The function must complete in a bounded amount of time, as it's invoked when the audio device needs more samples to avoid underrunning. Some systems may be less sensitive to this, but to ensure proper compatibility, avoid calling anything that can stall the callback even temporarily. Q: How should the callback be supplied? A: Through a buffer object. The buffer gets a new function to prepare it with the callback and format, replacing any buffered samples it may have (and similarly, calling alBufferData to fill the buffer with samples will replace/remove the callback). When the buffer is set onto a source and that source is played, the callback will be invoked as samples are needed for mixing. Q: What happens when a buffer with a callback is set on multiple sources, or queued onto a source? A: An error is generated. A buffer with a callback can only be set onto one static source (using alSourcei(sid, AL_BUFFER, bid)). Trying to queue it onto a source with alSourceQueueBuffers or set onto a second source will result in an AL_INVALID_OPERATION error. New Types typedef ALsizei (AL_APIENTRY *ALBUFFERCALLBACKTYPESOFT)(ALvoid *userptr, ALvoid *sampledata, ALsizei numbytes); New Procedures and Functions void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr); void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2); void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **ptr); New Tokens Accepted as the parameter of alGetBufferPtrSOFT and alGetBufferPtrvSOFT: AL_BUFFER_CALLBACK_FUNCTION_SOFT 0x19A0 AL_BUFFER_CALLBACK_USER_PARAM_SOFT 0x19A1 Additions to Specification Callback Buffers Instead of storing sample data, a buffer may be given a callback function which will be invoked when the source it's attached to needs more samples to mix. To specify a callback for a buffer, use alBufferCallbackSOFT. void alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); After a successful call, any sample data that was stored in the buffer is removed. The specified is the sample format that will be expected from the callback, with being the base sample rate the samples will play at. NULL is an invalid pointer value for . The pointer is stored with the pointer. Any data it references is not copied. A buffer with a callback cannot be queued onto a streaming source, and it can only be set on one static source at a time. Attempting to queue such a buffer on a source, or attempting to set it on a source while it's already on one, will generate an AL_INVALID_OPERATION error. A subsequent successful call to alBufferData will remove the callback from the buffer, and make it a normal non-callback buffer. The callback should follow the prototype typedef ALsizei (AL_APIENTRY *ALBUFFERCALLBACKTYPESOFT)( ALvoid *userptr, ALvoid *sampledata, ALsizei numbytes); When invoked, the pointer is the same as was provided to alBufferCallbackSOFT. is a pointer to the sample data buffer that should be filled in by the function, and is the number of bytes needed to fill the sample data buffer for this invocation. is guaranteed to be greater than 0 and a multiple of the frame size for the format. The return value of the callback is the number of bytes actually written, which must be equal to or less than . If the return value is less than , it's treated as the end of the buffer and the source will play any complete samples before stopping. The new alGetBuffer{3}Ptr{v}SOFT functions can be used to query the pointer attributes stored in the buffer. void alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr); void alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2); void alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **ptr); Buffer AL_BUFFER_CALLBACK_FUNCTION_SOFT Attribute Name Signature Values Default --------------------------------- ---------- ------- -------- AL_BUFFER_CALLBACK_FUNCTION_SOFT Ptr,Ptrv Any NULL Description: Query only. The function address for the callback currently set on the buffer, from the last call to alBufferCallbackSOFT. A call to alBufferData will reset this to NULL. Buffer AL_BUFFER_CALLBACK_USER_PARAM_SOFT Attribute Name Signature Values Default ----------------------------------- ---------- ------- -------- AL_BUFFER_CALLBACK_USER_PARAM_SOFT Ptr,Ptrv Any NULL Description: Query only. The user data pointer that will be passed to the callback, from the last call to alBufferCallbackSOFT. A call to alBufferData will reset this to NULL.