diff --git a/UnleashedRecomp/apu/driver/sdl2_driver.cpp b/UnleashedRecomp/apu/driver/sdl2_driver.cpp index 13938cf..87c7e2f 100644 --- a/UnleashedRecomp/apu/driver/sdl2_driver.cpp +++ b/UnleashedRecomp/apu/driver/sdl2_driver.cpp @@ -2,32 +2,36 @@ #include #include #include -#include +#include #define SDLAUDIO_DRIVER_KEY (uint32_t)('SDLA') constexpr uint32_t g_semaphoreCount = 16; constexpr uint32_t g_audioFrameSize = XAUDIO_NUM_SAMPLES * XAUDIO_NUM_CHANNELS; -PPCFunc* g_clientCallback{}; +PPCFunc* volatile g_clientCallback{}; +DWORD g_clientCallbackParam{}; // pointer in guest memory + SDL_AudioDeviceID g_audioDevice{}; SDL_sem* g_audioSemaphore{ SDL_CreateSemaphore(g_semaphoreCount) }; uint32_t g_audioFrames[g_audioFrameSize * g_semaphoreCount]; uint32_t g_audioFrameIndex = 0; +uint32_t g_renderFrameIndex = 0; // Index of frame that's being rendered +uint32_t g_numRenderFrames = 0; // Number of frames to render Mutex g_framesMutex{}; -std::queue g_queuedFrames{}; -std::queue> g_frames{}; static void SDLAudioCallback(void*, uint8_t* frames, int len) { - std::lock_guard g{ g_framesMutex }; - if (g_queuedFrames.empty()) + std::lock_guard guard{ g_framesMutex }; + if (g_numRenderFrames == 0) { memset(frames, 0, len); } else { - memcpy(frames, g_queuedFrames.front(), g_audioFrameSize * sizeof(float)); - g_queuedFrames.pop(); + g_renderFrameIndex = (g_renderFrameIndex + 1) % g_semaphoreCount; + auto* srcFrames = &g_audioFrames[g_renderFrameIndex * g_audioFrameSize]; + memcpy(frames, srcFrames, g_audioFrameSize * sizeof(float)); + --g_numRenderFrames; } SDL_SemPost(g_audioSemaphore); } @@ -40,12 +44,11 @@ static PPC_FUNC(DriverLoop) { if (!g_clientCallback) { - // NOTE: This if statement doesn't get compiled in without this barrier. What? - _ReadBarrier(); continue; } SDL_SemWait(g_audioSemaphore); + ctx.r3.u64 = g_clientCallbackParam; GuestCode::Run((void*)g_clientCallback, &ctx); } } @@ -56,6 +59,7 @@ void XAudioInitializeSystem() SDL_SetHint(SDL_HINT_AUDIO_CATEGORY, "playback"); SDL_SetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME, "SWA"); + auto err = SDL_InitSubSystem(SDL_INIT_AUDIO); SDL_AudioSpec spec{}; spec.freq = XAUDIO_SAMPLES_HZ; @@ -73,11 +77,17 @@ void XAudioInitializeSystem() void XAudioRegisterClient(PPCFunc* callback, uint32_t param) { + auto* pClientParam = static_cast(g_userHeap.Alloc(sizeof(param))); + ByteSwap(param); + *pClientParam = param; + g_clientCallbackParam = g_memory.MapVirtual(pClientParam); + g_clientCallback = callback; } void XAudioSubmitFrame(void* samples) { + std::lock_guard guard{ g_framesMutex }; uint32_t* audioFrame = &g_audioFrames[g_audioFrameSize * g_audioFrameIndex]; g_audioFrameIndex = (g_audioFrameIndex + 1) % g_semaphoreCount; @@ -87,6 +97,5 @@ void XAudioSubmitFrame(void* samples) audioFrame[i * XAUDIO_NUM_CHANNELS + j] = std::byteswap(((uint32_t*)samples)[j * XAUDIO_NUM_SAMPLES + i]); } - std::lock_guard g{ g_framesMutex }; - g_queuedFrames.emplace(reinterpret_cast(audioFrame)); + ++g_numRenderFrames; } diff --git a/UnleashedRecomp/apu/driver/xaudio_driver.cpp b/UnleashedRecomp/apu/driver/xaudio_driver.cpp index 822d8a3..a492e88 100644 --- a/UnleashedRecomp/apu/driver/xaudio_driver.cpp +++ b/UnleashedRecomp/apu/driver/xaudio_driver.cpp @@ -9,7 +9,7 @@ #define XAUDIO_DRIVER_KEY (uint32_t)('XAUD') -PPCFunc* g_clientCallback{}; +PPCFunc* volatile g_clientCallback{}; DWORD g_clientCallbackParam{}; // pointer in guest memory DWORD g_driverThread{}; @@ -49,8 +49,6 @@ PPC_FUNC(DriverLoop) { if (!g_clientCallback) { - // NOTE: This if statement doesn't get compiled in without this barrier. What? - _ReadBarrier(); continue; }