mirror of
https://github.com/Ryujinx/SDL.git
synced 2025-01-03 17:35:30 +00:00
SDL_audio.c: Fix crash if we switch from direct output to streaming, and if the buffersizes change.
This commit is contained in:
parent
7b4f1ef01b
commit
eb1b9b418c
|
@ -677,6 +677,7 @@ static int SDLCALL SDL_RunAudio(void *userdata)
|
|||
SDL_AudioCallback callback = device->callbackspec.callback;
|
||||
int data_len = 0;
|
||||
Uint8 *data;
|
||||
Uint8 *device_buf_keepsafe = NULL;
|
||||
|
||||
SDL_assert(!device->iscapture);
|
||||
|
||||
|
@ -703,8 +704,16 @@ static int SDLCALL SDL_RunAudio(void *userdata)
|
|||
|
||||
/* Fill the current buffer with sound */
|
||||
if (!device->stream && SDL_AtomicGet(&device->enabled)) {
|
||||
SDL_assert(data_len == device->spec.size);
|
||||
data = current_audio.impl.GetDeviceBuf(device);
|
||||
|
||||
if (device->stream && SDL_AtomicGet(&device->enabled)) {
|
||||
/* Oops. Audio device reset and now we suddenly use a stream, */
|
||||
/* so save this devicebuf for later, to prevent de-sync */
|
||||
if (data != NULL) {
|
||||
device_buf_keepsafe = data;
|
||||
}
|
||||
data = NULL;
|
||||
}
|
||||
} else {
|
||||
/* if the device isn't enabled, we still write to the
|
||||
work_buffer, so the app's callback will fire with
|
||||
|
@ -735,7 +744,19 @@ static int SDLCALL SDL_RunAudio(void *userdata)
|
|||
|
||||
while (SDL_AudioStreamAvailable(device->stream) >= ((int)device->spec.size)) {
|
||||
int got;
|
||||
data = SDL_AtomicGet(&device->enabled) ? current_audio.impl.GetDeviceBuf(device) : NULL;
|
||||
if (SDL_AtomicGet(&device->enabled)) {
|
||||
/* if device reset occured - a switch from direct output to streaming */
|
||||
/* use the already aquired device buffer */
|
||||
if (device_buf_keepsafe) {
|
||||
data = device_buf_keepsafe;
|
||||
device_buf_keepsafe = NULL;
|
||||
} else {
|
||||
/* else - normal flow, just acquire the device buffer here */
|
||||
data = current_audio.impl.GetDeviceBuf(device);
|
||||
}
|
||||
} else {
|
||||
data = NULL;
|
||||
}
|
||||
got = SDL_AudioStreamGet(device->stream, data ? data : device->work_buffer, device->spec.size);
|
||||
SDL_assert((got <= 0) || (got == device->spec.size));
|
||||
|
||||
|
@ -750,6 +771,14 @@ static int SDLCALL SDL_RunAudio(void *userdata)
|
|||
current_audio.impl.WaitDevice(device);
|
||||
}
|
||||
}
|
||||
|
||||
/* it seems resampling was not fast enough, device_buf_keepsafe was not released yet, so play silence here */
|
||||
if (device_buf_keepsafe) {
|
||||
SDL_memset(device_buf_keepsafe, device->spec.silence, device->spec.size);
|
||||
current_audio.impl.PlayDevice(device);
|
||||
current_audio.impl.WaitDevice(device);
|
||||
device_buf_keepsafe = NULL;
|
||||
}
|
||||
} else if (data == device->work_buffer) {
|
||||
/* nothing to do; pause like we queued a buffer to play. */
|
||||
const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
|
||||
|
|
Loading…
Reference in a new issue