From 831e0765db206708b56c4f7ca1d2f83058e54afd Mon Sep 17 00:00:00 2001 From: XProger Date: Tue, 4 Oct 2016 23:00:37 +0300 Subject: [PATCH] #9 support Web Audio API, defines for ADPCM, MP3 & OGG decoders, play bubble sound when Lara is under water --- bin/OpenLara.exe | Bin 103936 -> 82432 bytes src/controller.h | 7 ++---- src/game.h | 10 +++++---- src/sound.h | 52 ++++++++++++++++++++++++++++++++++++--------- src/web/build.bat | 4 ++-- src/web/index.html | 26 ++++++++++++++++++++++- src/web/main.cpp | 10 ++++++++- 7 files changed, 86 insertions(+), 23 deletions(-) diff --git a/bin/OpenLara.exe b/bin/OpenLara.exe index 84b909d3de27840f7ae6a5ff16a293c7ea6ea801..ae1da417a53eb7c101fa6c65ac8219fff3effb80 100644 GIT binary patch delta 18514 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 delta 39887 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[b.offset + rand() % ((b.flags & 0xFF) >> 2)]; void *p = &level->soundData[c]; - #ifdef WIN32 Sound::play(new Stream(p, 1024 * 1024), b.volume / 255.0f, 0.0f, Sound::Flags::PAN); - // PlaySound((LPSTR)p, NULL, SND_ASYNC | SND_MEMORY); - #endif } } @@ -373,8 +370,8 @@ struct Controller { case TR::ANIM_CMD_SPECIAL : // special commands if (frameIndex != animPrevFrame && frameIndex + anim->frameStart == ptr[0]) { switch (ptr[1]) { - case TR::ANIM_CMD_SPECIAL_FLIP : angle.y = angle.y + PI; break; - case TR::ANIM_CMD_SPECIAL_BUBBLE : /* playSound(TR::SND_BUBBLE); */ break; + case TR::ANIM_CMD_SPECIAL_FLIP : angle.y = angle.y + PI; break; + case TR::ANIM_CMD_SPECIAL_BUBBLE : playSound(TR::SND_BUBBLE); break; case TR::ANIM_CMD_SPECIAL_CTRL : LOG("water out ?\n"); break; default : LOG("unknown special cmd %d\n", (int)ptr[1]); } diff --git a/src/game.h b/src/game.h index 09636f9..64bc0c1 100644 --- a/src/game.h +++ b/src/game.h @@ -14,10 +14,12 @@ namespace Game { Core::init(); Stream stream("LEVEL2_DEMO.PHD"); level = new Level(stream); - - //Sound::play(Sound::openWAD("05_Lara's_Themes.wav"), 1, 1, 0); - Sound::play(new Stream("05.ogg"), 1, 1, 0); - //Sound::play(new Stream("03.mp3"), 1, 1, 0); + + #ifndef __EMSCRIPTEN__ + //Sound::play(Sound::openWAD("05_Lara's_Themes.wav"), 1, 1, 0); + Sound::play(new Stream("05.ogg"), 1, 1, 0); + //Sound::play(new Stream("03.mp3"), 1, 1, 0); + #endif } void free() { diff --git a/src/sound.h b/src/sound.h index 7b555b7..f0daf42 100644 --- a/src/sound.h +++ b/src/sound.h @@ -1,13 +1,25 @@ #ifndef H_SOUND #define H_SOUND +//#define DECODE_ADPCM +//#define DECODE_MP3 +#define DECODE_OGG + +#ifdef __EMSCRIPTEN__ // TODO: http streaming + #undef DECODE_MP3 + #undef DECODE_OGG +#endif + #include "utils.h" -#include "libs/minimp3/minimp3.h" -#define STB_VORBIS_HEADER_ONLY -#include "libs/stb_vorbis/stb_vorbis.c" +#ifdef DECODE_MP3 + #include "libs/minimp3/minimp3.h" +#endif +#ifdef DECODE_OGG + #define STB_VORBIS_HEADER_ONLY + #include "libs/stb_vorbis/stb_vorbis.c" +#endif #define SND_CHANNELS_MAX 32 -#define BUFFER_SIZE_MP3 8192 namespace Sound { @@ -56,6 +68,7 @@ namespace Sound { } }; +#ifdef DECODE_ADPCM struct ADPCM : Decoder { // https://wiki.multimedia.cx/?title=Microsoft_ADPCM int size, block; @@ -127,7 +140,9 @@ namespace Sound { } } }; - +#endif + +#ifdef DECODE_MP3 struct MP3 : Decoder { mp3_decoder_t mp3; char *buffer; @@ -160,7 +175,9 @@ namespace Sound { return i; } }; +#endif +#ifdef DECODE_OGG struct OGG : Decoder { stb_vorbis *ogg; stb_vorbis_alloc alloc; @@ -195,6 +212,7 @@ namespace Sound { return i; } }; +#endif struct Listener { mat4 matrix; @@ -216,7 +234,7 @@ namespace Sound { int flags; bool isPlaying; - Sample(Stream *stream, float volume, float pitch, int flags) : decoder(NULL), volume(volume), pitch(pitch), flags(flags), isPlaying(true) { + Sample(Stream *stream, float volume, float pitch, int flags) : decoder(NULL), volume(volume), pitch(pitch), flags(flags) { uint32 fourcc; stream->read(fourcc); if (fourcc == FOURCC("RIFF")) { // wav @@ -240,19 +258,28 @@ namespace Sound { stream->seek(size - sizeof(waveFmt)); } else if (type == FOURCC("data")) { if (waveFmt.format == 1) decoder = new PCM(stream, waveFmt.channels, waveFmt.samplesPerSec, size, waveFmt.sampleBits); + #ifdef DECODE_ADPCM if (waveFmt.format == 2) decoder = new ADPCM(stream, waveFmt.channels, size, waveFmt.block); + #endif break; } else stream->seek(size); } - } else if (fourcc == FOURCC("OggS")) { // ogg + } + #ifdef DECODE_OGG + else if (fourcc == FOURCC("OggS")) { // ogg stream->seek(-4); decoder = new OGG(stream, 2); - } else if (fourcc == FOURCC("ID3\3")) { // mp3 + } + #endif + #ifdef DECODE_MP3 + else if (fourcc == FOURCC("ID3\3")) { // mp3 decoder = new MP3(stream, 2); } - - ASSERT(decoder != NULL); + #endif + + isPlaying = decoder != NULL; + ASSERT(isPlaying); } ~Sample() { @@ -260,6 +287,7 @@ namespace Sound { } bool render(Frame *frames, int count) { + if (!isPlaying) return 0; int i = 0; while (i < count) { int res = decoder->decode(&frames[i], count - i); @@ -277,13 +305,17 @@ namespace Sound { void init() { channelsCount = 0; + #ifdef DECODE_MP3 mp3_decode_init(); + #endif } void free() { for (int i = 0; i < channelsCount; i++) delete channels[i]; + #ifdef DECODE_MP3 mp3_decode_free(); + #endif } void fill(Frame *frames, int count) { diff --git a/src/web/build.bat b/src/web/build.bat index 39b9900..55c1117 100644 --- a/src/web/build.bat +++ b/src/web/build.bat @@ -1,3 +1,3 @@ -set SRC=main.cpp ../libs/minimp3/minimp3.cpp ../libs/stb_vorbis/stb_vorbis.c -call em++ %SRC% -O2 -s ASSERTIONS=1 -Wno-deprecated-register --llvm-opts 2 --closure 2 -std=c++11 -o OpenLara.js --preload-file ./LEVEL2_DEMO.PHD -I..\ +set SRC=main.cpp +call em++ %SRC% -O2 -s ASSERTIONS=1 -Wno-deprecated-register --llvm-opts 2 --closure 1 -std=c++11 -o OpenLara.js --preload-file ./LEVEL2_DEMO.PHD -I..\ gzip.exe -9 -f OpenLara.data OpenLara.js OpenLara.js.mem \ No newline at end of file diff --git a/src/web/index.html b/src/web/index.html index 0da390a..992a664 100644 --- a/src/web/index.html +++ b/src/web/index.html @@ -41,8 +41,30 @@ monitorRunDependencies: function(left) { this.totalDependencies = Math.max(this.totalDependencies, left); Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.'); - } + }, }; + + function snd_init() { + var AudioContext = window.AudioContext || window.webkitAudioContext; + if (!AudioContext) return; + var ctx = new (window.AudioContext || window.webkitAudioContext)(); + var count = 2048; + var frames = Module._malloc(count * 4); // interleaved short L, R + var proc = ctx.createScriptProcessor(count, 2, 2); + + proc.onaudioprocess = function(e) { + var L = e.outputBuffer.getChannelData(0), + R = e.outputBuffer.getChannelData(1); + Module.ccall('snd_fill', 'null', ['number', 'number'], [frames, count]); + var index = frames; + for (var i = 0; i < count; i++) { + L[i] = Module.getValue(index , 'i16') / 0x8000; + R[i] = Module.getValue(index + 2, 'i16') / 0x8000; + index += 4; + } + } + proc.connect(ctx.destination); + } var gl = canvasElement.getContext("webgl") || canvasElement.getContext("experimental-webgl"); @@ -74,5 +96,7 @@ script.src = "OpenLara.js"; document.body.appendChild(script); + + \ No newline at end of file diff --git a/src/web/main.cpp b/src/web/main.cpp index 1f60d1c..125fd56 100644 --- a/src/web/main.cpp +++ b/src/web/main.cpp @@ -12,6 +12,12 @@ int getTime() { return (int)emscripten_get_now(); } +extern "C" { + void EMSCRIPTEN_KEEPALIVE snd_fill(Sound::Frame *frames, int count) { + Sound::fill(frames, count); + } +} + void main_loop() { int time = getTime(); @@ -168,7 +174,7 @@ EM_BOOL mouseCallback(int eventType, const EmscriptenMouseEvent *e, void *userDa int main() { initGL(); - emscripten_set_canvas_size(Core::width = 1280, Core::height = 720); + emscripten_set_canvas_size(Core::width = 854, Core::height = 480); emscripten_set_keydown_callback(0, 0, 1, keyCallback); emscripten_set_keyup_callback(0, 0, 1, keyCallback); @@ -185,6 +191,8 @@ int main() { Game::init(); + emscripten_run_script("snd_init()"); + lastTime = getTime(); fpsTime = lastTime + 1000; fps = 0;