diff --git a/src/xenia/apu/audio_system.cc b/src/xenia/apu/audio_system.cc index 3611f0c0c..97f5af060 100644 --- a/src/xenia/apu/audio_system.cc +++ b/src/xenia/apu/audio_system.cc @@ -22,7 +22,7 @@ using namespace xe::cpu; AudioSystem::AudioSystem(Emulator* emulator) : emulator_(emulator), memory_(emulator->memory()), thread_(0), running_(false), - client_({ 0 }), can_submit_(false) { + client_({ 0 }) { // Create the run loop used for any windows/etc. // This must be done on the thread we create the driver. run_loop_ = xe_run_loop_create(); @@ -85,13 +85,14 @@ void AudioSystem::ThreadStart() { } // Pump worker. + // This may block. Pump(); xe_mutex_lock(lock_); uint32_t client_callback = client_.callback; uint32_t client_callback_arg = client_.wrapped_callback_arg; xe_mutex_unlock(lock_); - if (client_callback && can_submit_) { + if (client_callback) { processor->Execute( thread_state_, client_callback, client_callback_arg, 0); } else { diff --git a/src/xenia/apu/audio_system.h b/src/xenia/apu/audio_system.h index ce5a4326f..9fdd10526 100644 --- a/src/xenia/apu/audio_system.h +++ b/src/xenia/apu/audio_system.h @@ -82,7 +82,6 @@ protected: uint32_t callback_arg; uint32_t wrapped_callback_arg; } client_; - bool can_submit_; }; diff --git a/src/xenia/apu/xaudio2/xaudio2_audio_system.cc b/src/xenia/apu/xaudio2/xaudio2_audio_system.cc index 85f498b78..0668bd716 100644 --- a/src/xenia/apu/xaudio2/xaudio2_audio_system.cc +++ b/src/xenia/apu/xaudio2/xaudio2_audio_system.cc @@ -19,8 +19,29 @@ using namespace xe::apu; using namespace xe::apu::xaudio2; +class XAudio2AudioSystem::VoiceCallback : public IXAudio2VoiceCallback { +public: + VoiceCallback(HANDLE wait_handle) : wait_handle_(wait_handle) {} + ~VoiceCallback() {} + + void OnStreamEnd() {} + void OnVoiceProcessingPassEnd() {} + void OnVoiceProcessingPassStart(UINT32 SamplesRequired) {} + void OnBufferEnd(void * pBufferContext) { + SetEvent(wait_handle_); + } + void OnBufferStart(void * pBufferContext) {} + void OnLoopEnd(void * pBufferContext) {} + void OnVoiceError(void * pBufferContext, HRESULT Error) {} + +private: + HANDLE wait_handle_; +}; + + XAudio2AudioSystem::XAudio2AudioSystem(Emulator* emulator) : audio_(0), mastering_voice_(0), pcm_voice_(0), + wait_handle_(NULL), voice_callback_(0), AudioSystem(emulator) { } @@ -32,6 +53,10 @@ void XAudio2AudioSystem::Initialize() { HRESULT hr; + wait_handle_ = CreateEvent(NULL, TRUE, TRUE, NULL); + + voice_callback_ = new VoiceCallback(wait_handle_); + hr = XAudio2Create(&audio_, 0, XAUDIO2_DEFAULT_PROCESSOR); if (FAILED(hr)) { XELOGE("XAudio2Create failed with %.8X", hr); @@ -62,12 +87,16 @@ void XAudio2AudioSystem::Initialize() { waveformat.nBlockAlign = 2; waveformat.wBitsPerSample = 16; waveformat.cbSize = 0; - hr = audio_->CreateSourceVoice(&pcm_voice_, &waveformat); + hr = audio_->CreateSourceVoice( + &pcm_voice_, &waveformat, 0, XAUDIO2_DEFAULT_FREQ_RATIO, + voice_callback_); if (FAILED(hr)) { XELOGE("CreateSourceVoice failed with %.8X", hr); exit(1); } + // + pcm_voice_->Start(); } @@ -76,10 +105,11 @@ void XAudio2AudioSystem::Pump() { pcm_voice_->GetState(&state); auto n = state.BuffersQueued; if (n > 30) { - can_submit_ = false; - } else { - can_submit_ = true; + // A lot of buffers are queued up, and until we use them block. + ResetEvent(wait_handle_); } + + WaitForSingleObject(wait_handle_, INFINITE); } void XAudio2AudioSystem::SubmitFrame(uint32_t samples_ptr) { @@ -117,5 +147,18 @@ void XAudio2AudioSystem::SubmitFrame(uint32_t samples_ptr) { } void XAudio2AudioSystem::Shutdown() { + pcm_voice_->Stop(); + pcm_voice_->DestroyVoice(); + pcm_voice_ = NULL; + + mastering_voice_->DestroyVoice(); + mastering_voice_ = NULL; + + audio_->StopEngine(); + XESAFERELEASE(audio_); + + delete voice_callback_; + CloseHandle(wait_handle_); + AudioSystem::Shutdown(); } diff --git a/src/xenia/apu/xaudio2/xaudio2_audio_system.h b/src/xenia/apu/xaudio2/xaudio2_audio_system.h index 285494da0..f0fc750aa 100644 --- a/src/xenia/apu/xaudio2/xaudio2_audio_system.h +++ b/src/xenia/apu/xaudio2/xaudio2_audio_system.h @@ -41,6 +41,10 @@ private: IXAudio2MasteringVoice* mastering_voice_; IXAudio2SourceVoice* pcm_voice_; float samples_[1536]; + HANDLE wait_handle_; + + class VoiceCallback; + VoiceCallback* voice_callback_; };