Pump audio faster, up to XAUDIO2_MAX_QUEUED_BUFFERS (64) frames, then wait.

This commit is contained in:
gibbed 2015-05-25 02:49:49 -05:00
parent 517dce01b1
commit 8a5d3526e5
3 changed files with 32 additions and 11 deletions

View File

@ -405,7 +405,7 @@ void AudioSystem::SubmitFrame(size_t index, uint32_t samples_ptr) {
assert_true(index < maximum_client_count_); assert_true(index < maximum_client_count_);
assert_true(clients_[index].driver != NULL); assert_true(clients_[index].driver != NULL);
(clients_[index].driver)->SubmitFrame(samples_ptr); (clients_[index].driver)->SubmitFrame(samples_ptr);
ResetEvent(client_wait_handles_[index]); //ResetEvent(client_wait_handles_[index]);
} }
void AudioSystem::UnregisterClient(size_t index) { void AudioSystem::UnregisterClient(size_t index) {

View File

@ -40,6 +40,7 @@ XAudio2AudioDriver::XAudio2AudioDriver(Emulator* emulator, HANDLE wait)
pcm_voice_(0), pcm_voice_(0),
wait_handle_(wait), wait_handle_(wait),
voice_callback_(0), voice_callback_(0),
current_frame_(0),
AudioDriver(emulator) {} AudioDriver(emulator) {}
XAudio2AudioDriver::~XAudio2AudioDriver() {} XAudio2AudioDriver::~XAudio2AudioDriver() {}
@ -101,7 +102,8 @@ void XAudio2AudioDriver::Initialize() {
waveformat.Samples.wValidBitsPerSample = waveformat.Format.wBitsPerSample; waveformat.Samples.wValidBitsPerSample = waveformat.Format.wBitsPerSample;
waveformat.dwChannelMask = ChannelMasks[waveformat.Format.nChannels]; waveformat.dwChannelMask = ChannelMasks[waveformat.Format.nChannels];
hr = audio_->CreateSourceVoice(&pcm_voice_, &waveformat.Format, 0, hr = audio_->CreateSourceVoice(&pcm_voice_, &waveformat.Format,
0, // XAUDIO2_VOICE_NOSRC | XAUDIO2_VOICE_NOPITCH,
XAUDIO2_DEFAULT_FREQ_RATIO, voice_callback_); XAUDIO2_DEFAULT_FREQ_RATIO, voice_callback_);
if (FAILED(hr)) { if (FAILED(hr)) {
XELOGE("CreateSourceVoice failed with %.8X", hr); XELOGE("CreateSourceVoice failed with %.8X", hr);
@ -127,22 +129,28 @@ void XAudio2AudioDriver::SubmitFrame(uint32_t frame_ptr) {
// Process samples! They are big-endian floats. // Process samples! They are big-endian floats.
HRESULT hr; HRESULT hr;
XAUDIO2_VOICE_STATE state;
pcm_voice_->GetState(&state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
assert_true(state.BuffersQueued < frame_count_);
auto input_frame = memory_->TranslateVirtual<float*>(frame_ptr); auto input_frame = memory_->TranslateVirtual<float*>(frame_ptr);
auto output_frame = reinterpret_cast<float*>(frame_); auto output_frame = reinterpret_cast<float*>(frames_[current_frame_]);
auto interleave_channels = frame_channels_; auto interleave_channels = frame_channels_;
// interleave the data // interleave the data
for (int index = 0, o = 0; index < channel_samples_; ++index) { for (uint32_t index = 0, o = 0; index < channel_samples_; ++index) {
for (int channel = 0, table = 0; channel < interleave_channels; for (uint32_t channel = 0, table = 0; channel < interleave_channels;
++channel, table += channel_samples_) { ++channel, table += channel_samples_) {
output_frame[o++] = xe::byte_swap(input_frame[table + index]); output_frame[o++] = xe::byte_swap(input_frame[table + index]);
} }
} }
XELOGE("Submitting audio frame %u", current_frame_);
XAUDIO2_BUFFER buffer; XAUDIO2_BUFFER buffer;
buffer.Flags = 0; buffer.Flags = 0;
buffer.pAudioData = (BYTE*)frame_; buffer.pAudioData = (BYTE*)output_frame;
buffer.AudioBytes = sizeof(frame_); buffer.AudioBytes = frame_size_;
buffer.PlayBegin = 0; buffer.PlayBegin = 0;
buffer.PlayLength = channel_samples_; buffer.PlayLength = channel_samples_;
buffer.LoopBegin = XAUDIO2_NO_LOOP_REGION; buffer.LoopBegin = XAUDIO2_NO_LOOP_REGION;
@ -155,6 +163,15 @@ void XAudio2AudioDriver::SubmitFrame(uint32_t frame_ptr) {
assert_always(); assert_always();
return; return;
} }
current_frame_ = (current_frame_ + 1) % frame_count_;
XAUDIO2_VOICE_STATE state2;
pcm_voice_->GetState(&state2, XAUDIO2_VOICE_NOSAMPLESPLAYED);
if (state2.BuffersQueued >= frame_count_) {
ResetEvent(wait_handle_);
}
} }
void XAudio2AudioDriver::Shutdown() { void XAudio2AudioDriver::Shutdown() {
@ -169,7 +186,6 @@ void XAudio2AudioDriver::Shutdown() {
audio_->Release(); audio_->Release();
delete voice_callback_; delete voice_callback_;
CloseHandle(wait_handle_);
} }
} // namespace xaudio2 } // namespace xaudio2

View File

@ -32,13 +32,18 @@ class XAudio2AudioDriver : public AudioDriver {
IXAudio2* audio_; IXAudio2* audio_;
IXAudio2MasteringVoice* mastering_voice_; IXAudio2MasteringVoice* mastering_voice_;
IXAudio2SourceVoice* pcm_voice_; IXAudio2SourceVoice* pcm_voice_;
static const int frame_channels_ = 6;
static const int channel_samples_ = 256;
float frame_[frame_channels_ * channel_samples_];
HANDLE wait_handle_; HANDLE wait_handle_;
class VoiceCallback; class VoiceCallback;
VoiceCallback* voice_callback_; VoiceCallback* voice_callback_;
static const uint32_t frame_count_ = XAUDIO2_MAX_QUEUED_BUFFERS;
static const uint32_t frame_channels_ = 6;
static const uint32_t channel_samples_ = 256;
static const uint32_t frame_samples_ = frame_channels_ * channel_samples_;
static const uint32_t frame_size_ = sizeof(float) * frame_samples_;
float frames_[frame_count_][frame_samples_];
uint32_t current_frame_;
}; };
} // namespace xaudio2 } // namespace xaudio2