diff options
Diffstat (limited to 'src/osd/modules/sound/direct_sound.cpp')
-rw-r--r-- | src/osd/modules/sound/direct_sound.cpp | 373 |
1 files changed, 184 insertions, 189 deletions
diff --git a/src/osd/modules/sound/direct_sound.cpp b/src/osd/modules/sound/direct_sound.cpp index fcdc13e07df..5f245bd6359 100644 --- a/src/osd/modules/sound/direct_sound.cpp +++ b/src/osd/modules/sound/direct_sound.cpp @@ -11,15 +11,6 @@ #if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32) -// standard windows headers -#include <windows.h> -#include <mmsystem.h> - -// undef WINNT for dsound.h to prevent duplicate definition -#undef WINNT -#include <dsound.h> -#undef interface - // MAME headers #include "emu.h" #include "osdepend.h" @@ -33,214 +24,217 @@ #include "winmain.h" #include "window.h" #endif + #include <utility> +// standard windows headers +#include <dsound.h> +#include <mmsystem.h> +#include <windows.h> +#include <wrl/client.h> + + //============================================================ // DEBUGGING //============================================================ #define LOG_SOUND 0 -#define LOG(x) do { if (LOG_SOUND) osd_printf_verbose x; } while(0) +#define LOG(...) do { if (LOG_SOUND) osd_printf_verbose(__VA_ARGS__); } while(0) -class sound_direct_sound : public osd_module, public sound_module +namespace { + +class buffer_base { public: + explicit operator bool() const { return bool(m_buffer); } - sound_direct_sound() : - osd_module(OSD_SOUND_PROVIDER, "dsound"), - sound_module(), - m_dsound(nullptr), - m_bytes_per_sample(0), - m_primary_buffer(), - m_stream_buffer(), - m_stream_buffer_in(0), - m_buffer_underflows(0), - m_buffer_overflows(0) + unsigned long release() { return m_buffer.Reset(); } + +protected: + Microsoft::WRL::ComPtr<IDirectSoundBuffer> m_buffer; +}; + + +class primary_buffer : public buffer_base +{ +public: + HRESULT create(LPDIRECTSOUND dsound) { + assert(!m_buffer); + DSBUFFERDESC desc; + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2; + desc.lpwfxFormat = nullptr; + return dsound->CreateSoundBuffer(&desc, &m_buffer, nullptr); } - virtual ~sound_direct_sound() { } - - virtual int init(osd_options const &options) override; - virtual void exit() override; - // sound_module - virtual void update_audio_stream(bool is_throttled, int16_t const *buffer, int samples_this_frame) override; - virtual void set_mastervolume(int attenuation) override; + HRESULT get_format(WAVEFORMATEX &format) const + { + assert(m_buffer); + return m_buffer->GetFormat(&format, sizeof(format), nullptr); + } -private: - class buffer + HRESULT set_format(WAVEFORMATEX const &format) const { - public: - buffer() : m_buffer(nullptr) { } - ~buffer() { release(); } + assert(m_buffer); + return m_buffer->SetFormat(&format); + } +}; - ULONG release() - { - ULONG const result = m_buffer ? m_buffer->Release() : 0; - m_buffer = nullptr; - return result; - } - operator bool() const { return m_buffer; } +class stream_buffer : public buffer_base +{ +public: + HRESULT create(LPDIRECTSOUND dsound, DWORD size, WAVEFORMATEX &format) + { + assert(!m_buffer); + DSBUFFERDESC desc; + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; + desc.dwBufferBytes = size; + desc.lpwfxFormat = &format; + m_size = size; + return dsound->CreateSoundBuffer(&desc, &m_buffer, nullptr); + } - protected: - LPDIRECTSOUNDBUFFER m_buffer; - }; + HRESULT play_looping() const + { + assert(m_buffer); + return m_buffer->Play(0, 0, DSBPLAY_LOOPING); + } + HRESULT stop() const + { + assert(m_buffer); + return m_buffer->Stop(); + } + HRESULT set_volume(LONG volume) const + { + assert(m_buffer); + return m_buffer->SetVolume(volume); + } + HRESULT set_min_volume() { return set_volume(DSBVOLUME_MIN); } - class primary_buffer : public buffer + HRESULT get_current_positions(DWORD &play_pos, DWORD &write_pos) const { - public: - HRESULT create(LPDIRECTSOUND dsound) - { - assert(!m_buffer); - DSBUFFERDESC desc; - memset(&desc, 0, sizeof(desc)); - desc.dwSize = sizeof(desc); - desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2; - desc.lpwfxFormat = nullptr; - return dsound->CreateSoundBuffer(&desc, &m_buffer, nullptr); - } + assert(m_buffer); + return m_buffer->GetCurrentPosition(&play_pos, &write_pos); + } + HRESULT copy_data(DWORD cursor, DWORD bytes, void const *data) + { + HRESULT result = lock(cursor, bytes); + if (DS_OK != result) + return result; - HRESULT get_format(WAVEFORMATEX &format) const - { - assert(m_buffer); - return m_buffer->GetFormat(&format, sizeof(format), nullptr); - } - HRESULT set_format(WAVEFORMATEX const &format) const + assert(m_bytes1); + assert((m_locked1 + m_locked2) >= bytes); + memcpy(m_bytes1, data, std::min(m_locked1, bytes)); + if (m_locked1 < bytes) { - assert(m_buffer); - return m_buffer->SetFormat(&format); + assert(m_bytes2); + memcpy(m_bytes2, (uint8_t const *)data + m_locked1, bytes - m_locked1); } - }; - class stream_buffer : public buffer + unlock(); + return DS_OK; + } + HRESULT clear() { - public: - stream_buffer() : m_size(0), m_bytes1(nullptr), m_bytes2(nullptr), m_locked1(0), m_locked2(0) { } + HRESULT result = lock_all(); + if (DS_OK != result) + return result; - HRESULT create(LPDIRECTSOUND dsound, DWORD size, WAVEFORMATEX &format) - { - assert(!m_buffer); - DSBUFFERDESC desc; - memset(&desc, 0, sizeof(desc)); - desc.dwSize = sizeof(desc); - desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; - desc.dwBufferBytes = size; - desc.lpwfxFormat = &format; - m_size = size; - return dsound->CreateSoundBuffer(&desc, &m_buffer, nullptr); - } + assert(m_bytes1); + assert(!m_bytes2); + assert(m_size == m_locked1); + assert(0U == m_locked2); + memset(m_bytes1, 0, m_locked1); - HRESULT play_looping() const - { - assert(m_buffer); - return m_buffer->Play(0, 0, DSBPLAY_LOOPING); - } - HRESULT stop() const - { - assert(m_buffer); - return m_buffer->Stop(); - } - HRESULT set_volume(LONG volume) const - { - assert(m_buffer); - return m_buffer->SetVolume(volume); - } - HRESULT set_min_volume() { return set_volume(DSBVOLUME_MIN); } + unlock(); + return DS_OK; + } - HRESULT get_current_positions(DWORD &play_pos, DWORD &write_pos) const - { - assert(m_buffer); - return m_buffer->GetCurrentPosition(&play_pos, &write_pos); - } - HRESULT copy_data(DWORD cursor, DWORD bytes, void const *data) - { - HRESULT result = lock(cursor, bytes); - if (DS_OK != result) - return result; - - assert(m_bytes1); - assert((m_locked1 + m_locked2) >= bytes); - memcpy(m_bytes1, data, std::min(m_locked1, bytes)); - if (m_locked1 < bytes) - { - assert(m_bytes2); - memcpy(m_bytes2, (uint8_t const *)data + m_locked1, bytes - m_locked1); - } - - unlock(); - return DS_OK; - } - HRESULT clear() - { - HRESULT result = lock_all(); - if (DS_OK != result) - return result; - - assert(m_bytes1); - assert(!m_bytes2); - assert(m_size == m_locked1); - assert(0U == m_locked2); - memset(m_bytes1, 0, m_locked1); - - unlock(); - return DS_OK; - } + DWORD size() const { return m_size; } - DWORD size() const { return m_size; } +private: + HRESULT lock(DWORD cursor, DWORD bytes) + { + assert(cursor < m_size); + assert(bytes <= m_size); + assert(m_buffer); + assert(!m_bytes1); + return m_buffer->Lock( + cursor, bytes, + &m_bytes1, + &m_locked1, + &m_bytes2, + &m_locked2, + 0); + } + HRESULT lock_all() { return lock(0, m_size); } + HRESULT unlock() + { + assert(m_buffer); + assert(m_bytes1); + HRESULT const result = m_buffer->Unlock( + m_bytes1, + m_locked1, + m_bytes2, + m_locked2); + m_bytes1 = m_bytes2 = nullptr; + m_locked1 = m_locked2 = 0; + return result; + } - protected: - HRESULT lock(DWORD cursor, DWORD bytes) - { - assert(cursor < m_size); - assert(bytes <= m_size); - assert(m_buffer); - assert(!m_bytes1); - return m_buffer->Lock( - cursor, bytes, - &m_bytes1, - &m_locked1, - &m_bytes2, - &m_locked2, - 0); - } - HRESULT lock_all() { return lock(0, m_size); } - HRESULT unlock() - { - assert(m_buffer); - assert(m_bytes1); - HRESULT const result = m_buffer->Unlock( - m_bytes1, - m_locked1, - m_bytes2, - m_locked2); - m_bytes1 = m_bytes2 = nullptr; - m_locked1 = m_locked2 = 0; - return result; - } + DWORD m_size = 0; + void *m_bytes1 = nullptr, *m_bytes2 = nullptr; + DWORD m_locked1 = 0, m_locked2 = 0; +}; - DWORD m_size; - void *m_bytes1, *m_bytes2; - DWORD m_locked1, m_locked2; - }; +class sound_direct_sound : public osd_module, public sound_module +{ +public: + + sound_direct_sound() : + osd_module(OSD_SOUND_PROVIDER, "dsound"), + sound_module(), + m_bytes_per_sample(0), + m_primary_buffer(), + m_stream_buffer(), + m_stream_buffer_in(0), + m_buffer_underflows(0), + m_buffer_overflows(0) + { + } + virtual ~sound_direct_sound() { } + + virtual int init(osd_options const &options) override; + virtual void exit() override; + + // sound_module + virtual void update_audio_stream(bool is_throttled, int16_t const *buffer, int samples_this_frame) override; + virtual void set_mastervolume(int attenuation) override; + +private: HRESULT dsound_init(); void dsound_kill(); HRESULT create_buffers(DWORD size, WAVEFORMATEX &format); void destroy_buffers(); // DirectSound objects - LPDIRECTSOUND m_dsound; + Microsoft::WRL::ComPtr<IDirectSound> m_dsound; // descriptors and formats - uint32_t m_bytes_per_sample; + uint32_t m_bytes_per_sample; // sound buffers primary_buffer m_primary_buffer; stream_buffer m_stream_buffer; - uint32_t m_stream_buffer_in; + uint32_t m_stream_buffer_in; // buffer over/underflow counts unsigned m_buffer_underflows; @@ -281,7 +275,7 @@ void sound_direct_sound::exit() m_buffer_underflows); } - LOG(("Sound buffer: overflows=%u underflows=%u\n", m_buffer_overflows, m_buffer_underflows)); + LOG("Sound buffer: overflows=%u underflows=%u\n", m_buffer_overflows, m_buffer_underflows); } @@ -385,7 +379,7 @@ HRESULT sound_direct_sound::dsound_init() result = DirectSoundCreate(nullptr, &m_dsound, nullptr); if (result != DS_OK) { - osd_printf_error("Error creating DirectSound: %08x\n", (unsigned)result); + osd_printf_error("Error creating DirectSound: %08x\n", result); goto error; } @@ -395,7 +389,7 @@ HRESULT sound_direct_sound::dsound_init() result = m_dsound->GetCaps(&dsound_caps); if (result != DS_OK) { - osd_printf_error("Error getting DirectSound capabilities: %08x\n", (unsigned)result); + osd_printf_error("Error getting DirectSound capabilities: %08x\n", result); goto error; } @@ -413,7 +407,7 @@ HRESULT sound_direct_sound::dsound_init() } if (result != DS_OK) { - osd_printf_error("Error setting DirectSound cooperative level: %08x\n", (unsigned)result); + osd_printf_error("Error setting DirectSound cooperative level: %08x\n", result); goto error; } @@ -432,7 +426,7 @@ HRESULT sound_direct_sound::dsound_init() DWORD stream_buffer_size = stream_format.nSamplesPerSec * stream_format.nBlockAlign * audio_latency / 10; stream_buffer_size = std::max(DWORD(1024), (stream_buffer_size / 1024) * 1024); - LOG(("stream_buffer_size = %u\n", (unsigned)stream_buffer_size)); + LOG("stream_buffer_size = %u\n", stream_buffer_size); // create the buffers m_bytes_per_sample = stream_format.nBlockAlign; @@ -446,7 +440,7 @@ HRESULT sound_direct_sound::dsound_init() result = m_stream_buffer.play_looping(); if (result != DS_OK) { - osd_printf_error("Error playing: %08x\n", (uint32_t)result); + osd_printf_error("Error playing: %08x\n", result); goto error; } return DS_OK; @@ -466,9 +460,7 @@ error: void sound_direct_sound::dsound_kill() { // release the object - if (m_dsound) - m_dsound->Release(); - m_dsound = nullptr; + m_dsound.Reset(); } @@ -484,10 +476,10 @@ HRESULT sound_direct_sound::create_buffers(DWORD size, WAVEFORMATEX &format) HRESULT result; // create the primary buffer - result = m_primary_buffer.create(m_dsound); + result = m_primary_buffer.create(m_dsound.Get()); if (result != DS_OK) { - osd_printf_error("Error creating primary DirectSound buffer: %08x\n", (unsigned)result); + osd_printf_error("Error creating primary DirectSound buffer: %08x\n", result); goto error; } @@ -495,7 +487,7 @@ HRESULT sound_direct_sound::create_buffers(DWORD size, WAVEFORMATEX &format) result = m_primary_buffer.set_format(format); if (result != DS_OK) { - osd_printf_error("Error setting primary DirectSound buffer format: %08x\n", (unsigned)result); + osd_printf_error("Error setting primary DirectSound buffer format: %08x\n", result); goto error; } @@ -504,20 +496,20 @@ HRESULT sound_direct_sound::create_buffers(DWORD size, WAVEFORMATEX &format) result = m_primary_buffer.get_format(primary_format); if (result != DS_OK) { - osd_printf_error("Error getting primary DirectSound buffer format: %08x\n", (unsigned)result); + osd_printf_error("Error getting primary DirectSound buffer format: %08x\n", result); goto error; } osd_printf_verbose( "DirectSound: Primary buffer: %d Hz, %d bits, %d channels\n", - (int)primary_format.nSamplesPerSec, - (int)primary_format.wBitsPerSample, - (int)primary_format.nChannels); + primary_format.nSamplesPerSec, + primary_format.wBitsPerSample, + primary_format.nChannels); // create the stream buffer - result = m_stream_buffer.create(m_dsound, size, format); + result = m_stream_buffer.create(m_dsound.Get(), size, format); if (result != DS_OK) { - osd_printf_error("Error creating DirectSound stream buffer: %08x\n", (unsigned)result); + osd_printf_error("Error creating DirectSound stream buffer: %08x\n", result); goto error; } @@ -525,7 +517,7 @@ HRESULT sound_direct_sound::create_buffers(DWORD size, WAVEFORMATEX &format) result = m_stream_buffer.clear(); if (result != DS_OK) { - osd_printf_error("Error locking DirectSound stream buffer: %08x\n", (unsigned)result); + osd_printf_error("Error locking DirectSound stream buffer: %08x\n", result); goto error; } @@ -555,8 +547,11 @@ void sound_direct_sound::destroy_buffers() m_primary_buffer.release(); } + #else // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32) MODULE_NOT_SUPPORTED(sound_direct_sound, OSD_SOUND_PROVIDER, "dsound") #endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32) +} // anonymous namespace + MODULE_DEFINITION(SOUND_DSOUND, sound_direct_sound) |