summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/sound/xaudio2_sound.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/sound/xaudio2_sound.cpp')
-rw-r--r--src/osd/modules/sound/xaudio2_sound.cpp878
1 files changed, 439 insertions, 439 deletions
diff --git a/src/osd/modules/sound/xaudio2_sound.cpp b/src/osd/modules/sound/xaudio2_sound.cpp
index c11151d2aae..7df854c0364 100644
--- a/src/osd/modules/sound/xaudio2_sound.cpp
+++ b/src/osd/modules/sound/xaudio2_sound.cpp
@@ -51,10 +51,10 @@
// Check HRESULT result and log if error, then take an optional action on failure
#define HR_LOG( CALL, LOGFN, ONFAIL ) do { \
- result = CALL; \
- if (FAILED(result)) { \
- LOGFN(#CALL " failed with error 0x%X\n", (unsigned int)result); \
- ONFAIL; } \
+ result = CALL; \
+ if (FAILED(result)) { \
+ LOGFN(#CALL " failed with error 0x%X\n", (unsigned int)result); \
+ ONFAIL; } \
} while (0)
// Variant of HR_LOG to log using osd_printf_error
@@ -91,47 +91,47 @@
// A stucture to hold a pointer and the count of bytes of the data it points to
struct xaudio2_buffer
{
- std::unique_ptr<BYTE[]> AudioData;
- DWORD AudioSize;
+ std::unique_ptr<BYTE[]> AudioData;
+ DWORD AudioSize;
};
// Custom deleter with overloads to free smart pointer types used in the implementations
struct xaudio2_custom_deleter
{
public:
- void operator()(IXAudio2* obj) const
- {
- if (obj != nullptr)
- {
- obj->Release();
- }
- }
-
- void operator()(IXAudio2MasteringVoice* obj) const
- {
- if (obj != nullptr)
- {
- obj->DestroyVoice();
- }
- }
-
- void operator()(IXAudio2SourceVoice* obj) const
- {
- if (obj != nullptr)
- {
- obj->Stop(0);
- obj->FlushSourceBuffers();
- obj->DestroyVoice();
- }
- }
-
- void operator()(osd_lock* obj) const
- {
- if (obj != nullptr)
- {
- osd_lock_free(obj);
- }
- }
+ void operator()(IXAudio2* obj) const
+ {
+ if (obj != nullptr)
+ {
+ obj->Release();
+ }
+ }
+
+ void operator()(IXAudio2MasteringVoice* obj) const
+ {
+ if (obj != nullptr)
+ {
+ obj->DestroyVoice();
+ }
+ }
+
+ void operator()(IXAudio2SourceVoice* obj) const
+ {
+ if (obj != nullptr)
+ {
+ obj->Stop(0);
+ obj->FlushSourceBuffers();
+ obj->DestroyVoice();
+ }
+ }
+
+ void operator()(osd_lock* obj) const
+ {
+ if (obj != nullptr)
+ {
+ osd_lock_free(obj);
+ }
+ }
};
// Typedefs for smart pointers used with customer deleters
@@ -151,70 +151,70 @@ typedef HRESULT(__stdcall* PFN_XAUDIO2CREATE)(IXAudio2**, UINT32, XAUDIO2_PROCES
class osd_scoped_lock
{
private:
- osd_lock * m_lock;
+ osd_lock * m_lock;
public:
- osd_scoped_lock(osd_lock* lock)
- {
- m_lock = lock;
- osd_lock_acquire(m_lock);
- }
-
- ~osd_scoped_lock()
- {
- if (m_lock != nullptr)
- {
- osd_lock_release(m_lock);
- }
- }
+ osd_scoped_lock(osd_lock* lock)
+ {
+ m_lock = lock;
+ osd_lock_acquire(m_lock);
+ }
+
+ ~osd_scoped_lock()
+ {
+ if (m_lock != nullptr)
+ {
+ osd_lock_release(m_lock);
+ }
+ }
};
// Provides a pool of buffers
class bufferpool
{
private:
- int m_initial;
- int m_buffersize;
- std::queue<std::unique_ptr<BYTE[]>> m_queue;
+ int m_initial;
+ int m_buffersize;
+ std::queue<std::unique_ptr<BYTE[]>> m_queue;
public:
- // constructor
- bufferpool(int capacity, int bufferSize) :
- m_initial(capacity),
- m_buffersize(bufferSize)
- {
- for (int i = 0; i < m_initial; i++)
- {
- auto newBuffer = std::make_unique<BYTE[]>(m_buffersize);
- memset(newBuffer.get(), 0, m_buffersize);
- m_queue.push(std::move(newBuffer));
- }
- }
-
- // get next buffer element from the pool
- BYTE* next()
- {
- BYTE* next_buffer;
- if (!m_queue.empty())
- {
- next_buffer = m_queue.front().release();
- m_queue.pop();
- }
- else
- {
- next_buffer = new BYTE[m_buffersize];
- memset(next_buffer, 0, m_buffersize);
- }
-
- return next_buffer;
- }
-
- // release element, make it available back in the pool
- void return_to_pool(BYTE* buffer)
- {
- auto returned_buf = std::unique_ptr<BYTE[]>(buffer);
- memset(returned_buf.get(), 0, m_buffersize);
- m_queue.push(std::move(returned_buf));
- }
+ // constructor
+ bufferpool(int capacity, int bufferSize) :
+ m_initial(capacity),
+ m_buffersize(bufferSize)
+ {
+ for (int i = 0; i < m_initial; i++)
+ {
+ auto newBuffer = std::make_unique<BYTE[]>(m_buffersize);
+ memset(newBuffer.get(), 0, m_buffersize);
+ m_queue.push(std::move(newBuffer));
+ }
+ }
+
+ // get next buffer element from the pool
+ BYTE* next()
+ {
+ BYTE* next_buffer;
+ if (!m_queue.empty())
+ {
+ next_buffer = m_queue.front().release();
+ m_queue.pop();
+ }
+ else
+ {
+ next_buffer = new BYTE[m_buffersize];
+ memset(next_buffer, 0, m_buffersize);
+ }
+
+ return next_buffer;
+ }
+
+ // release element, make it available back in the pool
+ void return_to_pool(BYTE* buffer)
+ {
+ auto returned_buf = std::unique_ptr<BYTE[]>(buffer);
+ memset(returned_buf.get(), 0, m_buffersize);
+ m_queue.push(std::move(returned_buf));
+ }
};
//============================================================
@@ -225,77 +225,77 @@ public:
class sound_xaudio2 : public osd_module, public sound_module, public IXAudio2VoiceCallback
{
private:
- xaudio2_ptr m_xAudio2;
- mastering_voice_ptr m_masterVoice;
- src_voice_ptr m_sourceVoice;
- DWORD m_sample_bytes;
- std::unique_ptr<BYTE[]> m_buffer;
- DWORD m_buffer_size;
- DWORD m_buffer_count;
- DWORD m_writepos;
- osd_lock_ptr m_buffer_lock;
- HANDLE m_hEventBufferCompleted;
- HANDLE m_hEventDataAvailable;
- HANDLE m_hEventExiting;
- std::thread m_audioThread;
- std::queue<xaudio2_buffer> m_queue;
- std::unique_ptr<bufferpool> m_buffer_pool;
- HMODULE m_xaudio2_module;
- PFN_XAUDIO2CREATE m_pfnxaudio2create;
- UINT32 m_overflows;
- UINT32 m_underflows;
- BOOL m_in_underflow;
+ xaudio2_ptr m_xAudio2;
+ mastering_voice_ptr m_masterVoice;
+ src_voice_ptr m_sourceVoice;
+ DWORD m_sample_bytes;
+ std::unique_ptr<BYTE[]> m_buffer;
+ DWORD m_buffer_size;
+ DWORD m_buffer_count;
+ DWORD m_writepos;
+ osd_lock_ptr m_buffer_lock;
+ HANDLE m_hEventBufferCompleted;
+ HANDLE m_hEventDataAvailable;
+ HANDLE m_hEventExiting;
+ std::thread m_audioThread;
+ std::queue<xaudio2_buffer> m_queue;
+ std::unique_ptr<bufferpool> m_buffer_pool;
+ HMODULE m_xaudio2_module;
+ PFN_XAUDIO2CREATE m_pfnxaudio2create;
+ UINT32 m_overflows;
+ UINT32 m_underflows;
+ BOOL m_in_underflow;
public:
- sound_xaudio2() :
- osd_module(OSD_SOUND_PROVIDER, "xaudio2"),
- sound_module(),
- m_xAudio2(nullptr),
- m_masterVoice(nullptr),
- m_sourceVoice(nullptr),
- m_sample_bytes(0),
- m_buffer(nullptr),
- m_buffer_size(0),
- m_buffer_count(0),
- m_writepos(0),
- m_buffer_lock(osd_lock_alloc()),
- m_hEventBufferCompleted(NULL),
- m_hEventDataAvailable(NULL),
- m_hEventExiting(NULL),
- m_buffer_pool(nullptr),
- m_xaudio2_module(NULL),
- m_pfnxaudio2create(nullptr),
- m_overflows(0),
- m_underflows(0),
- m_in_underflow(FALSE)
- {
- }
-
- virtual int init(osd_options const &options) override;
- virtual void exit() override;
-
- // sound_module
- virtual void update_audio_stream(bool is_throttled, INT16 const *buffer, int samples_this_frame) override;
- virtual void set_mastervolume(int attenuation) override;
-
- // Xaudio callbacks
- void OnVoiceProcessingPassStart(UINT32 bytes_required) override;
- void OnVoiceProcessingPassEnd() override {}
- void OnStreamEnd() override {}
- void OnBufferStart(void* pBufferContext) override {}
- void OnLoopEnd(void* pBufferContext) override {}
- void OnVoiceError(void* pBufferContext, HRESULT error) override {}
- void OnBufferEnd(void *pBufferContext) override;
-
+ sound_xaudio2() :
+ osd_module(OSD_SOUND_PROVIDER, "xaudio2"),
+ sound_module(),
+ m_xAudio2(nullptr),
+ m_masterVoice(nullptr),
+ m_sourceVoice(nullptr),
+ m_sample_bytes(0),
+ m_buffer(nullptr),
+ m_buffer_size(0),
+ m_buffer_count(0),
+ m_writepos(0),
+ m_buffer_lock(osd_lock_alloc()),
+ m_hEventBufferCompleted(NULL),
+ m_hEventDataAvailable(NULL),
+ m_hEventExiting(NULL),
+ m_buffer_pool(nullptr),
+ m_xaudio2_module(NULL),
+ m_pfnxaudio2create(nullptr),
+ m_overflows(0),
+ m_underflows(0),
+ m_in_underflow(FALSE)
+ {
+ }
+
+ virtual int init(osd_options const &options) override;
+ virtual void exit() override;
+
+ // sound_module
+ virtual void update_audio_stream(bool is_throttled, INT16 const *buffer, int samples_this_frame) override;
+ virtual void set_mastervolume(int attenuation) override;
+
+ // Xaudio callbacks
+ void OnVoiceProcessingPassStart(UINT32 bytes_required) override;
+ void OnVoiceProcessingPassEnd() override {}
+ void OnStreamEnd() override {}
+ void OnBufferStart(void* pBufferContext) override {}
+ void OnLoopEnd(void* pBufferContext) override {}
+ void OnVoiceError(void* pBufferContext, HRESULT error) override {}
+ void OnBufferEnd(void *pBufferContext) override;
+
private:
- void create_buffers(const WAVEFORMATEX &format);
- HRESULT create_voices(const WAVEFORMATEX &format);
- void process_audio();
- void submit_buffer(std::unique_ptr<BYTE[]> audioData, DWORD audioLength);
- void submit_needed();
- HRESULT xaudio2_create(IXAudio2 ** xaudio2_interface);
- void roll_buffer();
- BOOL submit_next_queued();
+ void create_buffers(const WAVEFORMATEX &format);
+ HRESULT create_voices(const WAVEFORMATEX &format);
+ void process_audio();
+ void submit_buffer(std::unique_ptr<BYTE[]> audioData, DWORD audioLength);
+ void submit_needed();
+ HRESULT xaudio2_create(IXAudio2 ** xaudio2_interface);
+ void roll_buffer();
+ BOOL submit_next_queued();
};
//============================================================
@@ -304,49 +304,49 @@ private:
int sound_xaudio2::init(osd_options const &options)
{
- HRESULT result = S_OK;
+ HRESULT result = S_OK;
- // Create the IXAudio2 object
- IXAudio2 *temp_xaudio2 = nullptr;
- HR_RET1(xaudio2_create(&temp_xaudio2));
- m_xAudio2 = xaudio2_ptr(temp_xaudio2);
+ // Create the IXAudio2 object
+ IXAudio2 *temp_xaudio2 = nullptr;
+ HR_RET1(xaudio2_create(&temp_xaudio2));
+ m_xAudio2 = xaudio2_ptr(temp_xaudio2);
- // make a format description for what we want
- WAVEFORMATEX format = { 0 };
- format.wBitsPerSample = 16;
- format.wFormatTag = WAVE_FORMAT_PCM;
- format.nChannels = 2;
- format.nSamplesPerSec = sample_rate();
- format.nBlockAlign = format.wBitsPerSample * format.nChannels / 8;
- format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
+ // make a format description for what we want
+ WAVEFORMATEX format = { 0 };
+ format.wBitsPerSample = 16;
+ format.wFormatTag = WAVE_FORMAT_PCM;
+ format.nChannels = 2;
+ format.nSamplesPerSec = sample_rate();
+ format.nBlockAlign = format.wBitsPerSample * format.nChannels / 8;
+ format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
- m_sample_bytes = format.nBlockAlign;
+ m_sample_bytes = format.nBlockAlign;
#if defined(_DEBUG)
- XAUDIO2_DEBUG_CONFIGURATION debugConfig = { 0 };
- debugConfig.TraceMask = XAUDIO2_LOG_WARNINGS | XAUDIO2_LOG_TIMING | XAUDIO2_LOG_STREAMING;
- debugConfig.LogFunctionName = TRUE;
- m_xAudio2->SetDebugConfiguration(&debugConfig);
+ XAUDIO2_DEBUG_CONFIGURATION debugConfig = { 0 };
+ debugConfig.TraceMask = XAUDIO2_LOG_WARNINGS | XAUDIO2_LOG_TIMING | XAUDIO2_LOG_STREAMING;
+ debugConfig.LogFunctionName = TRUE;
+ m_xAudio2->SetDebugConfiguration(&debugConfig);
#endif
- // Create the buffers
- create_buffers(format);
+ // Create the buffers
+ create_buffers(format);
- // Initialize our events
- m_hEventBufferCompleted = CreateEvent(NULL, FALSE, FALSE, NULL);
- m_hEventDataAvailable = CreateEvent(NULL, FALSE, FALSE, NULL);
- m_hEventExiting = CreateEvent(NULL, FALSE, FALSE, NULL);
+ // Initialize our events
+ m_hEventBufferCompleted = CreateEvent(NULL, FALSE, FALSE, NULL);
+ m_hEventDataAvailable = CreateEvent(NULL, FALSE, FALSE, NULL);
+ m_hEventExiting = CreateEvent(NULL, FALSE, FALSE, NULL);
- // create the voices and start them
- HR_RET1(create_voices(format));
- HR_RET1(m_sourceVoice->Start());
+ // create the voices and start them
+ HR_RET1(create_voices(format));
+ HR_RET1(m_sourceVoice->Start());
- // Start the thread listening
- m_audioThread = std::thread([](sound_xaudio2* self) { self->process_audio(); }, this);
+ // Start the thread listening
+ m_audioThread = std::thread([](sound_xaudio2* self) { self->process_audio(); }, this);
- osd_printf_verbose("Sound: XAudio2 initialized\n");
+ osd_printf_verbose("Sound: XAudio2 initialized\n");
- return 0;
+ return 0;
}
//============================================================
@@ -355,24 +355,24 @@ int sound_xaudio2::init(osd_options const &options)
void sound_xaudio2::exit()
{
- // Wait on processing thread to end
- SetEvent(m_hEventExiting);
- m_audioThread.join();
+ // Wait on processing thread to end
+ SetEvent(m_hEventExiting);
+ m_audioThread.join();
- CloseHandle(m_hEventBufferCompleted);
- CloseHandle(m_hEventDataAvailable);
- CloseHandle(m_hEventExiting);
+ CloseHandle(m_hEventBufferCompleted);
+ CloseHandle(m_hEventDataAvailable);
+ CloseHandle(m_hEventExiting);
- m_sourceVoice.reset();
- m_masterVoice.reset();
- m_xAudio2.reset();
- m_buffer.reset();
- m_buffer_pool.reset();
+ m_sourceVoice.reset();
+ m_masterVoice.reset();
+ m_xAudio2.reset();
+ m_buffer.reset();
+ m_buffer_pool.reset();
- if (m_overflows != 0 || m_underflows != 0)
- osd_printf_verbose("Sound: overflows=%u, underflows=%u\n", m_overflows, m_underflows);
+ if (m_overflows != 0 || m_underflows != 0)
+ osd_printf_verbose("Sound: overflows=%u, underflows=%u\n", m_overflows, m_underflows);
- osd_printf_verbose("Sound: XAudio2 deinitialized\n");
+ osd_printf_verbose("Sound: XAudio2 deinitialized\n");
}
//============================================================
@@ -380,37 +380,37 @@ void sound_xaudio2::exit()
//============================================================
void sound_xaudio2::update_audio_stream(
- bool is_throttled,
- INT16 const *buffer,
- int samples_this_frame)
+ bool is_throttled,
+ INT16 const *buffer,
+ int samples_this_frame)
{
- if ((sample_rate() == 0) || !m_buffer)
- return;
+ if ((sample_rate() == 0) || !m_buffer)
+ return;
- UINT32 const bytes_this_frame = samples_this_frame * m_sample_bytes;
+ UINT32 const bytes_this_frame = samples_this_frame * m_sample_bytes;
- osd_scoped_lock scope_lock(m_buffer_lock.get());
+ osd_scoped_lock scope_lock(m_buffer_lock.get());
- UINT32 bytes_left = bytes_this_frame;
+ UINT32 bytes_left = bytes_this_frame;
- while (bytes_left > 0)
- {
- UINT32 chunk = MIN(m_buffer_size, bytes_left);
+ while (bytes_left > 0)
+ {
+ UINT32 chunk = MIN(m_buffer_size, bytes_left);
- // Roll the buffer if needed
- if (m_writepos + chunk >= m_buffer_size)
- {
- roll_buffer();
- }
+ // Roll the buffer if needed
+ if (m_writepos + chunk >= m_buffer_size)
+ {
+ roll_buffer();
+ }
- // Copy in the data
- memcpy(m_buffer.get() + m_writepos, buffer, chunk);
- m_writepos += chunk;
- bytes_left -= chunk;
- }
+ // Copy in the data
+ memcpy(m_buffer.get() + m_writepos, buffer, chunk);
+ m_writepos += chunk;
+ bytes_left -= chunk;
+ }
- // Signal data available
- SetEvent(m_hEventDataAvailable);
+ // Signal data available
+ SetEvent(m_hEventDataAvailable);
}
//============================================================
@@ -419,21 +419,21 @@ void sound_xaudio2::update_audio_stream(
void sound_xaudio2::set_mastervolume(int attenuation)
{
- assert(m_sourceVoice);
-
- HRESULT result;
-
- // clamp the attenuation to 0-32 range
- attenuation = MAX(MIN(attenuation, 0), -32);
-
- // Ranges from 1.0 to XAUDIO2_MAX_VOLUME_LEVEL indicate additional gain
- // Ranges from 0 to 1.0 indicate a reduced volume level
- // 0 indicates silence
- // We only support a reduction from 1.0, so we generate values in the range 0.0 to 1.0
- float scaledVolume = (32.0f + attenuation) / 32.0f;
-
- // set the master volume
- HR_RETV(m_sourceVoice->SetVolume(scaledVolume));
+ assert(m_sourceVoice);
+
+ HRESULT result;
+
+ // clamp the attenuation to 0-32 range
+ attenuation = MAX(MIN(attenuation, 0), -32);
+
+ // Ranges from 1.0 to XAUDIO2_MAX_VOLUME_LEVEL indicate additional gain
+ // Ranges from 0 to 1.0 indicate a reduced volume level
+ // 0 indicates silence
+ // We only support a reduction from 1.0, so we generate values in the range 0.0 to 1.0
+ float scaledVolume = (32.0f + attenuation) / 32.0f;
+
+ // set the master volume
+ HR_RETV(m_sourceVoice->SetVolume(scaledVolume));
}
//============================================================
@@ -443,14 +443,14 @@ void sound_xaudio2::set_mastervolume(int attenuation)
// The XAudio2 voice callback triggered when a buffer finishes playing
void sound_xaudio2::OnBufferEnd(void *pBufferContext)
{
- BYTE* completed_buffer = (BYTE*)pBufferContext;
- if (completed_buffer != nullptr)
- {
- auto scoped_lock = osd_scoped_lock(m_buffer_lock.get());
- m_buffer_pool->return_to_pool(completed_buffer);
- }
-
- SetEvent(m_hEventBufferCompleted);
+ BYTE* completed_buffer = (BYTE*)pBufferContext;
+ if (completed_buffer != nullptr)
+ {
+ auto scoped_lock = osd_scoped_lock(m_buffer_lock.get());
+ m_buffer_pool->return_to_pool(completed_buffer);
+ }
+
+ SetEvent(m_hEventBufferCompleted);
}
//============================================================
@@ -460,20 +460,20 @@ void sound_xaudio2::OnBufferEnd(void *pBufferContext)
// The XAudio2 voice callback triggered on every pass
void sound_xaudio2::OnVoiceProcessingPassStart(UINT32 bytes_required)
{
- if (bytes_required == 0)
- {
- // Reset underflow indicator if we're caught up
- if (m_in_underflow) m_in_underflow = FALSE;
-
- return;
- }
-
- // Since there are bytes required, we're going to be in underflow
- if (!m_in_underflow)
- {
- m_underflows++;
- m_in_underflow = TRUE;
- }
+ if (bytes_required == 0)
+ {
+ // Reset underflow indicator if we're caught up
+ if (m_in_underflow) m_in_underflow = FALSE;
+
+ return;
+ }
+
+ // Since there are bytes required, we're going to be in underflow
+ if (!m_in_underflow)
+ {
+ m_underflows++;
+ m_in_underflow = TRUE;
+ }
}
//============================================================
@@ -483,31 +483,31 @@ void sound_xaudio2::OnVoiceProcessingPassStart(UINT32 bytes_required)
// Dynamically loads the XAudio2 DLL and calls the exported XAudio2Create()
HRESULT sound_xaudio2::xaudio2_create(IXAudio2 ** ppxaudio2_interface)
{
- HRESULT result;
-
- if (nullptr == m_pfnxaudio2create)
- {
- if (nullptr == m_xaudio2_module)
- {
- m_xaudio2_module = LoadLibrary(XAUDIO2_DLL);
- if (nullptr == m_xaudio2_module)
- {
- osd_printf_error("Failed to load module '%S', error: 0x%X\n", XAUDIO2_DLL, (unsigned int)GetLastError());
- HR_RETHR(E_FAIL);
- }
- }
-
- m_pfnxaudio2create = (PFN_XAUDIO2CREATE)GetProcAddress(m_xaudio2_module, "XAudio2Create");
- if (nullptr == m_pfnxaudio2create)
- {
- osd_printf_error("Failed to get adddress of exported function XAudio2Create, error: 0x%X\n", (unsigned int)GetLastError());
- HR_RETHR(E_FAIL);
- }
- }
-
- HR_RETHR(m_pfnxaudio2create(ppxaudio2_interface, 0, XAUDIO2_DEFAULT_PROCESSOR));
-
- return S_OK;
+ HRESULT result;
+
+ if (nullptr == m_pfnxaudio2create)
+ {
+ if (nullptr == m_xaudio2_module)
+ {
+ m_xaudio2_module = LoadLibrary(XAUDIO2_DLL);
+ if (nullptr == m_xaudio2_module)
+ {
+ osd_printf_error("Failed to load module '%S', error: 0x%X\n", XAUDIO2_DLL, (unsigned int)GetLastError());
+ HR_RETHR(E_FAIL);
+ }
+ }
+
+ m_pfnxaudio2create = (PFN_XAUDIO2CREATE)GetProcAddress(m_xaudio2_module, "XAudio2Create");
+ if (nullptr == m_pfnxaudio2create)
+ {
+ osd_printf_error("Failed to get adddress of exported function XAudio2Create, error: 0x%X\n", (unsigned int)GetLastError());
+ HR_RETHR(E_FAIL);
+ }
+ }
+
+ HR_RETHR(m_pfnxaudio2create(ppxaudio2_interface, 0, XAUDIO2_DEFAULT_PROCESSOR));
+
+ return S_OK;
}
//============================================================
@@ -516,38 +516,38 @@ HRESULT sound_xaudio2::xaudio2_create(IXAudio2 ** ppxaudio2_interface)
void sound_xaudio2::create_buffers(const WAVEFORMATEX &format)
{
- // Compute the buffer size
- // buffer size is equal to the bytes we need to hold in memory per X tenths of a second where X is audio_latency
- float audio_latency_in_seconds = m_audio_latency / 10.0f;
- UINT32 format_bytes_per_second = format.nSamplesPerSec * format.nBlockAlign;
- UINT32 total_buffer_size = format_bytes_per_second * audio_latency_in_seconds;
-
- // We want to be able to submit buffers every X milliseconds
- // I want to divide these up into "packets" so figure out how many buffers we need
- m_buffer_count = (audio_latency_in_seconds * 1000.0f) / SUBMIT_FREQUENCY_TARGET_MS;
-
- // Now record the size of the individual buffers
- m_buffer_size = MAX(1024, total_buffer_size / m_buffer_count);
-
- // Make the buffer a multiple of the format size bytes (rounding up)
- UINT32 remainder = m_buffer_size % format.nBlockAlign;
- if (remainder != 0)
- m_buffer_size += format.nBlockAlign - remainder;
-
- // get our initial buffer pool and our first buffer
- m_buffer_pool = std::make_unique<bufferpool>(m_buffer_count + 1, m_buffer_size);
- m_buffer = std::unique_ptr<BYTE[]>(m_buffer_pool->next());
-
- osd_printf_verbose(
- "Sound: XAudio2 created initial buffers. total size: %u, count %u, size each %u\n",
- (unsigned int)total_buffer_size,
- (unsigned int)m_buffer_count,
- (unsigned int)m_buffer_size);
-
- // reset buffer states
- m_writepos = 0;
- m_overflows = 0;
- m_underflows = 0;
+ // Compute the buffer size
+ // buffer size is equal to the bytes we need to hold in memory per X tenths of a second where X is audio_latency
+ float audio_latency_in_seconds = m_audio_latency / 10.0f;
+ UINT32 format_bytes_per_second = format.nSamplesPerSec * format.nBlockAlign;
+ UINT32 total_buffer_size = format_bytes_per_second * audio_latency_in_seconds;
+
+ // We want to be able to submit buffers every X milliseconds
+ // I want to divide these up into "packets" so figure out how many buffers we need
+ m_buffer_count = (audio_latency_in_seconds * 1000.0f) / SUBMIT_FREQUENCY_TARGET_MS;
+
+ // Now record the size of the individual buffers
+ m_buffer_size = MAX(1024, total_buffer_size / m_buffer_count);
+
+ // Make the buffer a multiple of the format size bytes (rounding up)
+ UINT32 remainder = m_buffer_size % format.nBlockAlign;
+ if (remainder != 0)
+ m_buffer_size += format.nBlockAlign - remainder;
+
+ // get our initial buffer pool and our first buffer
+ m_buffer_pool = std::make_unique<bufferpool>(m_buffer_count + 1, m_buffer_size);
+ m_buffer = std::unique_ptr<BYTE[]>(m_buffer_pool->next());
+
+ osd_printf_verbose(
+ "Sound: XAudio2 created initial buffers. total size: %u, count %u, size each %u\n",
+ (unsigned int)total_buffer_size,
+ (unsigned int)m_buffer_count,
+ (unsigned int)m_buffer_size);
+
+ // reset buffer states
+ m_writepos = 0;
+ m_overflows = 0;
+ m_underflows = 0;
}
//============================================================
@@ -556,31 +556,31 @@ void sound_xaudio2::create_buffers(const WAVEFORMATEX &format)
HRESULT sound_xaudio2::create_voices(const WAVEFORMATEX &format)
{
- assert(m_xAudio2);
- assert(!m_masterVoice);
- HRESULT result;
-
- IXAudio2MasteringVoice *temp_master_voice = nullptr;
- HR_RET1(
- m_xAudio2->CreateMasteringVoice(
- &temp_master_voice,
- format.nChannels,
- sample_rate()));
-
- m_masterVoice = mastering_voice_ptr(temp_master_voice);
-
- // create the source voice
- IXAudio2SourceVoice *temp_source_voice = nullptr;
- HR_RET1(m_xAudio2->CreateSourceVoice(
- &temp_source_voice,
- &format,
- XAUDIO2_VOICE_NOSRC | XAUDIO2_VOICE_NOPITCH,
- 1.0,
- this));
-
- m_sourceVoice = src_voice_ptr(temp_source_voice);
-
- return S_OK;
+ assert(m_xAudio2);
+ assert(!m_masterVoice);
+ HRESULT result;
+
+ IXAudio2MasteringVoice *temp_master_voice = nullptr;
+ HR_RET1(
+ m_xAudio2->CreateMasteringVoice(
+ &temp_master_voice,
+ format.nChannels,
+ sample_rate()));
+
+ m_masterVoice = mastering_voice_ptr(temp_master_voice);
+
+ // create the source voice
+ IXAudio2SourceVoice *temp_source_voice = nullptr;
+ HR_RET1(m_xAudio2->CreateSourceVoice(
+ &temp_source_voice,
+ &format,
+ XAUDIO2_VOICE_NOSRC | XAUDIO2_VOICE_NOPITCH,
+ 1.0,
+ this));
+
+ m_sourceVoice = src_voice_ptr(temp_source_voice);
+
+ return S_OK;
}
//============================================================
@@ -590,48 +590,48 @@ HRESULT sound_xaudio2::create_voices(const WAVEFORMATEX &format)
// submits audio events on another thread in a loop
void sound_xaudio2::process_audio()
{
- BOOL exiting = FALSE;
- HANDLE hEvents[] = { m_hEventBufferCompleted, m_hEventDataAvailable, m_hEventExiting };
- while (!exiting)
- {
- DWORD wait_result = WaitForMultipleObjects(3, hEvents, FALSE, INFINITE);
- switch (wait_result)
- {
- // Buffer is complete or new data is available
- case 0:
- case 1:
- submit_needed();
- break;
- case 2:
- // exiting
- exiting = TRUE;
- break;
- }
- }
+ BOOL exiting = FALSE;
+ HANDLE hEvents[] = { m_hEventBufferCompleted, m_hEventDataAvailable, m_hEventExiting };
+ while (!exiting)
+ {
+ DWORD wait_result = WaitForMultipleObjects(3, hEvents, FALSE, INFINITE);
+ switch (wait_result)
+ {
+ // Buffer is complete or new data is available
+ case 0:
+ case 1:
+ submit_needed();
+ break;
+ case 2:
+ // exiting
+ exiting = TRUE;
+ break;
+ }
+ }
}
//============================================================
// submit_needed
//============================================================
-// Submits any buffers that have currently been queued,
+// Submits any buffers that have currently been queued,
// assuming they are needed based on current queue depth
void sound_xaudio2::submit_needed()
{
- XAUDIO2_VOICE_STATE state;
- m_sourceVoice->GetState(&state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
+ XAUDIO2_VOICE_STATE state;
+ m_sourceVoice->GetState(&state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
- // If we have a buffer on the queue, no reason to submit
- if (state.BuffersQueued >= 1)
- return;
+ // If we have a buffer on the queue, no reason to submit
+ if (state.BuffersQueued >= 1)
+ return;
- osd_scoped_lock lock_scope(m_buffer_lock.get());
+ osd_scoped_lock lock_scope(m_buffer_lock.get());
- // Roll the buffer
- roll_buffer();
+ // Roll the buffer
+ roll_buffer();
- // Submit the next buffer
- submit_next_queued();
+ // Submit the next buffer
+ submit_next_queued();
}
//============================================================
@@ -640,27 +640,27 @@ void sound_xaudio2::submit_needed()
void sound_xaudio2::submit_buffer(std::unique_ptr<BYTE[]> audioData, DWORD audioLength)
{
- assert(audioLength != 0);
-
- XAUDIO2_BUFFER buf = { 0 };
- buf.AudioBytes = audioLength;
- buf.pAudioData = audioData.get();
- buf.PlayBegin = 0;
- buf.PlayLength = audioLength / m_sample_bytes;
- buf.Flags = XAUDIO2_END_OF_STREAM;
- buf.pContext = audioData.get();
-
- HRESULT result;
- if (FAILED(result = m_sourceVoice->SubmitSourceBuffer(&buf)))
- {
- osd_printf_verbose("Sound: XAudio2 failed to submit source buffer (non-fatal). Error: 0x%X\n", (unsigned int)result);
- m_buffer_pool->return_to_pool(audioData.release());
- return;
- }
-
- // If we succeeded, relinquish the buffer allocation to the XAudio2 runtime
- // The buffer will be freed on the OnBufferCompleted callback
- audioData.release();
+ assert(audioLength != 0);
+
+ XAUDIO2_BUFFER buf = { 0 };
+ buf.AudioBytes = audioLength;
+ buf.pAudioData = audioData.get();
+ buf.PlayBegin = 0;
+ buf.PlayLength = audioLength / m_sample_bytes;
+ buf.Flags = XAUDIO2_END_OF_STREAM;
+ buf.pContext = audioData.get();
+
+ HRESULT result;
+ if (FAILED(result = m_sourceVoice->SubmitSourceBuffer(&buf)))
+ {
+ osd_printf_verbose("Sound: XAudio2 failed to submit source buffer (non-fatal). Error: 0x%X\n", (unsigned int)result);
+ m_buffer_pool->return_to_pool(audioData.release());
+ return;
+ }
+
+ // If we succeeded, relinquish the buffer allocation to the XAudio2 runtime
+ // The buffer will be freed on the OnBufferCompleted callback
+ audioData.release();
}
//============================================================
@@ -669,23 +669,23 @@ void sound_xaudio2::submit_buffer(std::unique_ptr<BYTE[]> audioData, DWORD audio
BOOL sound_xaudio2::submit_next_queued()
{
- if (!m_queue.empty())
- {
- // Get a reference to the buffer
- auto buf = &m_queue.front();
+ if (!m_queue.empty())
+ {
+ // Get a reference to the buffer
+ auto buf = &m_queue.front();
- // submit the buffer data
- submit_buffer(std::move(buf->AudioData), buf->AudioSize);
+ // submit the buffer data
+ submit_buffer(std::move(buf->AudioData), buf->AudioSize);
- // Remove it from the queue
- assert(buf->AudioSize > 0);
- m_queue.pop();
+ // Remove it from the queue
+ assert(buf->AudioSize > 0);
+ m_queue.pop();
- return !m_queue.empty();
- }
+ return !m_queue.empty();
+ }
- // queue was already empty
- return FALSE;
+ // queue was already empty
+ return FALSE;
}
//============================================================
@@ -695,32 +695,32 @@ BOOL sound_xaudio2::submit_next_queued()
// Queues the current buffer, and gets a new write buffer
void sound_xaudio2::roll_buffer()
{
- // Don't queue a buffer if it is empty
- if (m_writepos == 0)
- return;
-
- // Queue the current buffer
- xaudio2_buffer buf;
- buf.AudioData = std::move(m_buffer);
- buf.AudioSize = m_writepos;
- m_queue.push(std::move(buf));
-
- // Get a new buffer
- m_buffer = std::unique_ptr<BYTE[]>(m_buffer_pool->next());
- m_writepos = 0;
-
- // We only want to keep a maximum number of buffers at any given time
- // so remove any from queue greater than MAX_QUEUED_BUFFERS
- if (m_queue.size() > m_buffer_count)
- {
- xaudio2_buffer *next_buffer = &m_queue.front();
-
- // return the oldest buffer to the pool, and remove it from queue
- m_buffer_pool->return_to_pool(next_buffer->AudioData.release());
- m_queue.pop();
-
- m_overflows++;
- }
+ // Don't queue a buffer if it is empty
+ if (m_writepos == 0)
+ return;
+
+ // Queue the current buffer
+ xaudio2_buffer buf;
+ buf.AudioData = std::move(m_buffer);
+ buf.AudioSize = m_writepos;
+ m_queue.push(std::move(buf));
+
+ // Get a new buffer
+ m_buffer = std::unique_ptr<BYTE[]>(m_buffer_pool->next());
+ m_writepos = 0;
+
+ // We only want to keep a maximum number of buffers at any given time
+ // so remove any from queue greater than MAX_QUEUED_BUFFERS
+ if (m_queue.size() > m_buffer_count)
+ {
+ xaudio2_buffer *next_buffer = &m_queue.front();
+
+ // return the oldest buffer to the pool, and remove it from queue
+ m_buffer_pool->return_to_pool(next_buffer->AudioData.release());
+ m_queue.pop();
+
+ m_overflows++;
+ }
}
@@ -728,4 +728,4 @@ void sound_xaudio2::roll_buffer()
MODULE_NOT_SUPPORTED(sound_xaudio2, OSD_SOUND_PROVIDER, "xaudio2")
#endif
-MODULE_DEFINITION(SOUND_XAUDIO2, sound_xaudio2) \ No newline at end of file
+MODULE_DEFINITION(SOUND_XAUDIO2, sound_xaudio2)