diff options
Diffstat (limited to 'src/osd/modules/sound/xaudio2_sound.cpp')
-rw-r--r-- | src/osd/modules/sound/xaudio2_sound.cpp | 180 |
1 files changed, 84 insertions, 96 deletions
diff --git a/src/osd/modules/sound/xaudio2_sound.cpp b/src/osd/modules/sound/xaudio2_sound.cpp index 1d9e1036f9a..a865f2527fe 100644 --- a/src/osd/modules/sound/xaudio2_sound.cpp +++ b/src/osd/modules/sound/xaudio2_sound.cpp @@ -7,9 +7,24 @@ //==================================================================== #include "sound_module.h" + #include "modules/osdmodule.h" -#if defined(OSD_WINDOWS) || defined(OSD_UWP) +#if defined(OSD_WINDOWS) | defined(SDLMAME_WIN32) + +// OSD headers +#include "modules/lib/osdlib.h" +#include "modules/lib/osdobj_common.h" +#include "osdcore.h" +#include "osdepend.h" +#include "windows/winutil.h" + +// stdlib includes +#include <algorithm> +#include <chrono> +#include <mutex> +#include <queue> +#include <thread> // standard windows headers #include <windows.h> @@ -19,21 +34,10 @@ // XAudio2 include #include <xaudio2.h> -#undef interface -// stdlib includes -#include <mutex> -#include <thread> -#include <queue> -#include <chrono> +namespace osd { -// MAME headers -#include "emu.h" -#include "osdepend.h" - -#include "winutil.h" - -#include "modules/lib/osdlib.h" +namespace { //============================================================ // Constants @@ -180,29 +184,6 @@ public: // The main class for the XAudio2 sound module implementation class sound_xaudio2 : public osd_module, public sound_module, public IXAudio2VoiceCallback { -private: - Microsoft::WRL::ComPtr<IXAudio2> 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; - std::mutex 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; - uint32_t m_overflows; - uint32_t m_underflows; - BOOL m_in_underflow; - BOOL m_initialized; - OSD_DYNAMIC_API(xaudio2, "XAudio2_9.dll", "XAudio2_8.dll"); - OSD_DYNAMIC_API_FN(xaudio2, HRESULT, WINAPI, XAudio2Create, IXAudio2 **, uint32_t, XAUDIO2_PROCESSOR); - public: sound_xaudio2() : osd_module(OSD_SOUND_PROVIDER, "xaudio2"), @@ -210,6 +191,8 @@ public: m_xAudio2(nullptr), m_masterVoice(nullptr), m_sourceVoice(nullptr), + m_sample_rate(0), + m_audio_latency(0), m_sample_bytes(0), m_buffer(nullptr), m_buffer_size(0), @@ -226,26 +209,23 @@ public: { } - virtual ~sound_xaudio2() { } - bool probe() override; - int init(osd_options const &options) override; + int init(osd_interface &osd, osd_options const &options) override; void exit() override; // sound_module - void update_audio_stream(bool is_throttled, int16_t const *buffer, int samples_this_frame) override; - void set_mastervolume(int attenuation) override; + void stream_sink_update(uint32_t, int16_t const *buffer, int samples_this_frame) override; +private: // Xaudio callbacks - void STDAPICALLTYPE OnVoiceProcessingPassStart(uint32_t bytes_required) override; - void STDAPICALLTYPE OnVoiceProcessingPassEnd() override {} - void STDAPICALLTYPE OnStreamEnd() override {} - void STDAPICALLTYPE OnBufferStart(void* pBufferContext) override {} - void STDAPICALLTYPE OnLoopEnd(void* pBufferContext) override {} - void STDAPICALLTYPE OnVoiceError(void* pBufferContext, HRESULT error) override {} - void STDAPICALLTYPE OnBufferEnd(void *pBufferContext) override; + void STDAPICALLTYPE OnVoiceProcessingPassStart(uint32_t bytes_required) noexcept override; + void STDAPICALLTYPE OnVoiceProcessingPassEnd() noexcept override {} + void STDAPICALLTYPE OnStreamEnd() noexcept override {} + void STDAPICALLTYPE OnBufferStart(void* pBufferContext) noexcept override {} + void STDAPICALLTYPE OnLoopEnd(void* pBufferContext) noexcept override {} + void STDAPICALLTYPE OnVoiceError(void* pBufferContext, HRESULT error) noexcept override {} + void STDAPICALLTYPE OnBufferEnd(void *pBufferContext) noexcept override; -private: void create_buffers(const WAVEFORMATEX &format); HRESULT create_voices(const WAVEFORMATEX &format); void process_audio(); @@ -253,6 +233,31 @@ private: void submit_needed(); void roll_buffer(); BOOL submit_next_queued(); + + Microsoft::WRL::ComPtr<IXAudio2> m_xAudio2; + mastering_voice_ptr m_masterVoice; + src_voice_ptr m_sourceVoice; + int m_sample_rate; + int m_audio_latency; + DWORD m_sample_bytes; + std::unique_ptr<BYTE[]> m_buffer; + DWORD m_buffer_size; + DWORD m_buffer_count; + DWORD m_writepos; + std::mutex 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; + uint32_t m_overflows; + uint32_t m_underflows; + BOOL m_in_underflow; + BOOL m_initialized; + + OSD_DYNAMIC_API(xaudio2, "XAudio2_9.dll", "XAudio2_8.dll"); + OSD_DYNAMIC_API_FN(xaudio2, HRESULT, WINAPI, XAudio2Create, IXAudio2 **, uint32_t, XAUDIO2_PROCESSOR); }; //============================================================ @@ -268,14 +273,9 @@ bool sound_xaudio2::probe() // init //============================================================ -int sound_xaudio2::init(osd_options const &options) +int sound_xaudio2::init(osd_interface &osd, osd_options const &options) { - HRESULT result; - WAVEFORMATEX format = {0}; - auto init_start = std::chrono::system_clock::now(); - std::chrono::milliseconds init_time; - - CoInitializeEx(nullptr, COINIT_MULTITHREADED); + auto const init_start = std::chrono::system_clock::now(); // Make sure our XAudio2Create entrypoint is bound if (!OSD_DYNAMIC_API_TEST(XAudio2Create)) @@ -284,6 +284,13 @@ int sound_xaudio2::init(osd_options const &options) return 1; } + HRESULT result; + std::chrono::milliseconds init_time; + WAVEFORMATEX format = { 0 }; + + m_sample_rate = options.sample_rate(); + m_audio_latency = options.audio_latency(); + // Create the IXAudio2 object HR_GOERR(OSD_DYNAMIC_CALL(XAudio2Create, m_xAudio2.GetAddressOf(), 0, XAUDIO2_DEFAULT_PROCESSOR)); @@ -291,7 +298,7 @@ int sound_xaudio2::init(osd_options const &options) format.wBitsPerSample = 16; format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = 2; - format.nSamplesPerSec = sample_rate(); + format.nSamplesPerSec = m_sample_rate; format.nBlockAlign = format.wBitsPerSample * format.nChannels / 8; format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; @@ -310,10 +317,10 @@ int sound_xaudio2::init(osd_options const &options) HR_GOERR(m_sourceVoice->Start()); // Start the thread listening - m_audioThread = std::thread([](sound_xaudio2* self) { self->process_audio(); }, this); + m_audioThread = std::thread([] (sound_xaudio2 *self) { self->process_audio(); }, this); init_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - init_start); - osd_printf_verbose("Sound: XAudio2 initialized. %d ms.\n", static_cast<int>(init_time.count())); + osd_printf_verbose("Sound: XAudio2 initialized. %d ms.\n", init_time.count()); m_initialized = TRUE; return 0; @@ -368,15 +375,15 @@ void sound_xaudio2::exit() } //============================================================ -// update_audio_stream +// stream_sink_update //============================================================ -void sound_xaudio2::update_audio_stream( - bool is_throttled, +void sound_xaudio2::stream_sink_update( + uint32_t, int16_t const *buffer, int samples_this_frame) { - if (!m_initialized || sample_rate() == 0 || !m_buffer) + if (!m_initialized || m_sample_rate == 0 || !m_buffer) return; uint32_t const bytes_this_frame = samples_this_frame * m_sample_bytes; @@ -406,37 +413,11 @@ void sound_xaudio2::update_audio_stream( } //============================================================ -// set_mastervolume -//============================================================ - -void sound_xaudio2::set_mastervolume(int attenuation) -{ - if (!m_initialized) - return; - - assert(m_sourceVoice); - - HRESULT result; - - // clamp the attenuation to 0-32 range - attenuation = std::max(std::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)); -} - -//============================================================ // IXAudio2VoiceCallback::OnBufferEnd //============================================================ // The XAudio2 voice callback triggered when a buffer finishes playing -void sound_xaudio2::OnBufferEnd(void *pBufferContext) +void sound_xaudio2::OnBufferEnd(void *pBufferContext) noexcept { BYTE* completed_buffer = static_cast<BYTE*>(pBufferContext); if (completed_buffer != nullptr) @@ -453,7 +434,7 @@ void sound_xaudio2::OnBufferEnd(void *pBufferContext) //============================================================ // The XAudio2 voice callback triggered on every pass -void sound_xaudio2::OnVoiceProcessingPassStart(uint32_t bytes_required) +void sound_xaudio2::OnVoiceProcessingPassStart(uint32_t bytes_required) noexcept { if (bytes_required == 0) { @@ -479,7 +460,8 @@ 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; + int audio_latency = std::max(m_audio_latency, 1); + float audio_latency_in_seconds = audio_latency / 10.0f; uint32_t format_bytes_per_second = format.nSamplesPerSec * format.nBlockAlign; uint32_t total_buffer_size = format_bytes_per_second * audio_latency_in_seconds * RESAMPLE_TOLERANCE; @@ -526,7 +508,7 @@ HRESULT sound_xaudio2::create_voices(const WAVEFORMATEX &format) m_xAudio2->CreateMasteringVoice( &temp_master_voice, format.nChannels, - sample_rate())); + m_sample_rate)); m_masterVoice = mastering_voice_ptr(temp_master_voice); @@ -693,9 +675,15 @@ void sound_xaudio2::roll_buffer() } } +} // anonymous namespace + +} // namespace osd + #else -MODULE_NOT_SUPPORTED(sound_xaudio2, OSD_SOUND_PROVIDER, "xaudio2") + +namespace osd { namespace { MODULE_NOT_SUPPORTED(sound_xaudio2, OSD_SOUND_PROVIDER, "xaudio2") } } + #endif -MODULE_DEFINITION(SOUND_XAUDIO2, sound_xaudio2) +MODULE_DEFINITION(SOUND_XAUDIO2, osd::sound_xaudio2) |