Functions for callbacks.
More...
|
typedef void(* | playback_finished_callback) (ALint which_channel, ALuint al_source, ALmixer_Data *almixer_data, ALboolean finished_naturally, void *ALmixer_SetPlaybackFinishedCallbackContainer) |
|
|
void | ALmixer_SetPlaybackFinishedCallback (void(*playback_finished_callback)(ALint which_channel, ALuint al_source, ALmixer_Data *almixer_data, ALboolean finished_naturally, void *user_data), void *user_data) |
| Allows you to set a callback for when a sound has finished playing on a channel/source. More...
|
|
void | ALmixer_SetPlaybackDataCallback (void(*playback_data_callback)(ALint which_channel, ALuint al_source, ALbyte *pcm_data, ALuint num_bytes, ALuint frequency, ALubyte num_channels_in_sample, ALubyte bit_depth, ALboolean is_unsigned, ALboolean decode_mode_is_predecoded, ALuint length_in_msec, void *user_data), void *user_data) |
| Allows you to set a callback for getting audio data. More...
|
|
Functions for callbacks.
◆ playback_finished_callback
typedef void(* playback_finished_callback) (ALint which_channel, ALuint al_source, ALmixer_Data *almixer_data, ALboolean finished_naturally, void *ALmixer_SetPlaybackFinishedCallbackContainer) |
◆ ALmixer_SetPlaybackDataCallback()
void ALmixer_SetPlaybackDataCallback |
( |
void(*)(ALint which_channel, ALuint al_source, ALbyte *pcm_data, ALuint num_bytes, ALuint frequency, ALubyte num_channels_in_sample, ALubyte bit_depth, ALboolean is_unsigned, ALboolean decode_mode_is_predecoded, ALuint length_in_msec, void *user_data) |
playback_data_callback, |
|
|
void * |
user_data |
|
) |
| |
Allows you to set a callback for getting audio data.
This is a callback function pointer that when set, will trigger a function anytime there is new data loaded for a sample. The appropriate load parameter must be set in order for a sample to appear here. Keep in mind the the current backend implementation must do an end run around OpenAL because OpenAL lacks support for this kind of thing. As such, buffers are copied at decode time, and there is no attempt to do fine grained timing syncronization. You will be provided the entire buffer that is decoded regardless of length. So if you predecoded the entire audio file, the entire data buffer will be provided in a single callback. If you stream the data, you will be getting chunk sizes that are the same as what you specified the decode size to be. Unfortunely, this means if you pick smaller buffers, you get finer detail at the expense/risk of buffer underruns. If you decode more data, you have to deal with the syncronization issues if you want to display the data during playback in something like an oscilloscope.
- Note
- You may call this function before initializing ALmixer. This was done to facilite wrapper libraries around ALmixer where you needed to intercept all callbacks to monitor state (for things likes channel resources available or ALmixer_Data* that is in use). But as a consequence, the things you set in this function will persist across Init/Quit calls. If you need to clear or change the values, you must call this function again with the new values.
- Warning
- You should not call other ALmixer functions in this callback. Particularly in the case of when compiled with threads, recursive locking will occur which will lead to deadlocks. Also be aware that particularly in the threaded case, the callbacks may (and currently do) occur on a background thread. One typical thread safe strategy is to set flags or schedule events to occur on the main thread.
- Parameters
-
playback_data_callback | The function you want called back. Passing NULL (which is the default) disables the callback. |
which_channel | The ALmixer channel that the data is currently playing on. |
al_source | The OpenAL source that the data is currently playing on. |
pcm_data | This is a pointer to the data buffer containing ALmixer's version of the decoded data. Consider this data as read-only. In the non-threaded backend, this data will persist until potentially the next call to Update(). Currently, data buffers are preallocated and not destroyed until FreeData() is called (though this behavior is subject to change), but the contents will change when the buffer needs to be reused for a future callback. The buffer reuse is tied to the amount of buffers that may be queued. But assuming I don't change this, this may allow for some optimization so you can try referencing data from these buffers without worrying about crashing. (You still need to be aware that the data could be modified behind the scenes on an Update().) The data type listed is an signed 8-bit format, but the real data may not actually be this. ALbyte was chosen as a convenience. If you have a 16 bit format, you will want to cast the data and divide the num_bytes by 2. Typically, data is either Sint16. This seems to be a convention audio people seem to follow though I'm not sure what the underlying reasons (if any) are for this. I suspect that there may be some nice alignment/conversion property if you need to cast between ALbyte and ALubyte. |
num_bytes | This is the total length of the data buffer. It presumes that this length is measured for ALbyte. So if you have Sint16 data, you should divide num_bytes by two if you access the data as Sint16. |
frequency | The frequency the data was decoded at. |
num_channels_in_sample | 1 for mono, 2 for stereo. Not to be confused with the ALmixer which_channel. |
bit_depth | Bits per sample. This is expected to be 8 or 16. This number will tell you if you if you need to treat the data buffer as 16 bit or not. |
is_unsigned | 1 if the data is unsigned, 0 if signed. Using this combined with bit_depth will tell you if you need to treat the data as ALubyte, ALbyte, ALuint, or ALint. |
decode_mode_is_predecoded | This is here to tell you if the data was totally predecoded or loaded as a stream. If predecoded, you will only get one data callback per playback instance. (This might also be true for looping the same sample...I don't remember how it was implemented. Maybe this should be fixed.) 0 (ALMIXER_DECODE_STREAM) for streamed. 1 (ALMIXER_DECODE_ALL) for predecoded. |
length_in_msec | This returns the total length (time) of the data buffer in milliseconds. This could be computed yourself, but is provided as a convenince. |
user_data | The user data you pass in will be passed back to you in the callback. NULL is allowed. |
◆ ALmixer_SetPlaybackFinishedCallback()
void ALmixer_SetPlaybackFinishedCallback |
( |
void(*)(ALint which_channel, ALuint al_source, ALmixer_Data *almixer_data, ALboolean finished_naturally, void *user_data) |
playback_finished_callback, |
|
|
void * |
user_data |
|
) |
| |
Allows you to set a callback for when a sound has finished playing on a channel/source.
- Parameters
-
playback_finished_callback | The function you want to be invoked when a sound finishes. The callback function will pass you back the channel number which just finished playing, the OpenAL source id associated with the channel, the ALmixer_Data* that was played, a boolean telling you whether a sound finished playing because it ended normally or because something interrupted the playback (such as the user calling ALmixer_Halt*), and the user_data supplied as the second parameter to this function. Passing NULL (which is the default) disables the callback. |
which_chan | The ALmixer channel that the data is currently playing on. |
al_source | The OpenAL source that the data is currently playing on. |
almixer_data | The ALmixer_Data that was played. |
finished_naturally | AL_TRUE if the sound finished playing because it ended normally or AL_FALSE because something interrupted playback (such as the user calling ALmixer_Halt*). |
user_data | This will be passed back to you in the callback. NULL is allowed. |
- Note
- You may call this function before initializing ALmixer. This was done to facilite wrapper libraries around ALmixer where you needed to intercept all callbacks to monitor state (for things likes channel resources available or ALmixer_Data* that is in use). But as a consequence, the things you set in this function will persist across Init/Quit calls. If you need to clear or change the values, you must call this function again with the new values.
- Warning
- You should not call other ALmixer functions in this callback. Particularly in the case of when compiled with threads, recursive locking will occur which will lead to deadlocks. Also be aware that particularly in the threaded case, the callbacks may (and currently do) occur on a background thread. One typical thread safe strategy is to set flags or schedule events to occur on the main thread. One possible exception to the no-calling ALmixer functions rule is ALmixer_FreeData. ALmixer_FreeData currently does not lock so it might okay to call this to free your data. However, this has only had limited testing.