-
-
Save inolen/35fa98f685e49a814ff3ce8b9a7b6b3e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/deps/sdl2/include/SDL_audio.h b/deps/sdl2/include/SDL_audio.h | |
index d3e1bface..06efb24b9 100644 | |
--- a/deps/sdl2/include/SDL_audio.h | |
+++ b/deps/sdl2/include/SDL_audio.h | |
@@ -634,6 +634,8 @@ extern DECLSPEC void SDLCALL SDL_MixAudioFormat(Uint8 * dst, | |
SDL_AudioFormat format, | |
Uint32 len, int volume); | |
+extern DECLSPEC int SDLCALL SDL_WriteAudio(SDL_AudioDeviceID dev, const void *buffer, int buflen); | |
+ | |
/** | |
* Queue more audio on non-callback devices. | |
* | |
diff --git a/deps/sdl2/src/audio/SDL_audio.c b/deps/sdl2/src/audio/SDL_audio.c | |
index 97bb2ddd9..49146a9d1 100644 | |
--- a/deps/sdl2/src/audio/SDL_audio.c | |
+++ b/deps/sdl2/src/audio/SDL_audio.c | |
@@ -661,24 +661,7 @@ SDL_RunAudio(void *devicep) | |
while (!SDL_AtomicGet(&device->shutdown)) { | |
current_audio.impl.BeginLoopIteration(device); | |
data_len = device->callbackspec.size; | |
- | |
- /* 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); | |
- } else { | |
- /* if the device isn't enabled, we still write to the | |
- work_buffer, so the app's callback will fire with | |
- a regular frequency, in case they depend on that | |
- for timing or progress. They can use hotplug | |
- now to know if the device failed. | |
- Streaming playback uses work_buffer, too. */ | |
- data = NULL; | |
- } | |
- | |
- if (data == NULL) { | |
- data = device->work_buffer; | |
- } | |
+ data = device->work_buffer; | |
/* !!! FIXME: this should be LockDevice. */ | |
SDL_LockMutex(device->mixer_lock); | |
@@ -695,9 +678,7 @@ SDL_RunAudio(void *devicep) | |
SDL_AudioStreamPut(device->stream, data, data_len); | |
while (SDL_AudioStreamAvailable(device->stream) >= ((int) device->spec.size)) { | |
- int got; | |
- data = SDL_AtomicGet(&device->enabled) ? current_audio.impl.GetDeviceBuf(device) : NULL; | |
- got = SDL_AudioStreamGet(device->stream, data ? data : device->work_buffer, device->spec.size); | |
+ int got = SDL_AudioStreamGet(device->stream, device->work_buffer, device->spec.size); | |
SDL_assert((got < 0) || (got == device->spec.size)); | |
if (data == NULL) { /* device is having issues... */ | |
@@ -707,18 +688,12 @@ SDL_RunAudio(void *devicep) | |
if (got != device->spec.size) { | |
SDL_memset(data, device->spec.silence, device->spec.size); | |
} | |
- current_audio.impl.PlayDevice(device); | |
- current_audio.impl.WaitDevice(device); | |
+ current_audio.impl.WriteDevice(device, device->work_buffer, device->spec.size); | |
} | |
} | |
- } 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); | |
- SDL_Delay(delay); | |
- } else { /* writing directly to the device. */ | |
- /* queue this buffer and wait for it to finish playing. */ | |
- current_audio.impl.PlayDevice(device); | |
- current_audio.impl.WaitDevice(device); | |
+ } else { | |
+ /* writing directly to the device. */ | |
+ current_audio.impl.WriteDevice(device, data, data_len); | |
} | |
} | |
@@ -1369,6 +1344,7 @@ open_audio_device(const char *devname, int iscapture, | |
open_devices[id] = device; /* add it to our list of open devices. */ | |
+#if 0 | |
/* Start the audio thread if necessary */ | |
if (!current_audio.impl.ProvidesOwnCallbackThread) { | |
/* Start the audio thread */ | |
@@ -1386,6 +1362,7 @@ open_audio_device(const char *devname, int iscapture, | |
return 0; | |
} | |
} | |
+#endif | |
return device->id; | |
} | |
@@ -1520,6 +1497,28 @@ SDL_CloseAudio(void) | |
SDL_CloseAudioDevice(1); | |
} | |
+int | |
+SDL_WriteAudio(SDL_AudioDeviceID devid, const void *buffer, int buflen) { | |
+ SDL_AudioDevice *device = get_audio_device(devid); | |
+ | |
+ if (!device) { | |
+ return -1; | |
+ } | |
+ | |
+ if (device->stream) { | |
+ SDL_AudioStreamPut(device->stream, buffer, buflen); | |
+ SDL_AudioStreamFlush(device->stream); | |
+ | |
+ int buflen2 = SDL_AudioStreamAvailable(device->stream); | |
+ SDL_AudioStreamGet(device->stream, device->work_buffer, buflen2); | |
+ | |
+ buffer = device->work_buffer; | |
+ buflen = buflen2; | |
+ } | |
+ | |
+ return current_audio.impl.WriteDevice(device, buffer, buflen); | |
+} | |
+ | |
void | |
SDL_AudioQuit(void) | |
{ | |
diff --git a/deps/sdl2/src/audio/SDL_sysaudio.h b/deps/sdl2/src/audio/SDL_sysaudio.h | |
index f0e1f3dad..4e3c962c4 100644 | |
--- a/deps/sdl2/src/audio/SDL_sysaudio.h | |
+++ b/deps/sdl2/src/audio/SDL_sysaudio.h | |
@@ -71,6 +71,7 @@ typedef struct SDL_AudioDriverImpl | |
void (*BeginLoopIteration)(_THIS); /* Called by audio thread at top of loop */ | |
void (*WaitDevice) (_THIS); | |
void (*PlayDevice) (_THIS); | |
+ int (*WriteDevice)(_THIS, const void *buffer, int buflen); | |
int (*GetPendingBytes) (_THIS); | |
Uint8 *(*GetDeviceBuf) (_THIS); | |
int (*CaptureFromDevice) (_THIS, void *buffer, int buflen); | |
diff --git a/deps/sdl2/src/audio/alsa/SDL_alsa_audio.c b/deps/sdl2/src/audio/alsa/SDL_alsa_audio.c | |
index 2ce270583..7d954ab97 100644 | |
--- a/deps/sdl2/src/audio/alsa/SDL_alsa_audio.c | |
+++ b/deps/sdl2/src/audio/alsa/SDL_alsa_audio.c | |
@@ -363,6 +363,53 @@ ALSA_PlayDevice(_THIS) | |
} | |
} | |
+static int | |
+ALSA_WriteDevice(_THIS, const void *buffer, int buflen) | |
+{ | |
+ const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) * | |
+ this->spec.channels; | |
+ snd_pcm_sframes_t frames_total = buflen / frame_size; | |
+ snd_pcm_sframes_t frames_left = frames_total; | |
+ | |
+ while (frames_left) { | |
+ int status = ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1); | |
+ | |
+ if (status == -EPIPE || status == -ESTRPIPE || status == -EINTR) { | |
+ if (ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 1) < 0) { | |
+ fprintf(stderr, "ALSA write failed (unrecoverable): %s\n", | |
+ ALSA_snd_strerror(status)); | |
+ SDL_OpenedAudioDeviceDisconnected(this); | |
+ return -1; | |
+ } | |
+ continue; | |
+ } | |
+ | |
+ snd_pcm_sframes_t wrote = ALSA_snd_pcm_writei(this->hidden->pcm_handle, | |
+ buffer, frames_left); | |
+ if (wrote == -EPIPE || wrote == -ESTRPIPE || wrote == -EINTR) { | |
+ if (ALSA_snd_pcm_recover(this->hidden->pcm_handle, wrote, 1) < 0) { | |
+ fprintf(stderr, "ALSA write failed (unrecoverable): %s\n", | |
+ ALSA_snd_strerror(wrote)); | |
+ SDL_OpenedAudioDeviceDisconnected(this); | |
+ return -1; | |
+ } | |
+ continue; | |
+ } else if (wrote == -EAGAIN) { | |
+ /* Apparently snd_pcm_recover() doesn't handle this case - | |
+ does it assume snd_pcm_wait() above? */ | |
+ SDL_Delay(1); | |
+ continue; | |
+ } else if (wrote < 0) { | |
+ return -1; | |
+ } | |
+ | |
+ buffer += wrote * frame_size; | |
+ frames_left -= wrote; | |
+ } | |
+ | |
+ return (frames_total - frames_left) * frame_size; | |
+} | |
+ | |
static Uint8 * | |
ALSA_GetDeviceBuf(_THIS) | |
{ | |
@@ -945,12 +992,12 @@ ALSA_Init(SDL_AudioDriverImpl * impl) | |
impl->OpenDevice = ALSA_OpenDevice; | |
impl->WaitDevice = ALSA_WaitDevice; | |
impl->GetDeviceBuf = ALSA_GetDeviceBuf; | |
+ impl->WriteDevice = ALSA_WriteDevice; | |
impl->PlayDevice = ALSA_PlayDevice; | |
impl->CloseDevice = ALSA_CloseDevice; | |
impl->Deinitialize = ALSA_Deinitialize; | |
impl->CaptureFromDevice = ALSA_CaptureFromDevice; | |
impl->FlushCapture = ALSA_FlushCapture; | |
- | |
impl->HasCaptureSupport = SDL_TRUE; | |
return 1; /* this audio target is available. */ | |
diff --git a/deps/sdl2/src/audio/wasapi/SDL_wasapi.c b/deps/sdl2/src/audio/wasapi/SDL_wasapi.c | |
index b7c8dda5d..8b2e8d10d 100644 | |
--- a/deps/sdl2/src/audio/wasapi/SDL_wasapi.c | |
+++ b/deps/sdl2/src/audio/wasapi/SDL_wasapi.c | |
@@ -314,6 +314,49 @@ WASAPI_GetDeviceBuf(_THIS) | |
return (Uint8 *) buffer; | |
} | |
+static int | |
+WASAPI_WriteDevice(_THIS, const void *buffer, int buflen) | |
+{ | |
+ int frames_total = buflen / this->hidden->framesize; | |
+ int frames_left = frames_total; | |
+ | |
+ while (frames_left) { | |
+ DWORD res = WaitForSingleObject(this->hidden->event, INFINITE); | |
+ if (res != WAIT_OBJECT_0) { | |
+ return -1; | |
+ } | |
+ | |
+ const UINT32 maxpadding = this->spec.samples; | |
+ UINT32 padding = 0; | |
+ if (WasapiFailed(this, IAudioClient_GetCurrentPadding(this->hidden->client, &padding))) { | |
+ return -1; | |
+ } | |
+ | |
+ int avail_frames = maxpadding - padding; | |
+ if (!avail_frames) { | |
+ continue; | |
+ } | |
+ | |
+ int write_frames = frames_left < avail_frames ? frames_left : avail_frames; | |
+ | |
+ BYTE *out; | |
+ if (WasapiFailed(this, IAudioRenderClient_GetBuffer(this->hidden->render, write_frames, &out))) { | |
+ return -1; | |
+ } | |
+ | |
+ memcpy(out, buffer, write_frames * this->hidden->framesize); | |
+ | |
+ if (WasapiFailed(this, IAudioRenderClient_ReleaseBuffer(this->hidden->render, write_frames, 0))) { | |
+ return -1; | |
+ } | |
+ | |
+ buffer += write_frames * this->hidden->framesize; | |
+ frames_left -= write_frames; | |
+ } | |
+ | |
+ return (frames_total - frames_left) * this->hidden->framesize; | |
+} | |
+ | |
static void | |
WASAPI_PlayDevice(_THIS) | |
{ | |
@@ -757,6 +800,7 @@ WASAPI_Init(SDL_AudioDriverImpl * impl) | |
impl->ThreadDeinit = WASAPI_ThreadDeinit; | |
impl->BeginLoopIteration = WASAPI_BeginLoopIteration; | |
impl->OpenDevice = WASAPI_OpenDevice; | |
+ impl->WriteDevice = WASAPI_WriteDevice; | |
impl->PlayDevice = WASAPI_PlayDevice; | |
impl->WaitDevice = WASAPI_WaitDevice; | |
impl->GetPendingBytes = WASAPI_GetPendingBytes; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment