diff --git a/rpcs3/Emu/Audio/AudioBackend.h b/rpcs3/Emu/Audio/AudioBackend.h index e751ad6b6a..10454d342d 100644 --- a/rpcs3/Emu/Audio/AudioBackend.h +++ b/rpcs3/Emu/Audio/AudioBackend.h @@ -34,6 +34,12 @@ public: virtual bool AddData(const void* src, u32 num_samples) = 0; + /* + * This virtual method should be reimplemented if backend can fail to be initialized under non-error conditions + * eg. when there is no audio devices attached + */ + virtual bool Initialized() const { return true; } + /* * Virtual methods - should be implemented depending on backend capabilities */ diff --git a/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.cpp b/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.cpp index 542235f259..5f9cad47b6 100644 --- a/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.cpp +++ b/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.cpp @@ -22,7 +22,6 @@ XAudio2Backend::XAudio2Backend() if (FAILED(hr)) { XAudio.error("XAudio2Create() failed(0x%08x)", (u32)hr); - Emu.Pause(); return; } @@ -30,7 +29,7 @@ XAudio2Backend::XAudio2Backend() if (FAILED(hr)) { XAudio.error("CreateMasteringVoice() failed(0x%08x)", (u32)hr); - Emu.Pause(); + return; } // All succeeded, "commit" diff --git a/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.h b/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.h index 2433884110..b5b1226112 100644 --- a/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.h +++ b/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.h @@ -26,6 +26,8 @@ public: static const u32 capabilities = PLAY_PAUSE_FLUSH | IS_PLAYING | GET_NUM_ENQUEUED_SAMPLES | SET_FREQUENCY_RATIO; virtual u32 GetCapabilities() const override { return capabilities; }; + virtual bool Initialized() const override { return m_xaudio2_instance != nullptr; } + virtual void Open(u32 /* num_buffers */) override; virtual void Close() override; diff --git a/rpcs3/main_application.cpp b/rpcs3/main_application.cpp index a3a5ac977b..a327247742 100644 --- a/rpcs3/main_application.cpp +++ b/rpcs3/main_application.cpp @@ -33,6 +33,8 @@ #include "Emu/RSX/VK/VKGSRender.h" #endif +LOG_CHANNEL(sys_log, "SYS"); + /** Emu.Init() wrapper for user manager */ bool main_application::InitializeEmulator(const std::string& user, bool force_init, bool show_gui) { @@ -144,25 +146,34 @@ EmuCallbacks main_application::CreateCallbacks() callbacks.get_audio = []() -> std::shared_ptr { + std::shared_ptr result; switch (audio_renderer type = g_cfg.audio.renderer) { - case audio_renderer::null: return std::make_shared(); + case audio_renderer::null: result = std::make_shared(); break; #ifdef _WIN32 - case audio_renderer::xaudio: return std::make_shared(); + case audio_renderer::xaudio: result = std::make_shared(); break; #endif #ifdef HAVE_ALSA - case audio_renderer::alsa: return std::make_shared(); + case audio_renderer::alsa: result = std::make_shared(); break; #endif #ifdef HAVE_PULSE - case audio_renderer::pulse: return std::make_shared(); + case audio_renderer::pulse: result = std::make_shared(); break; #endif - case audio_renderer::openal: return std::make_shared(); + case audio_renderer::openal: result = std::make_shared(); break; #ifdef HAVE_FAUDIO - case audio_renderer::faudio: return std::make_shared(); + case audio_renderer::faudio: result = std::make_shared(); break; #endif default: fmt::throw_exception("Invalid audio renderer: %s" HERE, type); } + + if (!result->Initialized()) + { + // Fall back to a null backend if something went wrong + sys_log.error("Audio renderer %s could not be initialized, using a Null renderer instead", result->GetName()); + result = std::make_shared(); + } + return result; }; return callbacks;