Skip to content

Commit

Permalink
Fix XAudio2.7 hanging on device disconnection
Browse files Browse the repository at this point in the history
  • Loading branch information
LIJI32 committed Dec 23, 2023
1 parent e89df2d commit c9fb3b3
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 2 deletions.
46 changes: 46 additions & 0 deletions SDL/audio/xaudio2_7.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,27 @@ static unsigned _audio_get_frequency(void)
return audio_frequency;
}

static void nop(IXAudio2EngineCallback *this)
{
}

static bool _audio_init(void);

static _Atomic bool needs_restart = false;

static void critical_error(IXAudio2EngineCallback *this, HRESULT error)
{
needs_restart = true;
}


static size_t _audio_get_queue_length(void)
{
if (needs_restart) {
_audio_init();
if (!xaudio2) return 0;
_audio_set_paused(!playing);
}
static XAUDIO2_VOICE_STATE state;
IXAudio2SourceVoice_GetState(source_voice, &state);

Expand All @@ -120,6 +139,12 @@ static size_t _audio_get_queue_length(void)
static void _audio_queue_sample(GB_sample_t *sample)
{
if (!playing) return;

if (needs_restart) {
_audio_init();
if (!xaudio2) return;
_audio_set_paused(!playing);
}

static XAUDIO2_BUFFER buffer = {.AudioBytes = sizeof(*sample) * BATCH_SIZE, };
sample_pool[pos] = *sample;
Expand All @@ -133,6 +158,14 @@ static void _audio_queue_sample(GB_sample_t *sample)

static bool _audio_init(void)
{
if (needs_restart) {
needs_restart = false;
if (xaudio2) {
xaudio2->lpVtbl->Release(xaudio2);
xaudio2 = NULL;
}
}

HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) {
fprintf(stderr, "CoInitializeEx failed: %lx\n", hr);
Expand Down Expand Up @@ -168,6 +201,19 @@ static bool _audio_init(void)
return false;
}


static IXAudio2EngineCallbackVtbl callbacks = {
nop,
nop,
.OnCriticalError = critical_error
};

static IXAudio2EngineCallback callbackObject = {
.lpVtbl = &callbacks
};

IXAudio2SourceVoice_RegisterForCallbacks(xaudio2, &callbackObject);

return true;
}

Expand Down
20 changes: 18 additions & 2 deletions SDL/audio/xaudio2_7.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ typedef struct IXAudio2 {
typedef struct IXAudio2Vtbl IXAudio2Vtbl;
typedef void *IXAudio2MasteringVoice;

#undef INTERFACE
#define INTERFACE IXAudio2EngineCallback
DECLARE_INTERFACE(IXAudio2EngineCallback)
{
// Called by XAudio2 just before an audio processing pass begins.
STDMETHOD_(void, OnProcessingPassStart) (THIS) PURE;

// Called just after an audio processing pass ends.
STDMETHOD_(void, OnProcessingPassEnd) (THIS) PURE;

// 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.
STDMETHOD_(void, OnCriticalError) (THIS_ HRESULT Error) PURE;
};

#undef INTERFACE
#define INTERFACE IXAudio2

Expand All @@ -61,8 +76,8 @@ struct IXAudio2Vtbl {
STDMETHOD(Initialize) (THIS_ UINT32 Flags,
XAUDIO2_PROCESSOR XAudio2Processor) PURE;

void *RegisterForCallbacks;
void *UnregisterForCallbacks;
STDMETHOD(RegisterForCallbacks) (THIS_ __in IXAudio2EngineCallback *pCallback) PURE;
void *UnregisterForCallbacks;

STDMETHOD(CreateSourceVoice) (THIS_ __deref_out IXAudio2SourceVoice **ppSourceVoice,
__in const WAVEFORMATEX *pSourceFormat,
Expand Down Expand Up @@ -91,6 +106,7 @@ DEFINE_CLSID(XAudio2, 5a508685, a254, 4fba, 9b, 82, 9a, 24, b0, 03, 06, af);
DEFINE_IID(IXAudio2, 8bcf1f58, 9fe7, 4583, 8a, c6, e2, ad, c4, 65, c8, bb);


#define IXAudio2SourceVoice_RegisterForCallbacks(This, pCallback) ((This)->lpVtbl->RegisterForCallbacks(This,pCallback))
#define IXAudio2SourceVoice_Start(This,Flags,OperationSet) ((This)->lpVtbl->Start(This,Flags,OperationSet))
#define IXAudio2SourceVoice_Stop(This,Flags,OperationSet) ((This)->lpVtbl->Stop(This,Flags,OperationSet))
#define IXAudio2SourceVoice_SubmitSourceBuffer(This,pBuffer,pBufferWMA) ((This)->lpVtbl->SubmitSourceBuffer(This,pBuffer,pBufferWMA))
Expand Down

0 comments on commit c9fb3b3

Please sign in to comment.