summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/sound
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/sound')
-rw-r--r--src/osd/modules/sound/direct_sound.cpp9
-rw-r--r--src/osd/modules/sound/js_sound.cpp6
-rw-r--r--src/osd/modules/sound/js_sound.js213
-rw-r--r--src/osd/modules/sound/sdl_sound.cpp4
-rw-r--r--src/osd/modules/sound/xaudio2_sound.cpp40
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();