mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
Merge branch 'master' of https://github.com/mamedev/mame
This commit is contained in:
commit
9e910e95a8
@ -88,7 +88,7 @@ end
|
||||
targetextension ".bc"
|
||||
if os.getenv("EMSCRIPTEN") then
|
||||
postbuildcommands {
|
||||
os.getenv("EMSCRIPTEN") .. "/emcc -O3 -s DISABLE_EXCEPTION_CATCHING=2 -s USE_SDL=2 --memory-init-file 0 -s ALLOW_MEMORY_GROWTH=0 -s TOTAL_MEMORY=268435456 -s EXCEPTION_CATCHING_WHITELIST='[\"__ZN15running_machine17start_all_devicesEv\"]' -s EXPORTED_FUNCTIONS=\"['_main', '_malloc', '__Z14js_get_machinev', '__Z9js_get_uiv', '__Z12js_get_soundv', '__ZN10ui_manager12set_show_fpsEb', '__ZNK10ui_manager8show_fpsEv', '__ZN13sound_manager4muteEbh', '_SDL_PauseAudio']\" $(TARGET) -o " .. _MAKE.esc(MAME_DIR) .. _OPTIONS["target"] .. _OPTIONS["subtarget"] .. ".js --post-js " .. _MAKE.esc(MAME_DIR) .. "src/osd/sdl/emscripten_post.js",
|
||||
os.getenv("EMSCRIPTEN") .. "/emcc -O3 -s DISABLE_EXCEPTION_CATCHING=2 -s USE_SDL=2 --memory-init-file 0 -s ALLOW_MEMORY_GROWTH=0 -s TOTAL_MEMORY=268435456 -s EXCEPTION_CATCHING_WHITELIST='[\"__ZN15running_machine17start_all_devicesEv\"]' -s EXPORTED_FUNCTIONS=\"['_main', '_malloc', '__Z14js_get_machinev', '__Z9js_get_uiv', '__Z12js_get_soundv', '__ZN10ui_manager12set_show_fpsEb', '__ZNK10ui_manager8show_fpsEv', '__ZN13sound_manager4muteEbh', '_SDL_PauseAudio']\" $(TARGET) -o " .. _MAKE.esc(MAME_DIR) .. _OPTIONS["target"] .. _OPTIONS["subtarget"] .. ".js --pre-js " .. _MAKE.esc(MAME_DIR) .. "src/osd/modules/sound/js_sound.js --post-js " .. _MAKE.esc(MAME_DIR) .. "src/osd/sdl/emscripten_post.js",
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
213
src/osd/modules/sound/js_sound.js
Normal file
213
src/osd/modules/sound/js_sound.js
Normal file
@ -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;
|
Loading…
Reference in New Issue
Block a user