Audio engine now blocking when buffers are full.

This commit is contained in:
Ben Vanik 2014-01-13 00:20:53 -08:00
parent 20ad328e4a
commit f6ca6cced8
4 changed files with 54 additions and 7 deletions

View File

@ -22,7 +22,7 @@ using namespace xe::cpu;
AudioSystem::AudioSystem(Emulator* emulator) : AudioSystem::AudioSystem(Emulator* emulator) :
emulator_(emulator), memory_(emulator->memory()), emulator_(emulator), memory_(emulator->memory()),
thread_(0), running_(false), thread_(0), running_(false),
client_({ 0 }), can_submit_(false) { client_({ 0 }) {
// Create the run loop used for any windows/etc. // Create the run loop used for any windows/etc.
// This must be done on the thread we create the driver. // This must be done on the thread we create the driver.
run_loop_ = xe_run_loop_create(); run_loop_ = xe_run_loop_create();
@ -85,13 +85,14 @@ void AudioSystem::ThreadStart() {
} }
// Pump worker. // Pump worker.
// This may block.
Pump(); Pump();
xe_mutex_lock(lock_); xe_mutex_lock(lock_);
uint32_t client_callback = client_.callback; uint32_t client_callback = client_.callback;
uint32_t client_callback_arg = client_.wrapped_callback_arg; uint32_t client_callback_arg = client_.wrapped_callback_arg;
xe_mutex_unlock(lock_); xe_mutex_unlock(lock_);
if (client_callback && can_submit_) { if (client_callback) {
processor->Execute( processor->Execute(
thread_state_, client_callback, client_callback_arg, 0); thread_state_, client_callback, client_callback_arg, 0);
} else { } else {

View File

@ -82,7 +82,6 @@ protected:
uint32_t callback_arg; uint32_t callback_arg;
uint32_t wrapped_callback_arg; uint32_t wrapped_callback_arg;
} client_; } client_;
bool can_submit_;
}; };

View File

@ -19,8 +19,29 @@ using namespace xe::apu;
using namespace xe::apu::xaudio2; 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) : XAudio2AudioSystem::XAudio2AudioSystem(Emulator* emulator) :
audio_(0), mastering_voice_(0), pcm_voice_(0), audio_(0), mastering_voice_(0), pcm_voice_(0),
wait_handle_(NULL), voice_callback_(0),
AudioSystem(emulator) { AudioSystem(emulator) {
} }
@ -32,6 +53,10 @@ void XAudio2AudioSystem::Initialize() {
HRESULT hr; HRESULT hr;
wait_handle_ = CreateEvent(NULL, TRUE, TRUE, NULL);
voice_callback_ = new VoiceCallback(wait_handle_);
hr = XAudio2Create(&audio_, 0, XAUDIO2_DEFAULT_PROCESSOR); hr = XAudio2Create(&audio_, 0, XAUDIO2_DEFAULT_PROCESSOR);
if (FAILED(hr)) { if (FAILED(hr)) {
XELOGE("XAudio2Create failed with %.8X", hr); XELOGE("XAudio2Create failed with %.8X", hr);
@ -62,12 +87,16 @@ void XAudio2AudioSystem::Initialize() {
waveformat.nBlockAlign = 2; waveformat.nBlockAlign = 2;
waveformat.wBitsPerSample = 16; waveformat.wBitsPerSample = 16;
waveformat.cbSize = 0; 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)) { if (FAILED(hr)) {
XELOGE("CreateSourceVoice failed with %.8X", hr); XELOGE("CreateSourceVoice failed with %.8X", hr);
exit(1); exit(1);
} }
//
pcm_voice_->Start(); pcm_voice_->Start();
} }
@ -76,10 +105,11 @@ void XAudio2AudioSystem::Pump() {
pcm_voice_->GetState(&state); pcm_voice_->GetState(&state);
auto n = state.BuffersQueued; auto n = state.BuffersQueued;
if (n > 30) { if (n > 30) {
can_submit_ = false; // A lot of buffers are queued up, and until we use them block.
} else { ResetEvent(wait_handle_);
can_submit_ = true;
} }
WaitForSingleObject(wait_handle_, INFINITE);
} }
void XAudio2AudioSystem::SubmitFrame(uint32_t samples_ptr) { void XAudio2AudioSystem::SubmitFrame(uint32_t samples_ptr) {
@ -117,5 +147,18 @@ void XAudio2AudioSystem::SubmitFrame(uint32_t samples_ptr) {
} }
void XAudio2AudioSystem::Shutdown() { 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(); AudioSystem::Shutdown();
} }

View File

@ -41,6 +41,10 @@ private:
IXAudio2MasteringVoice* mastering_voice_; IXAudio2MasteringVoice* mastering_voice_;
IXAudio2SourceVoice* pcm_voice_; IXAudio2SourceVoice* pcm_voice_;
float samples_[1536]; float samples_[1536];
HANDLE wait_handle_;
class VoiceCallback;
VoiceCallback* voice_callback_;
}; };