Try to improve audio playback on mobile
This commit is contained in:
parent
7550707562
commit
f9c932b737
@ -58,7 +58,7 @@ endif
|
||||
CFLAGS += -Werror -Wall -Wno-strict-aliasing -Wno-unknown-warning -Wno-unknown-warning-option -Wno-multichar -Wno-int-in-bool-context -std=gnu11 -D_GNU_SOURCE -DVERSION="$(VERSION)" -I. -D_USE_MATH_DEFINES
|
||||
# CFLAGS += -DGB_INTERNAL=1 # get access to internal APIs
|
||||
CFLAGS += -I$(CORE_DIR)
|
||||
CFLAGS += -s WASM=1 -s USE_SDL=2 --preload-file $(BOOTROMS_DIR)@/BootROMs -s "EXTRA_EXPORTED_RUNTIME_METHODS=['FS']"
|
||||
CFLAGS += -s WASM=1 -s USE_SDL=2 --preload-file $(BOOTROMS_DIR)@/BootROMs -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap', 'getValue', 'AsciiToString', 'FS']"
|
||||
# CFLAGS += -Wcast-align -Wover-aligned -s SAFE_HEAP=1 -s WARN_UNALIGNED=1
|
||||
WASM_LDFLAGS :=
|
||||
|
||||
|
@ -98,6 +98,34 @@
|
||||
const progressElement = document.querySelector('#progress');
|
||||
|
||||
var Module = {
|
||||
get_models: function () {
|
||||
const ptr = Module._get_models_string_pointer();
|
||||
const ptr_size = Module._get_models_string_pointer_size();
|
||||
const size = Module._get_models_string_size() - ptr_size; // last element is a end marker
|
||||
const models = [];
|
||||
|
||||
for (let i = 0; i < size; i += ptr_size) {
|
||||
const key = AsciiToString(getValue(ptr + i, '*'));
|
||||
|
||||
models.push(key.replace(/^MODEL_/, ''));
|
||||
}
|
||||
|
||||
return models
|
||||
},
|
||||
get_sgb_revisions: function () {
|
||||
const ptr = Module._get_sgb_revisions_string_pointer();
|
||||
const ptr_size = Module._get_sgb_revisions_string_pointer_size();
|
||||
const size = Module._get_sgb_revisions_string_size() - ptr_size; // last element is a end marker
|
||||
const revisions = [];
|
||||
|
||||
for (let i = 0; i < size; i += ptr_size) {
|
||||
const key = AsciiToString(getValue(ptr + i, '*'));
|
||||
|
||||
revisions.push(key.replace(/^SGB_/, ''));
|
||||
}
|
||||
|
||||
return revisions
|
||||
},
|
||||
sync_fs: function () {
|
||||
console.log("Syncing file system ...");
|
||||
|
||||
|
82
wasm/main.c
82
wasm/main.c
@ -80,11 +80,15 @@ int save_battery(GB_gameboy_t *gb, const char *path) {
|
||||
|
||||
unsigned query_sample_rate_of_audiocontexts() {
|
||||
return EM_ASM_INT({
|
||||
const AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
const ctx = new AudioContext();
|
||||
const sr = ctx.sampleRate;
|
||||
ctx.close();
|
||||
return sr;
|
||||
if (!Module.SDL2 || !Module.SDL2.audioContext) {
|
||||
const AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
const ctx = new AudioContext();
|
||||
const sr = ctx.sampleRate;
|
||||
ctx.close();
|
||||
return sr;
|
||||
}
|
||||
|
||||
return Module.SDL2.audioContext.sampleRate;
|
||||
});
|
||||
}
|
||||
|
||||
@ -217,7 +221,7 @@ void init_gb() {
|
||||
}
|
||||
|
||||
int EMSCRIPTEN_KEEPALIVE init() {
|
||||
#define str(x) #x
|
||||
#define str(x) #x
|
||||
#define xstr(x) str(x)
|
||||
pixel_format = (SDL_PixelFormat *) malloc(sizeof(SDL_PixelFormat));
|
||||
|
||||
@ -292,7 +296,7 @@ int EMSCRIPTEN_KEEPALIVE init() {
|
||||
want_aspec.freq = audio_sample_rate;
|
||||
want_aspec.format = AUDIO_S16SYS;
|
||||
want_aspec.channels = 2;
|
||||
want_aspec.samples = 512;
|
||||
want_aspec.samples = 2048;
|
||||
|
||||
want_aspec.callback = audio_callback;
|
||||
want_aspec.userdata = &gb;
|
||||
@ -302,27 +306,51 @@ int EMSCRIPTEN_KEEPALIVE init() {
|
||||
fprintf(stderr, "Failed to open audio: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
EM_ASM({
|
||||
var AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
var ctx = new AudioContext();
|
||||
fprintf(stderr, "WANT:\nfreq: %d\nchannels: %d\nsilence: %d\nsamples: %d\nsize: %d\nformat: %d\n", want_aspec.freq, want_aspec.channels, want_aspec.silence, want_aspec.samples, want_aspec.size, want_aspec.format);
|
||||
fprintf(stderr, "HAVE:\nfreq: %d\nchannels: %d\nsilence: %d\nsamples: %d\nsize: %d\nformat: %d\n", have_aspec.freq, have_aspec.channels, have_aspec.silence, have_aspec.samples, have_aspec.size, have_aspec.format);
|
||||
|
||||
// unlock audio for iOS
|
||||
if (ctx && ctx.currentTime == 0) {
|
||||
var buffer = ctx.createBuffer(1, 1, 22050);
|
||||
var source = ctx.createBufferSource();
|
||||
source.buffer = buffer;
|
||||
source.connect(ctx.destination);
|
||||
source.start(0);
|
||||
EM_ASM({
|
||||
function audio_workaround(e) {
|
||||
if (!Module.SDL2 || !Module.SDL2.audioContext || !Module.SDL2.audioContext.resume) return;
|
||||
|
||||
console.log('Applying audio workarounds...');
|
||||
|
||||
if (Module.SDL2.audioContext.state == 'suspended') {
|
||||
Module.SDL2.audioContext.resume();
|
||||
}
|
||||
|
||||
if (Module.SDL2.audioContext.state == 'running') {
|
||||
document.removeEventListener('touchstart', audio_workaround);
|
||||
document.removeEventListener('click', audio_workaround);
|
||||
document.removeEventListener('keydown', audio_workaround);
|
||||
|
||||
if (Module.canvas) {
|
||||
Module.canvas.removeEventListener('touchstart', audio_workaround);
|
||||
Module.canvas.removeEventListener('click', audio_workaround);
|
||||
Module.canvas.removeEventListener('keydown', audio_workaround);
|
||||
}
|
||||
}
|
||||
else if (Module.SDL2.audioContext && Module.SDL2.audioContext.currentTime == 0) {
|
||||
// unlock audio for iOS
|
||||
let buffer = Module.SDL2.audioContext.createBuffer(1, 1, 22050);
|
||||
let source = Module.SDL2.audioContext.createBufferSource();
|
||||
source.buffer = buffer;
|
||||
source.connect(Module.SDL2.audioContext.destination);
|
||||
source.start(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Google audio enable work-around:
|
||||
// https://github.com/emscripten-ports/SDL2/issues/57
|
||||
try {
|
||||
if (!Module.SDL2 || !ctx || !ctx.resume) return;
|
||||
ctx.resume();
|
||||
} catch (err) {}
|
||||
document.addEventListener('touchstart', audio_workaround);
|
||||
document.addEventListener('click', audio_workaround);
|
||||
document.addEventListener('keydown', audio_workaround);
|
||||
|
||||
ctx.close();
|
||||
if (Module.canvas) {
|
||||
Module.canvas.addEventListener('touchstart', audio_workaround);
|
||||
Module.canvas.addEventListener('click', audio_workaround);
|
||||
Module.canvas.addEventListener('keydown', audio_workaround);
|
||||
}
|
||||
|
||||
audio_workaround();
|
||||
});
|
||||
|
||||
init_gb();
|
||||
@ -332,7 +360,11 @@ int EMSCRIPTEN_KEEPALIVE init() {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int EMSCRIPTEN_KEEPALIVE load_rom(char* filename, char* battery_save_path) {
|
||||
int EMSCRIPTEN_KEEPALIVE load_boot_rom_from_file(char* filename) {
|
||||
return GB_load_boot_rom(&gb, filename);
|
||||
}
|
||||
|
||||
int EMSCRIPTEN_KEEPALIVE load_rom_from_file(char* filename, char* battery_save_path) {
|
||||
int result = GB_load_rom(&gb, filename);
|
||||
|
||||
if (result == 0) {
|
||||
|
64
wasm/main.h
64
wasm/main.h
@ -1,6 +1,9 @@
|
||||
#ifndef main_h
|
||||
#define main_h
|
||||
|
||||
#define str(x) #x
|
||||
#define xstr(x) str(x)
|
||||
|
||||
#define VIDEO_WIDTH 160
|
||||
#define VIDEO_HEIGHT 144
|
||||
#define VIDEO_PIXELS (VIDEO_WIDTH * VIDEO_HEIGHT)
|
||||
@ -9,6 +12,22 @@
|
||||
#define SGB_VIDEO_HEIGHT 224
|
||||
#define SGB_VIDEO_PIXELS (SGB_VIDEO_WIDTH * SGB_VIDEO_HEIGHT)
|
||||
|
||||
#define GENERATE_ENUM(ENUM) ENUM,
|
||||
#define GENERATE_STRING(STRING) #STRING,
|
||||
|
||||
#define MODELS(MODEL) \
|
||||
MODEL(MODEL_DMG) \
|
||||
MODEL(MODEL_CGB) \
|
||||
MODEL(MODEL_AGB) \
|
||||
MODEL(MODEL_SGB) \
|
||||
MODEL(MODEL_MAX)
|
||||
|
||||
#define SGB_REVISIONS(REVISION) \
|
||||
REVISION(SGB_NTSC) \
|
||||
REVISION(SGB_PAL) \
|
||||
REVISION(SGB_2) \
|
||||
REVISION(SGB_MAX)
|
||||
|
||||
typedef enum {
|
||||
JOYPAD_AXISES_X,
|
||||
JOYPAD_AXISES_Y,
|
||||
@ -24,11 +43,7 @@ typedef struct {
|
||||
|
||||
char filter[32];
|
||||
enum {
|
||||
MODEL_DMG,
|
||||
MODEL_CGB,
|
||||
MODEL_AGB,
|
||||
MODEL_SGB,
|
||||
MODEL_MAX,
|
||||
MODELS(GENERATE_ENUM)
|
||||
} model;
|
||||
|
||||
/* v0.11 */
|
||||
@ -39,11 +54,42 @@ typedef struct {
|
||||
|
||||
/* v0.12 */
|
||||
enum {
|
||||
SGB_NTSC,
|
||||
SGB_PAL,
|
||||
SGB_2,
|
||||
SGB_MAX
|
||||
SGB_REVISIONS(GENERATE_ENUM)
|
||||
} sgb_revision;
|
||||
} configuration_t;
|
||||
|
||||
// TODO: There must be a better way to not duplicate this data on the JavaScript side
|
||||
static const char *MODELS_STRING[] = {
|
||||
MODELS(GENERATE_STRING)
|
||||
};
|
||||
|
||||
static const char *SGB_REVISIONS_STRING[] = {
|
||||
SGB_REVISIONS(GENERATE_STRING)
|
||||
};
|
||||
|
||||
static const char** EMSCRIPTEN_KEEPALIVE get_models_string_pointer() {
|
||||
return MODELS_STRING;
|
||||
}
|
||||
|
||||
static const size_t EMSCRIPTEN_KEEPALIVE get_models_string_pointer_size() {
|
||||
return sizeof(*MODELS_STRING);
|
||||
}
|
||||
|
||||
static const size_t EMSCRIPTEN_KEEPALIVE get_models_string_size() {
|
||||
return sizeof(MODELS_STRING);
|
||||
}
|
||||
|
||||
static const char** EMSCRIPTEN_KEEPALIVE get_sgb_revisions_string_pointer() {
|
||||
return SGB_REVISIONS_STRING;
|
||||
}
|
||||
|
||||
static const size_t EMSCRIPTEN_KEEPALIVE get_sgb_revisions_string_pointer_size() {
|
||||
return sizeof(*SGB_REVISIONS_STRING);
|
||||
}
|
||||
|
||||
static const size_t EMSCRIPTEN_KEEPALIVE get_sgb_revisions_string_size() {
|
||||
return sizeof(SGB_REVISIONS_STRING);
|
||||
}
|
||||
|
||||
|
||||
#endif /* main_h */
|
||||
|
@ -50,7 +50,7 @@ const loadRomFromMemory = (name, data) => {
|
||||
const rom_path = allocate(intArrayFromString(`/rom/${name}`), 'i8', ALLOC_NORMAL);
|
||||
const battery_path = allocate(intArrayFromString(`/persist/${battery_name}`), 'i8', ALLOC_NORMAL);
|
||||
|
||||
Module._load_rom(rom_path, battery_path);
|
||||
Module._load_rom_from_file(rom_path, battery_path);
|
||||
|
||||
// The ROM has been read into memory, we can unlink the file now
|
||||
FS.unlink(`/rom/${name}`)
|
||||
@ -123,6 +123,9 @@ document.getElementById('file').addEventListener('change', e => {
|
||||
}, false);
|
||||
|
||||
Module.onRuntimeInitialized = _ => {
|
||||
console.log(Module.get_models());
|
||||
console.log(Module.get_sgb_revisions());
|
||||
|
||||
FS.mkdir('/persist');
|
||||
FS.mount(IDBFS, { }, '/persist');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user