summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd
diff options
context:
space:
mode:
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
commitb8cea5e0f9e7e2c578c41163b543eaaf701e7b6e (patch)
tree41af35e514e4f9022ea29c69e55df4b38ac04f6f /src/osd
parent5a605796159460dcc6f721ac1f7c9c64900a1bf2 (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.cpp76
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,