diff --git a/src/Audio.c b/src/Audio.c index bc486ef03..e861f82a1 100644 --- a/src/Audio.c +++ b/src/Audio.c @@ -717,6 +717,67 @@ cc_bool Audio_DescribeError(cc_result res, cc_string* dst) { if (err) String_AppendConst(dst, err); return err != NULL; } +#elif defined CC_BUILD_WEBAUDIO +/*########################################################################################################################* +*-----------------------------------------------------WebAudio backend----------------------------------------------------* +*#########################################################################################################################*/ +struct AudioContext { int contextID; }; +extern int interop_InitAudio(void); +extern int interop_AudioCreate(void); +extern void interop_AudioClose(int contextID); +extern int interop_AudioPlay(int contextID, const char* name); +extern int interop_AudioDescribe(int res, char* buffer, int bufferLen); + +static cc_bool AudioBackend_Init(void) { + cc_result res = interop_InitAudio(); + if (res) { AudioWarn(res, "initing WebAudio context"); return false; } + + InitFakeSounds(); + return true; +} + +void Audio_Init(struct AudioContext* ctx, int buffers) { +} + +void Audio_Close(struct AudioContext* ctx) { + if (ctx->contextID) interop_AudioClose(ctx->contextID); + ctx->contextID = 0; +} + +cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate) { + return ERR_NOT_SUPPORTED; +} + +cc_result Audio_QueueData(struct AudioContext* ctx, void* data, cc_uint32 size) { + return ERR_NOT_SUPPORTED; +} + +cc_result Audio_Play(struct AudioContext* ctx) { + return ERR_NOT_SUPPORTED; +} + +cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) { + return ERR_NOT_SUPPORTED; +} + +cc_bool Audio_FastPlay(struct AudioContext* ctx, int channels, int sampleRate) { + /* Channels/Sample rate is per buffer, not a per source property */ + return true; +} + +cc_result Audio_PlaySound(struct AudioContext* ctx, struct Sound* snd, int volume) { + if (!ctx->contextID) + ctx->contextID = interop_AudioCreate(); + return interop_AudioPlay(ctx->contextID, snd->data); +} + +cc_bool Audio_DescribeError(cc_result res, cc_string* dst) { + char buffer[NATIVE_STR_LEN]; + int len = interop_AudioDescribe(res, buffer, NATIVE_STR_LEN); + + String_AppendUtf8(dst, buffer, len); + return len > 0; +} #endif /*########################################################################################################################* @@ -989,6 +1050,12 @@ static void Sounds_LoadFile(const cc_string* path, void* obj) { Soundboard_Load(&stepBoard, &step, path); } +/* TODO this is a pretty terrible solution */ +#ifdef CC_BUILD_WEBAUDIO +static void InitWebSounds(void) { +} +#endif + static cc_bool sounds_loaded; static void Sounds_Start(void) { int i; @@ -1004,7 +1071,11 @@ static void Sounds_Start(void) { if (sounds_loaded) return; sounds_loaded = true; +#ifdef CC_BUILD_WEBAUDIO + InitWebSounds(); +#else Directory_Enum(&audio_dir, NULL, Sounds_LoadFile); +#endif } static void Sounds_Stop(void) { diff --git a/src/Core.h b/src/Core.h index 1a12499cf..b53973bf6 100644 --- a/src/Core.h +++ b/src/Core.h @@ -239,7 +239,7 @@ Thus it is **NOT SAFE** to allocate a string on the stack. */ #define CC_BUILD_GLMODERN #define CC_BUILD_GLES #define CC_BUILD_TOUCH -#define CC_BUILD_NOSOUNDS +#define CC_BUILD_WEBAUDIO #define CC_BUILD_NOMUSIC #define CC_BUILD_MINFILES #endif diff --git a/src/interop_web.js b/src/interop_web.js index 062b0d490..365473b8e 100644 --- a/src/interop_web.js +++ b/src/interop_web.js @@ -660,5 +660,85 @@ mergeInto(LibraryManager.library, { var dbg = GLctx.getExtension('WEBGL_debug_renderer_info'); var str = dbg ? GLctx.getParameter(dbg.UNMASKED_RENDERER_WEBGL) : ""; stringToUTF8(str, buffer, len); - } + }, + + +//######################################################################################################################## +//---------------------------------------------------------Sockets-------------------------------------------------------- +//######################################################################################################################## + interop_AudioLog: function(err) { + console.log(err); + window.AUDIO.errors.push(''+err); + return window.AUDIO.errors.length|0; + }, + interop_InitAudio: function() { + window.AUDIO = window.AUDIO || { + context: null, + sources: [], + buffers: {}, + errors: [], + seen: {}, + }; + if (window.AUDIO.context) return 0; + + // TODO error handling everywhere + try { + if (window.AudioContext) { + AUDIO.context = new window.AudioContext(); + } else { + AUDIO.context = new window.webkitAudioContext(); + } + } catch (err) { + return _interop_AudioLog(err) + } + return 0; + }, + interop_InitAudio__deps: ['interop_AudioLog'], + interop_AudioCreate: function() { + var source = AUDIO.context.createBufferSource(); + AUDIO.sources.push(source); + return AUDIO.sources.length|0; + // NOTE: 0 is used by Audio.c for "no source" + }, + interop_AudioClose: function(ctxID) { + var source = AUDIO.sources[ctxID - 1|0]; + source.stop(); + AUDIO.sources[ctxID - 1|0] = null; + }, + interop_AudioPlay: function(ctxID, name) { + var source = AUDIO.sources[ctxID - 1|0]; + var name_ = UTF8ToString(name); + + // have we already downloaded or are downloading this file? + if (!AUDIO.seen.hasOwnProperty(name_)) { + Audio.seen[name_] = true; + _interop_AudioDownload(name_); + return 0; + } + + source.buffer = AUDIO.buffers[name_]; + source.connect(audioCtx.destination); + source.start(); + return 0; + }, + interop_AudioPlay__deps: ['interop_AudioDownload'], + interop_AudioDownload: function(name) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', 'static/' + name + '.wav', true); + xhr.responseType = 'arraybuffer'; + + xhr.onload = function() { + var data = xhr.response; + AUDIO.context.decodeAudioData(data, function(buffer) { + AUDIO.buffers[name] = buffer; + }); + }; + xhr.send(); + }, + interop_AudioDescribe: function(errCode, buffer, bufferLen) { + if (errCode > AUDIO.errors.length) return 0; + + var str = AUDIO.errors[errCode - 1]; + return stringToUTF8(str, buffer, bufferLen); + }, }); \ No newline at end of file