diff options
Diffstat (limited to 'src/osd/modules/sound')
-rw-r--r-- | src/osd/modules/sound/direct_sound.cpp | 9 | ||||
-rw-r--r-- | src/osd/modules/sound/js_sound.cpp | 6 | ||||
-rw-r--r-- | src/osd/modules/sound/js_sound.js | 213 | ||||
-rw-r--r-- | src/osd/modules/sound/sdl_sound.cpp | 4 | ||||
-rw-r--r-- | src/osd/modules/sound/xaudio2_sound.cpp | 40 |
5 files changed, 221 insertions, 51 deletions
diff --git a/src/osd/modules/sound/direct_sound.cpp b/src/osd/modules/sound/direct_sound.cpp index 78996093e77..0ec810578a3 100644 --- a/src/osd/modules/sound/direct_sound.cpp +++ b/src/osd/modules/sound/direct_sound.cpp @@ -28,11 +28,7 @@ #ifdef SDLMAME_WIN32 #include "../../sdl/osdsdl.h" -#if (SDLMAME_SDL2) #include <SDL2/SDL_syswm.h> -#else -#include <SDL/SDL_syswm.h> -#endif #include "../../sdl/window.h" #else #include "winmain.h" @@ -408,13 +404,8 @@ HRESULT sound_direct_sound::dsound_init() #ifdef SDLMAME_WIN32 SDL_SysWMinfo wminfo; SDL_VERSION(&wminfo.version); -#if SDLMAME_SDL2 SDL_GetWindowWMInfo(sdl_window_list->sdl_window(), &wminfo); HWND const window = wminfo.info.win.window; -#else // SDLMAME_SDL2 - SDL_GetWMInfo(&wminfo); - HWND const window = wminfo.window; -#endif // SDLMAME_SDL2 #else // SDLMAME_WIN32 HWND const window = win_window_list->m_hwnd; #endif // SDLMAME_WIN32 diff --git a/src/osd/modules/sound/js_sound.cpp b/src/osd/modules/sound/js_sound.cpp index bd95c79dd2e..581de205d7b 100644 --- a/src/osd/modules/sound/js_sound.cpp +++ b/src/osd/modules/sound/js_sound.cpp @@ -6,7 +6,7 @@ Shim for native JavaScript sound interface implementations (Emscripten only). -*******************************************************************c********/ +****************************************************************************/ #include "sound_module.h" #include "modules/osdmodule.h" @@ -34,14 +34,14 @@ public: { EM_ASM_ARGS({ // Forward audio stream update on to JS backend implementation. - jsmess_update_audio_stream($0, $1); + jsmame_update_audio_stream($0, $1); }, (unsigned int)buffer, samples_this_frame); } virtual void set_mastervolume(int attenuation) { EM_ASM_ARGS({ // Forward volume update on to JS backend implementation. - jsmess_set_mastervolume($0); + jsmame_set_mastervolume($0); }, attenuation); } diff --git a/src/osd/modules/sound/js_sound.js b/src/osd/modules/sound/js_sound.js new file mode 100644 index 00000000000..b06cbb44365 --- /dev/null +++ b/src/osd/modules/sound/js_sound.js @@ -0,0 +1,213 @@ +// license:BSD-3-Clause +// copyright-holders:Grant Galitz, Katelyn Gadd +/*************************************************************************** + + JSMAME web audio backend v0.3 + + Original by katelyn gadd - kg at luminance dot org ; @antumbral on twitter + Substantial changes by taisel + +***************************************************************************/ + +var jsmame_web_audio = (function () { + +var context = null; +var gain_node = null; +var eventNode = null; +var sampleScale = 32766; +var inputBuffer = new Float32Array(44100); +var bufferSize = 44100; +var start = 0; +var rear = 0; +var watchDogDateLast = null; +var watchDogTimerEvent = null; + +function lazy_init () { + //Make + if (context) { + //Return if already created: + return; + } + if (typeof AudioContext != "undefined") { + //Standard context creation: + context = new AudioContext(); + } + else if (typeof webkitAudioContext != "undefined") { + //Older webkit context creation: + context = new webkitAudioContext(); + } + else { + //API not found! + return; + } + //Generate a volume control node: + gain_node = context.createGain(); + //Set initial volume to 1: + gain_node.gain.value = 1.0; + //Connect volume node to output: + gain_node.connect(context.destination); + //Initialize the streaming event: + init_event(); +}; + +function init_event() { + //Generate a streaming node point: + if (typeof context.createScriptProcessor == "function") { + //Current standard compliant way: + eventNode = context.createScriptProcessor(4096, 0, 2); + } + else { + //Deprecated way: + eventNode = context.createJavaScriptNode(4096, 0, 2); + } + //Make our tick function the audio callback function: + eventNode.onaudioprocess = tick; + //Connect stream to volume control node: + eventNode.connect(gain_node); + //WORKAROUND FOR FIREFOX BUG: + initializeWatchDogForFirefoxBug(); +}; + +function initializeWatchDogForFirefoxBug() { + //TODO: decide if we want to user agent sniff firefox here, + //since Google Chrome doesn't need this: + watchDogDateLast = (new Date()).getTime(); + if (watchDogTimerEvent === null) { + watchDogTimerEvent = setInterval(function () { + var timeDiff = (new Date()).getTime() - watchDogDateLast; + if (timeDiff > 500) { + disconnect_old_event(); + init_event(); + } + }, 500); + } +}; + +function disconnect_old_event() { + //Disconnect from audio graph: + eventNode.disconnect(); + //IIRC there was a firefox bug that did not GC this event when nulling the node itself: + eventNode.onaudioprocess = null; + //Null the glitched/unused node: + eventNode = null; +}; + +function set_mastervolume ( + // even though it's 'attenuation' the value is negative, so... + attenuation_in_decibels +) { + lazy_init(); + if (!context) return; + + // http://stackoverflow.com/questions/22604500/web-audio-api-working-with-decibels + // seemingly incorrect/broken. figures. welcome to Web Audio + // var gain_web_audio = 1.0 - Math.pow(10, 10 / attenuation_in_decibels); + + // HACK: Max attenuation in JSMESS appears to be 32. + // Hit ' then left/right arrow to test. + // FIXME: This is linear instead of log10 scale. + var gain_web_audio = 1.0 + (+attenuation_in_decibels / +32); + if (gain_web_audio < +0) + gain_web_audio = +0; + else if (gain_web_audio > +1) + gain_web_audio = +1; + + gain_node.gain.value = gain_web_audio; +}; + +function update_audio_stream ( + pBuffer, // pointer into emscripten heap. int16 samples + samples_this_frame // int. number of samples at pBuffer address. +) { + lazy_init(); + if (!context) return; + + for ( + var i = 0, + l = samples_this_frame | 0; + i < l; + i++ + ) { + var offset = + // divide by sizeof(INT16) since pBuffer is offset + // in bytes + ((pBuffer / 2) | 0) + + ((i * 2) | 0); + + var left_sample = HEAP16[offset]; + var right_sample = HEAP16[(offset + 1) | 0]; + + // normalize from signed int16 to signed float + var left_sample_float = left_sample / sampleScale; + var right_sample_float = right_sample / sampleScale; + + inputBuffer[rear++] = left_sample_float; + inputBuffer[rear++] = right_sample_float; + if (rear == bufferSize) { + rear = 0; + } + if (start == rear) { + start += 2; + if (start == bufferSize) { + start = 0; + } + } + } +}; +function tick (event) { + //Find all output channels: + for (var bufferCount = 0, buffers = []; bufferCount < 2; ++bufferCount) { + buffers[bufferCount] = event.outputBuffer.getChannelData(bufferCount); + } + //Copy samples from the input buffer to the Web Audio API: + for (var index = 0; index < 4096 && start != rear; ++index) { + buffers[0][index] = inputBuffer[start++]; + buffers[1][index] = inputBuffer[start++]; + if (start == bufferSize) { + start = 0; + } + } + //Pad with silence if we're underrunning: + while (index < 4096) { + buffers[0][index] = 0; + buffers[1][index++] = 0; + } + //Deep inside the bowels of vendors bugs, + //we're using watchdog for a firefox bug, + //where the user agent decides to stop firing events + //if the user agent lags out due to system load. + //Don't even ask.... + watchDogDateLast = (new Date()).getTime(); +} + +function get_context() { + return context; +}; + +function sample_count() { + //TODO get someone to call this from the emulator, + //so the emulator can do proper audio buffering by + //knowing how many samples are left: + if (!context) { + //Use impossible value as an error code: + return -1; + } + var count = rear - start; + if (start > rear) { + count += bufferSize; + } + return count; +} + +return { + set_mastervolume: set_mastervolume, + update_audio_stream: update_audio_stream, + get_context: get_context, + sample_count: sample_count +}; + +})(); + +window.jsmame_set_mastervolume = jsmame_web_audio.set_mastervolume; +window.jsmame_update_audio_stream = jsmame_web_audio.update_audio_stream; +window.jsmame_sample_count = jsmame_web_audio.sample_count; diff --git a/src/osd/modules/sound/sdl_sound.cpp b/src/osd/modules/sound/sdl_sound.cpp index de8d57af11c..c1e3e3dff2b 100644 --- a/src/osd/modules/sound/sdl_sound.cpp +++ b/src/osd/modules/sound/sdl_sound.cpp @@ -421,11 +421,7 @@ int sound_sdl::init(const osd_options &options) } osd_printf_verbose("Audio: Start initialization\n"); - #if (SDLMAME_SDL2) strncpy(audio_driver, SDL_GetCurrentAudioDriver(), sizeof(audio_driver)); - #else - SDL_AudioDriverName(audio_driver, sizeof(audio_driver)); - #endif osd_printf_verbose("Audio: Driver is %s\n", audio_driver); sdl_xfer_samples = SDL_XFER_SAMPLES; diff --git a/src/osd/modules/sound/xaudio2_sound.cpp b/src/osd/modules/sound/xaudio2_sound.cpp index 7df854c0364..9dc3d0461be 100644 --- a/src/osd/modules/sound/xaudio2_sound.cpp +++ b/src/osd/modules/sound/xaudio2_sound.cpp @@ -14,6 +14,7 @@ // standard windows headers #define WIN32_LEAN_AND_MEAN #include <windows.h> +#include <mutex> #pragma warning( push ) #pragma warning( disable: 4068 ) @@ -124,21 +125,12 @@ public: obj->DestroyVoice(); } } - - void operator()(osd_lock* obj) const - { - if (obj != nullptr) - { - osd_lock_free(obj); - } - } }; // Typedefs for smart pointers used with customer deleters typedef std::unique_ptr<IXAudio2, xaudio2_custom_deleter> xaudio2_ptr; typedef std::unique_ptr<IXAudio2MasteringVoice, xaudio2_custom_deleter> mastering_voice_ptr; typedef std::unique_ptr<IXAudio2SourceVoice, xaudio2_custom_deleter> src_voice_ptr; -typedef std::unique_ptr<osd_lock, xaudio2_custom_deleter> osd_lock_ptr; // Typedef for pointer to XAudio2Create typedef HRESULT(__stdcall* PFN_XAUDIO2CREATE)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR); @@ -147,27 +139,6 @@ typedef HRESULT(__stdcall* PFN_XAUDIO2CREATE)(IXAudio2**, UINT32, XAUDIO2_PROCES // Helper classes //============================================================ -// Helper for locking within a particular scope without having to manually release -class osd_scoped_lock -{ -private: - 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); - } - } -}; - // Provides a pool of buffers class bufferpool { @@ -233,7 +204,7 @@ private: DWORD m_buffer_size; DWORD m_buffer_count; DWORD m_writepos; - osd_lock_ptr m_buffer_lock; + std::mutex m_buffer_lock; HANDLE m_hEventBufferCompleted; HANDLE m_hEventDataAvailable; HANDLE m_hEventExiting; @@ -258,7 +229,6 @@ public: 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), @@ -389,7 +359,7 @@ void sound_xaudio2::update_audio_stream( UINT32 const bytes_this_frame = samples_this_frame * m_sample_bytes; - osd_scoped_lock scope_lock(m_buffer_lock.get()); + std::lock_guard<std::mutex> lock(m_buffer_lock); UINT32 bytes_left = bytes_this_frame; @@ -446,7 +416,7 @@ 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()); + std::lock_guard<std::mutex> lock(m_buffer_lock); m_buffer_pool->return_to_pool(completed_buffer); } @@ -625,7 +595,7 @@ void sound_xaudio2::submit_needed() if (state.BuffersQueued >= 1) return; - osd_scoped_lock lock_scope(m_buffer_lock.get()); + std::lock_guard<std::mutex> lock(m_buffer_lock); // Roll the buffer roll_buffer(); |