Audio engine now blocking when buffers are full.
This commit is contained in:
parent
20ad328e4a
commit
f6ca6cced8
|
@ -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 {
|
||||||
|
|
|
@ -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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue