win32: stop trying to send audio data after device removal

This commit is contained in:
OV2 2022-02-14 01:05:57 +01:00
parent f1ac3dc6d3
commit d7dc9acf2f
4 changed files with 36 additions and 5 deletions

View File

@ -20,17 +20,25 @@ CWaveOut::~CWaveOut(void)
DeInitSoundOutput(); DeInitSoundOutput();
} }
void CALLBACK WaveCallback(HWAVEOUT hWave, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) void CALLBACK CWaveOut::WaveCallback(HWAVEOUT hWave, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{ {
CWaveOut *wo = (CWaveOut*)dwUser;
if (uMsg == WOM_DONE) if (uMsg == WOM_DONE)
{ {
InterlockedDecrement(((volatile LONG *)dwUser)); InterlockedDecrement(&wo->bufferCount);
SetEvent(GUI.SoundSyncEvent); SetEvent(GUI.SoundSyncEvent);
} }
else if (uMsg == WOM_CLOSE) // also sent on device removals
{
// this stops any output from being sent to the non existing device
wo->initDone = false;
}
} }
bool CWaveOut::SetupSound() bool CWaveOut::SetupSound()
{ {
DeInitSoundOutput();
WAVEFORMATEX wfx; WAVEFORMATEX wfx;
wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2; wfx.nChannels = 2;
@ -43,7 +51,7 @@ bool CWaveOut::SetupSound()
// subtract -1, we added "Default" as first index - Default will yield -1, which is WAVE_MAPPER // subtract -1, we added "Default" as first index - Default will yield -1, which is WAVE_MAPPER
int device_index = FindDeviceIndex(GUI.AudioDevice) - 1; int device_index = FindDeviceIndex(GUI.AudioDevice) - 1;
waveOutOpen(&hWaveOut, device_index, &wfx, (DWORD_PTR)WaveCallback, (DWORD_PTR)&bufferCount, CALLBACK_FUNCTION); waveOutOpen(&hWaveOut, device_index, &wfx, (DWORD_PTR)WaveCallback, (DWORD_PTR)this, CALLBACK_FUNCTION);
UINT32 blockTime = GUI.SoundBufferSize / blockCount; UINT32 blockTime = GUI.SoundBufferSize / blockCount;
singleBufferSamples = (Settings.SoundPlaybackRate * blockTime) / 1000; singleBufferSamples = (Settings.SoundPlaybackRate * blockTime) / 1000;
@ -91,7 +99,7 @@ bool CWaveOut::InitSoundOutput()
void CWaveOut::DeInitSoundOutput() void CWaveOut::DeInitSoundOutput()
{ {
if (!initDone) if (!hWaveOut)
return; return;
StopPlayback(); StopPlayback();
@ -109,6 +117,7 @@ void CWaveOut::DeInitSoundOutput()
waveHeaders.clear(); waveHeaders.clear();
waveOutClose(hWaveOut); waveOutClose(hWaveOut);
hWaveOut = NULL;
initDone = false; initDone = false;
} }

View File

@ -44,4 +44,6 @@ class CWaveOut : public IS9xSoundOutput
void SetVolume(double volume); void SetVolume(double volume);
std::vector<std::wstring> GetDeviceList(); std::vector<std::wstring> GetDeviceList();
int FindDeviceIndex(TCHAR *audio_device); int FindDeviceIndex(TCHAR *audio_device);
static void CALLBACK WaveCallback(HWAVEOUT hWave, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2);
}; };

View File

@ -108,6 +108,8 @@ bool CXAudio2::InitXAudio2(void)
if(initDone) if(initDone)
return true; return true;
DeInitXAudio2();
HRESULT hr; HRESULT hr;
if ( FAILED(hr = XAudio2Create( &pXAudio2, 0 , XAUDIO2_DEFAULT_PROCESSOR ) ) ) { if ( FAILED(hr = XAudio2Create( &pXAudio2, 0 , XAUDIO2_DEFAULT_PROCESSOR ) ) ) {
DXTRACE_ERR_MSGBOX(TEXT("Unable to create XAudio2 object."),hr); DXTRACE_ERR_MSGBOX(TEXT("Unable to create XAudio2 object."),hr);
@ -115,6 +117,7 @@ bool CXAudio2::InitXAudio2(void)
return false; return false;
} }
initDone = true; initDone = true;
pXAudio2->RegisterForCallbacks(this);
return true; return true;
} }

View File

@ -11,7 +11,7 @@
#include <windows.h> #include <windows.h>
#include "IS9xSoundOutput.h" #include "IS9xSoundOutput.h"
class CXAudio2 : public IXAudio2VoiceCallback, public IS9xSoundOutput class CXAudio2 : public IXAudio2VoiceCallback, public IXAudio2EngineCallback, public IS9xSoundOutput
{ {
private: private:
IXAudio2SourceVoice *pSourceVoice; IXAudio2SourceVoice *pSourceVoice;
@ -56,6 +56,23 @@ public:
STDMETHODIMP_(void) OnVoiceProcessingPassStart(UINT32 BytesRequired) {} STDMETHODIMP_(void) OnVoiceProcessingPassStart(UINT32 BytesRequired) {}
// inherited from IXAudio2EngineCallback - we only use OnCriticalError
// Called by XAudio2 just before an audio processing pass begins.
STDMETHODIMP_(void) OnProcessingPassStart() {}
// Called just after an audio processing pass ends.
STDMETHODIMP_(void) OnProcessingPassEnd() {}
// Called in the event of a critical system error which requires XAudio2
// to be closed down and restarted. The error code is given in Error.
STDMETHODIMP_(void) OnCriticalError(HRESULT Error)
{
// this stops any output from being sent to the non existing device
initDone = false;
}
// Inherited from IS9xSoundOutput // Inherited from IS9xSoundOutput
bool InitSoundOutput(void) { return InitXAudio2(); } bool InitSoundOutput(void) { return InitXAudio2(); }
void DeInitSoundOutput(void) { DeInitXAudio2(); } void DeInitSoundOutput(void) { DeInitXAudio2(); }