audio: Added SDL_SetAudioIterationCallbacks().

This commit is contained in:
Ryan C. Gordon
2025-04-06 14:31:47 -04:00
parent 18a86ea6bb
commit 608f706a95
6 changed files with 127 additions and 2 deletions

View File

@@ -1147,7 +1147,20 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
// We should have updated this elsewhere if the format changed!
SDL_assert(SDL_AudioSpecsEqual(&stream->dst_spec, &device->spec, NULL, NULL));
const int br = SDL_GetAtomicInt(&logdev->paused) ? 0 : SDL_GetAudioStreamDataAdjustGain(stream, device_buffer, buffer_size, logdev->gain);
int br = 0;
if (!SDL_GetAtomicInt(&logdev->paused)) {
if (logdev->iteration_start) {
logdev->iteration_start(logdev->iteration_userdata, logdev->instance_id, true);
}
br = SDL_GetAudioStreamDataAdjustGain(stream, device_buffer, buffer_size, logdev->gain);
if (logdev->iteration_end) {
logdev->iteration_end(logdev->iteration_userdata, logdev->instance_id, false);
}
}
if (br < 0) { // Probably OOM. Kill the audio device; the whole thing is likely dying soon anyhow.
failed = true;
SDL_memset(device_buffer, device->silence_value, buffer_size); // just supply silence to the device before we die.
@@ -1185,6 +1198,10 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
SDL_memset(mix_buffer, '\0', work_buffer_size); // start with silence.
}
if (logdev->iteration_start) {
logdev->iteration_start(logdev->iteration_userdata, logdev->instance_id, true);
}
for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) {
// We should have updated this elsewhere if the format changed!
SDL_assert(SDL_AudioSpecsEqual(&stream->dst_spec, &outspec, NULL, NULL));
@@ -1207,6 +1224,10 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
}
}
if (logdev->iteration_end) {
logdev->iteration_end(logdev->iteration_userdata, logdev->instance_id, false);
}
if (postmix) {
SDL_assert(mix_buffer == device->postmix_buffer);
postmix(logdev->postmix_userdata, &outspec, mix_buffer, work_buffer_size);
@@ -1902,8 +1923,9 @@ bool SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallba
{
SDL_AudioDevice *device = NULL;
SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device);
bool result = true;
bool result = false;
if (logdev) {
result = true;
if (callback && !device->postmix_buffer) {
device->postmix_buffer = (float *)SDL_aligned_alloc(SDL_GetSIMDAlignment(), device->work_buffer_size);
if (!device->postmix_buffer) {
@@ -1922,6 +1944,21 @@ bool SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallba
return result;
}
bool SDL_SetAudioIterationCallbacks(SDL_AudioDeviceID devid, SDL_AudioIterationCallback iter_start, SDL_AudioIterationCallback iter_end, void *userdata)
{
SDL_AudioDevice *device = NULL;
SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device);
bool result = false;
if (logdev) {
logdev->iteration_start = iter_start;
logdev->iteration_end = iter_end;
logdev->iteration_userdata = userdata;
result = true;
}
ReleaseAudioDevice(device);
return result;
}
bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream * const *streams, int num_streams)
{
const bool islogical = !(devid & (1<<1));

View File

@@ -264,6 +264,13 @@ struct SDL_LogicalAudioDevice
// true if device was opened with SDL_OpenAudioDeviceStream (so it forbids binding changes, etc).
bool simplified;
// If non-NULL, callback into the app that alerts it to start/end of device iteration.
SDL_AudioIterationCallback iteration_start;
SDL_AudioIterationCallback iteration_end;
// App-supplied pointer for iteration callbacks.
void *iteration_userdata;
// If non-NULL, callback into the app that lets them access the final postmix buffer.
SDL_AudioPostmixCallback postmix;

View File

@@ -1251,6 +1251,7 @@ SDL3_0.0.0 {
SDL_GetGPUDeviceProperties;
SDL_CreateGPURenderer;
SDL_PutAudioStreamPlanarData;
SDL_SetAudioIterationCallbacks;
# extra symbols go here (don't modify this line)
local: *;
};

View File

@@ -1276,3 +1276,4 @@
#define SDL_GetGPUDeviceProperties SDL_GetGPUDeviceProperties_REAL
#define SDL_CreateGPURenderer SDL_CreateGPURenderer_REAL
#define SDL_PutAudioStreamPlanarData SDL_PutAudioStreamPlanarData_REAL
#define SDL_SetAudioIterationCallbacks SDL_SetAudioIterationCallbacks_REAL

View File

@@ -1284,3 +1284,4 @@ SDL_DYNAPI_PROC(bool,SDL_GetRenderTextureAddressMode,(SDL_Renderer *a,SDL_Textur
SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGPUDeviceProperties,(SDL_GPUDevice *a),(a),return)
SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateGPURenderer,(SDL_Window *a,SDL_GPUShaderFormat b,SDL_GPUDevice **c),(a,b,c),return)
SDL_DYNAPI_PROC(bool,SDL_PutAudioStreamPlanarData,(SDL_AudioStream *a,const void * const*b,int c),(a,b,c),return)
SDL_DYNAPI_PROC(bool,SDL_SetAudioIterationCallbacks,(SDL_AudioDeviceID a,SDL_AudioIterationCallback b,SDL_AudioIterationCallback c,void *d),(a,b,c,d),return)