From 3784886cd5d88a04dfc423b2ab4cc6d405b7736a Mon Sep 17 00:00:00 2001 From: z2442 Date: Sat, 17 Aug 2024 10:26:11 -0400 Subject: [PATCH] Audio plugin changes for SDL2 *Added SDL2 thread async *fixed bug that prevented linux audio from working. --- Source/HLEAudio/Plugin/SDL/AudioPluginSDL.cpp | 204 +++++++++--------- 1 file changed, 105 insertions(+), 99 deletions(-) diff --git a/Source/HLEAudio/Plugin/SDL/AudioPluginSDL.cpp b/Source/HLEAudio/Plugin/SDL/AudioPluginSDL.cpp index 46a9e20a..899f0399 100644 --- a/Source/HLEAudio/Plugin/SDL/AudioPluginSDL.cpp +++ b/Source/HLEAudio/Plugin/SDL/AudioPluginSDL.cpp @@ -1,7 +1,5 @@ #include - - #include "Base/Types.h" #include "Interface/ConfigOptions.h" #include "Utility/FramerateLimiter.h" @@ -10,118 +8,117 @@ #include "HLEAudio/AudioPlugin.h" #include "HLEAudio/HLEAudioInternal.h" #include "System/Timing.h" -#include EAudioPluginMode gAudioPluginEnabled = APM_ENABLED_ASYNC; -pthread_t Asyncthread; -int Asyncthreadreturn; +SDL_Thread* Asyncthread = nullptr; +int Asyncthreadreturn; void* Audio_UcodeEntry(void* arg) { Audio_Ucode(); return nullptr; } -SDL_AudioDeviceID audio_device; +SDL_AudioDeviceID audio_device = 0; struct Sample { - s16 L; - s16 R; + s16 L; + s16 R; }; class AudioPluginSDL : public CAudioPlugin { public: - AudioPluginSDL(); - virtual ~AudioPluginSDL(); + AudioPluginSDL(); + virtual ~AudioPluginSDL(); - virtual bool StartEmulation(); - virtual void StopEmulation(); + virtual bool StartEmulation(); + virtual void StopEmulation(); - virtual void DacrateChanged(int system_type); - virtual void LenChanged(); - virtual u32 ReadLength() { return 0; } - virtual EProcessResult ProcessAList(); + virtual void DacrateChanged(int system_type); + virtual void LenChanged(); + virtual u32 ReadLength() { return 0; } + virtual EProcessResult ProcessAList(); - void AddBuffer(void * ptr, u32 length); // Uploads a new buffer and returns status - void StopAudio(); // Stops the Audio PlayBack (as if paused) - void StartAudio(); // Starts the Audio PlayBack (as if unpaused) + void AddBuffer(void * ptr, u32 length); // Uploads a new buffer and returns status + void StopAudio(); // Stops the Audio PlayBack (as if paused) + void StartAudio(); // Starts the Audio PlayBack (as if unpaused) - static void AudioSyncFunction(void * arg); - static int AudioThread(void * arg); + static void AudioSyncFunction(void * arg); + static int AudioThread(void * arg); private: - u32 mFrequency; - SDL_Thread* mAudioThread; + u32 mFrequency; + SDL_Thread* mAudioThread; }; AudioPluginSDL::AudioPluginSDL() -: mFrequency( 44100 ) +: mFrequency(44100), mAudioThread(nullptr) {} AudioPluginSDL::~AudioPluginSDL() { - StopAudio(); + StopAudio(); } bool AudioPluginSDL::StartEmulation() { - return true; + return true; } void AudioPluginSDL::StopEmulation() { - Audio_Reset(); - StopAudio(); + Audio_Reset(); + StopAudio(); } void AudioPluginSDL::DacrateChanged(int system_type) { - u32 clock = (system_type == ST_NTSC) ? VI_NTSC_CLOCK : VI_PAL_CLOCK; - u32 dacrate = Memory_AI_GetRegister(AI_DACRATE_REG); - u32 frequency = clock / (dacrate + 1); + u32 clock = (system_type == ST_NTSC) ? VI_NTSC_CLOCK : VI_PAL_CLOCK; + u32 dacrate = Memory_AI_GetRegister(AI_DACRATE_REG); + u32 frequency = clock / (dacrate + 1); - mFrequency = frequency; + mFrequency = frequency; } void AudioPluginSDL::LenChanged() { - if (gAudioPluginEnabled > APM_DISABLED) - { - u32 address = Memory_AI_GetRegister(AI_DRAM_ADDR_REG) & 0xFFFFFF; - u32 length = Memory_AI_GetRegister(AI_LEN_REG); + if (gAudioPluginEnabled > APM_DISABLED) + { + u32 address = Memory_AI_GetRegister(AI_DRAM_ADDR_REG) & 0xFFFFFF; + u32 length = Memory_AI_GetRegister(AI_LEN_REG); - AddBuffer( g_pu8RamBase + address, length ); - } + AddBuffer(g_pu8RamBase + address, length); + } } EProcessResult AudioPluginSDL::ProcessAList() { - Memory_SP_SetRegisterBits(SP_STATUS_REG, SP_STATUS_HALT); - - EProcessResult result = PR_NOT_STARTED; - - switch (gAudioPluginEnabled) - { - case APM_DISABLED: - result = PR_COMPLETED; - break; - case APM_ENABLED_ASYNC: - #ifdef APPLE - Asyncthreadreturn = pthread_create(&Asyncthread, NULL, &Audio_UcodeEntry, (void*)nullptr); - result = PR_COMPLETED; - #else - Audio_Ucode(); + Memory_SP_SetRegisterBits(SP_STATUS_REG, SP_STATUS_HALT); + + EProcessResult result = PR_NOT_STARTED; + + switch (gAudioPluginEnabled) + { + case APM_DISABLED: + result = PR_COMPLETED; + break; + case APM_ENABLED_ASYNC: + Asyncthread = SDL_CreateThread((SDL_ThreadFunction)Audio_UcodeEntry, "Audio_UcodeThread", nullptr); + if (Asyncthread == nullptr) { + DBGConsole_Msg(0, "Failed to create Async thread", SDL_GetError()); + } else { + SDL_DetachThread(Asyncthread); + } result = PR_COMPLETED; - #endif - break; - case APM_ENABLED_SYNC: - Audio_Ucode(); - result = PR_COMPLETED; - break; - } - - return result; + break; + case APM_ENABLED_SYNC: + Audio_Ucode(); + result = PR_COMPLETED; + break; + } + + return result; } void AudioPluginSDL::AddBuffer(void * ptr, u32 length) @@ -132,10 +129,15 @@ void AudioPluginSDL::AddBuffer(void * ptr, u32 length) if (mAudioThread == nullptr) StartAudio(); + if (audio_device == 0) { + DBGConsole_Msg(0, "Audio device not initialized"); + return; + } + u32 num_samples = length / sizeof(Sample); // Queue the samples into SDL's audio buffer - if(SDL_QueueAudio(audio_device, ptr, num_samples * sizeof(Sample)) != 0) { + if (SDL_QueueAudio(audio_device, ptr, num_samples * sizeof(Sample)) != 0) { DBGConsole_Msg(0, "SDL_QueueAudio error: %s", SDL_GetError()); return; } @@ -143,56 +145,60 @@ void AudioPluginSDL::AddBuffer(void * ptr, u32 length) int AudioPluginSDL::AudioThread(void * arg) { - AudioPluginSDL * plugin = static_cast< AudioPluginSDL *>(arg); - - SDL_AudioSpec audio_spec; - SDL_zero(audio_spec); - audio_spec.freq = 44100; - audio_spec.format = AUDIO_S16SYS; - audio_spec.channels = 2; - audio_spec.samples = 4096; - audio_spec.callback = NULL; - audio_spec.userdata = plugin; - - audio_device = SDL_OpenAudioDevice( - NULL, 0, &audio_spec, NULL, 0); - - SDL_QueueAudio(0, &audio_spec, 4096); + AudioPluginSDL * plugin = static_cast(arg); + + SDL_AudioSpec audio_spec; + SDL_zero(audio_spec); + audio_spec.freq = plugin->mFrequency; + audio_spec.format = AUDIO_S16SYS; + audio_spec.channels = 2; + audio_spec.samples = 4096; + audio_spec.callback = NULL; + audio_spec.userdata = plugin; + + audio_device = SDL_OpenAudioDevice(NULL, 0, &audio_spec, NULL, 0); + if (audio_device == 0) { + DBGConsole_Msg(0, "Failed to open audio: %s", SDL_GetError()); + return -1; + } - SDL_PauseAudioDevice(audio_device, 0); + SDL_PauseAudioDevice(audio_device, 0); - return 0; + return 0; } void AudioPluginSDL::StartAudio() { - mAudioThread = SDL_CreateThread(&AudioThread, "Audio", this); - - if (mAudioThread == nullptr) - { - DBGConsole_Msg(0, "Failed to start the audio thread!"); - FramerateLimiter_SetAuxillarySyncFunction(nullptr, nullptr); - } + mAudioThread = SDL_CreateThread(&AudioThread, "Audio", this); + + if (mAudioThread == nullptr) + { + DBGConsole_Msg(0, "Failed to start the audio thread!"); + FramerateLimiter_SetAuxillarySyncFunction(nullptr, nullptr); + } } void AudioPluginSDL::StopAudio() { - if (mAudioThread == nullptr) - return; + if (mAudioThread == nullptr) + return; - if (mAudioThread != nullptr) - { - int threadReturnValue; - SDL_WaitThread(mAudioThread, &threadReturnValue); - mAudioThread = nullptr; - } + if (mAudioThread != nullptr) + { + int threadReturnValue; + SDL_WaitThread(mAudioThread, &threadReturnValue); + mAudioThread = nullptr; + } // Clear the remaining audio data in SDL's audio buffer - SDL_ClearQueuedAudio(audio_device); - SDL_CloseAudioDevice(audio_device); + if (audio_device != 0) { + SDL_ClearQueuedAudio(audio_device); + SDL_CloseAudioDevice(audio_device); + audio_device = 0; + } } std::unique_ptr CreateAudioPlugin() { - return std::make_unique(); -} \ No newline at end of file + return std::make_unique(); +}