From 5cd694fac654063848b2cae030a7b1a0579e85e5 Mon Sep 17 00:00:00 2001 From: Sajid Date: Sat, 30 Nov 2024 12:03:14 +0600 Subject: [PATCH] Default to SDL audio --- UnleashedRecomp/CMakeLists.txt | 3 +- UnleashedRecomp/apu/audio.h | 7 ++ UnleashedRecomp/apu/driver/sdl2_driver.cpp | 92 ++++++++++++++++++++ UnleashedRecomp/apu/driver/sdl2_driver.h | 3 + UnleashedRecomp/apu/driver/xaudio_driver.cpp | 14 +-- UnleashedRecomp/apu/driver/xaudio_driver.h | 1 + 6 files changed, 112 insertions(+), 8 deletions(-) create mode 100644 UnleashedRecomp/apu/driver/sdl2_driver.cpp create mode 100644 UnleashedRecomp/apu/driver/sdl2_driver.h diff --git a/UnleashedRecomp/CMakeLists.txt b/UnleashedRecomp/CMakeLists.txt index f736fbe..59f99c4 100644 --- a/UnleashedRecomp/CMakeLists.txt +++ b/UnleashedRecomp/CMakeLists.txt @@ -57,7 +57,8 @@ set(SWA_GPU_CXX_SOURCES set(SWA_APU_CXX_SOURCES "apu/audio.cpp" - "apu/driver/xaudio_driver.cpp" + #"apu/driver/xaudio_driver.cpp" + "apu/driver/sdl2_driver.cpp" ) set(SWA_HID_CXX_SOURCES diff --git a/UnleashedRecomp/apu/audio.h b/UnleashedRecomp/apu/audio.h index e04cf38..c09a1f8 100644 --- a/UnleashedRecomp/apu/audio.h +++ b/UnleashedRecomp/apu/audio.h @@ -1,5 +1,12 @@ #pragma once +#define XAUDIO_SAMPLES_HZ 48000 +#define XAUDIO_NUM_CHANNELS 6 +#define XAUDIO_SAMPLE_BITS 32 + +// Number of samples in a frame +#define XAUDIO_NUM_SAMPLES 256 + #ifdef SWA_IMPL void XAudioInitializeSystem(); void XAudioRegisterClient(PPCFunc* callback, uint32_t param); diff --git a/UnleashedRecomp/apu/driver/sdl2_driver.cpp b/UnleashedRecomp/apu/driver/sdl2_driver.cpp new file mode 100644 index 0000000..13938cf --- /dev/null +++ b/UnleashedRecomp/apu/driver/sdl2_driver.cpp @@ -0,0 +1,92 @@ +#include "sdl2_driver.h" +#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{}; +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; +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()) + { + memset(frames, 0, len); + } + else + { + memcpy(frames, g_queuedFrames.front(), g_audioFrameSize * sizeof(float)); + g_queuedFrames.pop(); + } + SDL_SemPost(g_audioSemaphore); +} + +static PPC_FUNC(DriverLoop) +{ + GuestThread::SetThreadName(GetCurrentThreadId(), "Audio Driver"); + + while (true) + { + if (!g_clientCallback) + { + // NOTE: This if statement doesn't get compiled in without this barrier. What? + _ReadBarrier(); + continue; + } + + SDL_SemWait(g_audioSemaphore); + GuestCode::Run((void*)g_clientCallback, &ctx); + } +} + +void XAudioInitializeSystem() +{ + assert(g_audioSemaphore); + + 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; + spec.format = AUDIO_F32SYS; + spec.channels = XAUDIO_NUM_CHANNELS; + spec.samples = XAUDIO_NUM_SAMPLES; + spec.callback = SDLAudioCallback; + g_audioDevice = SDL_OpenAudioDevice(nullptr, false, &spec, &spec, 0); + assert(g_audioDevice); + + SDL_PauseAudioDevice(g_audioDevice, 0); + KeInsertHostFunction(SDLAUDIO_DRIVER_KEY, DriverLoop); + GuestThread::Start(SDLAUDIO_DRIVER_KEY, 0, 0, nullptr); +} + +void XAudioRegisterClient(PPCFunc* callback, uint32_t param) +{ + g_clientCallback = callback; +} + +void XAudioSubmitFrame(void* samples) +{ + uint32_t* audioFrame = &g_audioFrames[g_audioFrameSize * g_audioFrameIndex]; + g_audioFrameIndex = (g_audioFrameIndex + 1) % g_semaphoreCount; + + for (size_t i = 0; i < XAUDIO_NUM_SAMPLES; i++) + { + for (size_t j = 0; j < XAUDIO_NUM_CHANNELS; j++) + 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)); +} diff --git a/UnleashedRecomp/apu/driver/sdl2_driver.h b/UnleashedRecomp/apu/driver/sdl2_driver.h new file mode 100644 index 0000000..ab732be --- /dev/null +++ b/UnleashedRecomp/apu/driver/sdl2_driver.h @@ -0,0 +1,3 @@ +#pragma once +#include +#include diff --git a/UnleashedRecomp/apu/driver/xaudio_driver.cpp b/UnleashedRecomp/apu/driver/xaudio_driver.cpp index d1b1d52..822d8a3 100644 --- a/UnleashedRecomp/apu/driver/xaudio_driver.cpp +++ b/UnleashedRecomp/apu/driver/xaudio_driver.cpp @@ -77,9 +77,9 @@ void XAudioInitializeSystem() WAVEFORMATIEEEFLOATEX format{}; format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; format.Format.cbSize = sizeof(format) - sizeof(format.Format); - format.Format.nChannels = 6; - format.Format.nSamplesPerSec = 48000; - format.Format.wBitsPerSample = 32; + format.Format.nChannels = XAUDIO_NUM_CHANNELS; + format.Format.nSamplesPerSec = XAUDIO_SAMPLES_HZ; + format.Format.wBitsPerSample = XAUDIO_SAMPLE_BITS; format.Format.nBlockAlign = (format.Format.nChannels * format.Format.wBitsPerSample) / 8; format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec * format.Format.nBlockAlign; @@ -110,16 +110,16 @@ void XAudioSubmitFrame(void* samples) uint32_t* audioFrame = &g_audioFrames[g_audioFrameSize * g_audioFrameIndex]; g_audioFrameIndex = (g_audioFrameIndex + 1) % g_semaphoreCount; - for (size_t i = 0; i < 256; i++) + for (size_t i = 0; i < XAUDIO_NUM_SAMPLES; i++) { for (size_t j = 0; j < 6; j++) - audioFrame[i * 6 + j] = std::byteswap(((uint32_t*)samples)[j * 256 + i]); + audioFrame[i * XAUDIO_NUM_CHANNELS + j] = std::byteswap(((uint32_t*)samples)[j * XAUDIO_NUM_SAMPLES + i]); } XAUDIO2_BUFFER buffer{}; buffer.pAudioData = (BYTE*)audioFrame; - buffer.AudioBytes = 256 * 6 * sizeof(float); - buffer.PlayLength = 256; + buffer.AudioBytes = XAUDIO_NUM_SAMPLES * XAUDIO_NUM_CHANNELS * sizeof(float); + buffer.PlayLength = XAUDIO_NUM_SAMPLES; g_sourceVoice->SubmitSourceBuffer(&buffer); } diff --git a/UnleashedRecomp/apu/driver/xaudio_driver.h b/UnleashedRecomp/apu/driver/xaudio_driver.h index 6f70f09..c8f99bf 100644 --- a/UnleashedRecomp/apu/driver/xaudio_driver.h +++ b/UnleashedRecomp/apu/driver/xaudio_driver.h @@ -1 +1,2 @@ #pragma once +#include