diff options
author | Brad Hughes <bradhugh@outlook.com> | 2016-06-03 23:17:20 -0400 |
---|---|---|
committer | Brad Hughes <bradhugh@outlook.com> | 2016-06-03 23:17:20 -0400 |
commit | b8cea5e0f9e7e2c578c41163b543eaaf701e7b6e (patch) | |
tree | 41af35e514e4f9022ea29c69e55df4b38ac04f6f /src/osd | |
parent | 5a605796159460dcc6f721ac1f7c9c64900a1bf2 (diff) |
Ensure XAudio2 doesn't crash when no sound card present.
Diffstat (limited to 'src/osd')
-rw-r--r-- | src/osd/modules/sound/xaudio2_sound.cpp | 76 |
1 files changed, 48 insertions, 28 deletions
diff --git a/src/osd/modules/sound/xaudio2_sound.cpp b/src/osd/modules/sound/xaudio2_sound.cpp index d49765e9d07..f4da54db2ec 100644 --- a/src/osd/modules/sound/xaudio2_sound.cpp +++ b/src/osd/modules/sound/xaudio2_sound.cpp @@ -15,6 +15,8 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> +#include <wrl/client.h> + // XAudio2 include #include <xaudio2.h> @@ -92,14 +94,6 @@ struct xaudio2_buffer struct xaudio2_custom_deleter { public: - void operator()(IXAudio2* obj) const - { - if (obj != nullptr) - { - obj->Release(); - } - } - void operator()(IXAudio2MasteringVoice* obj) const { if (obj != nullptr) @@ -120,7 +114,6 @@ public: }; // Typedefs for smart pointers used with customer deleters -typedef std::unique_ptr<IXAudio2, xaudio2_custom_deleter> xaudio2_ptr; typedef std::unique_ptr<IXAudio2MasteringVoice, xaudio2_custom_deleter> mastering_voice_ptr; typedef std::unique_ptr<IXAudio2SourceVoice, xaudio2_custom_deleter> src_voice_ptr; @@ -190,7 +183,7 @@ class sound_xaudio2 : public osd_module, public sound_module, public IXAudio2Voi private: const wchar_t* XAUDIO_DLLS[2] = { L"XAudio2_9.dll", L"XAudio2_8.dll" }; - xaudio2_ptr m_xAudio2; + Microsoft::WRL::ComPtr<IXAudio2> m_xAudio2; mastering_voice_ptr m_masterVoice; src_voice_ptr m_sourceVoice; DWORD m_sample_bytes; @@ -209,6 +202,7 @@ private: UINT32 m_underflows; BOOL m_in_underflow; xaudio2_create_ptr XAudio2Create; + BOOL m_initialized; public: sound_xaudio2() : @@ -229,7 +223,8 @@ public: m_overflows(0), m_underflows(0), m_in_underflow(FALSE), - XAudio2Create("XAudio2Create", XAUDIO_DLLS, ARRAY_LENGTH(XAUDIO_DLLS)) + XAudio2Create("XAudio2Create", XAUDIO_DLLS, ARRAY_LENGTH(XAUDIO_DLLS)), + m_initialized(FALSE) { } @@ -277,6 +272,7 @@ bool sound_xaudio2::probe() int sound_xaudio2::init(osd_options const &options) { HRESULT result; + WAVEFORMATEX format = {0}; CoInitializeEx(nullptr, COINIT_MULTITHREADED); // Make sure our XAudio2Create entrypoint is bound @@ -288,12 +284,9 @@ int sound_xaudio2::init(osd_options const &options) } // Create the IXAudio2 object - IXAudio2 *temp_xaudio2 = nullptr; - HR_RET1(this->XAudio2Create(&temp_xaudio2, 0, XAUDIO2_DEFAULT_PROCESSOR)); - m_xAudio2 = xaudio2_ptr(temp_xaudio2); + HR_GOERR(this->XAudio2Create(m_xAudio2.GetAddressOf(), 0, XAUDIO2_DEFAULT_PROCESSOR)); // make a format description for what we want - WAVEFORMATEX format = { 0 }; format.wBitsPerSample = 16; format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = 2; @@ -312,15 +305,20 @@ int sound_xaudio2::init(osd_options const &options) m_hEventExiting = CreateEvent(nullptr, FALSE, FALSE, nullptr); // create the voices and start them - HR_RET1(create_voices(format)); - HR_RET1(m_sourceVoice->Start()); + HR_GOERR(create_voices(format)); + HR_GOERR(m_sourceVoice->Start()); // Start the thread listening m_audioThread = std::thread([](sound_xaudio2* self) { self->process_audio(); }, this); osd_printf_verbose("Sound: XAudio2 initialized\n"); + m_initialized = TRUE; return 0; + +Error: + this->exit(); + return 1; } //============================================================ @@ -330,25 +328,44 @@ int sound_xaudio2::init(osd_options const &options) void sound_xaudio2::exit() { // Wait on processing thread to end - SetEvent(m_hEventExiting); - m_audioThread.join(); + if (m_hEventExiting) + { + SetEvent(m_hEventExiting); + m_hEventExiting = nullptr; + } + + if (m_audioThread.joinable()) + m_audioThread.join(); - CloseHandle(m_hEventBufferCompleted); - CloseHandle(m_hEventDataAvailable); - CloseHandle(m_hEventExiting); + if (m_hEventBufferCompleted) + { + CloseHandle(m_hEventBufferCompleted); + m_hEventBufferCompleted = nullptr; + } + + if (m_hEventDataAvailable) + { + CloseHandle(m_hEventDataAvailable); + m_hEventDataAvailable = nullptr; + } + + if (m_hEventExiting) + { + CloseHandle(m_hEventExiting); + m_hEventExiting = nullptr; + } m_sourceVoice.reset(); m_masterVoice.reset(); - m_xAudio2.reset(); + m_xAudio2 = nullptr; m_buffer.reset(); m_buffer_pool.reset(); - CoUninitialize(); - if (m_overflows != 0 || m_underflows != 0) osd_printf_verbose("Sound: overflows=%u, underflows=%u\n", m_overflows, m_underflows); osd_printf_verbose("Sound: XAudio2 deinitialized\n"); + m_initialized = FALSE; } //============================================================ @@ -360,7 +377,7 @@ void sound_xaudio2::update_audio_stream( INT16 const *buffer, int samples_this_frame) { - if ((sample_rate() == 0) || !m_buffer) + if (!m_initialized || sample_rate() == 0 || !m_buffer) return; UINT32 const bytes_this_frame = samples_this_frame * m_sample_bytes; @@ -395,6 +412,9 @@ void sound_xaudio2::update_audio_stream( void sound_xaudio2::set_mastervolume(int attenuation) { + if (!m_initialized) + return; + assert(m_sourceVoice); HRESULT result; @@ -503,7 +523,7 @@ HRESULT sound_xaudio2::create_voices(const WAVEFORMATEX &format) HRESULT result; IXAudio2MasteringVoice *temp_master_voice = nullptr; - HR_RET1( + HR_RETHR( m_xAudio2->CreateMasteringVoice( &temp_master_voice, format.nChannels, @@ -513,7 +533,7 @@ HRESULT sound_xaudio2::create_voices(const WAVEFORMATEX &format) // create the source voice IXAudio2SourceVoice *temp_source_voice = nullptr; - HR_RET1(m_xAudio2->CreateSourceVoice( + HR_RETHR(m_xAudio2->CreateSourceVoice( &temp_source_voice, &format, XAUDIO2_VOICE_NOSRC | XAUDIO2_VOICE_NOPITCH, |