Add sync audio for emscripten

This commit is contained in:
Varun Patil 2020-05-04 17:39:00 +05:30
parent ee39e65061
commit 9b531afb0c
9 changed files with 149 additions and 73 deletions

View File

@ -27,7 +27,7 @@
#define DEF_PLAY_STOP(entity) \ #define DEF_PLAY_STOP(entity) \
MRB_FUNCTION(audio_##entity##Play) \ MRB_FUNCTION(audio_##entity##Play) \
{ \ { \
return mrb_nil_value();char *filename; \ char *filename; \
mrb_int volume = 100; \ mrb_int volume = 100; \
mrb_int pitch = 100; \ mrb_int pitch = 100; \
mrb_get_args(mrb, "z|ii", &filename, &volume, &pitch); \ mrb_get_args(mrb, "z|ii", &filename, &volume, &pitch); \
@ -36,7 +36,7 @@
} \ } \
MRB_FUNCTION(audio_##entity##Stop) \ MRB_FUNCTION(audio_##entity##Stop) \
{ \ { \
return mrb_nil_value();MRB_FUN_UNUSED_PARAM; \ MRB_FUN_UNUSED_PARAM; \
shState->audio().entity##Stop(); \ shState->audio().entity##Stop(); \
return mrb_nil_value(); \ return mrb_nil_value(); \
} }
@ -44,7 +44,7 @@
#define DEF_FADE(entity) \ #define DEF_FADE(entity) \
MRB_FUNCTION(audio_##entity##Fade) \ MRB_FUNCTION(audio_##entity##Fade) \
{ \ { \
return mrb_nil_value();mrb_int time; \ mrb_int time; \
mrb_get_args(mrb, "i", &time); \ mrb_get_args(mrb, "i", &time); \
shState->audio().entity##Fade(time); \ shState->audio().entity##Fade(time); \
return mrb_nil_value(); \ return mrb_nil_value(); \

View File

@ -19,6 +19,10 @@
** along with mkxp. If not, see <http://www.gnu.org/licenses/>. ** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef __EMSCRIPTEN__
#include "audio.h"
#endif
#include "graphics.h" #include "graphics.h"
#include "sharedstate.h" #include "sharedstate.h"
#include "binding-util.h" #include "binding-util.h"
@ -30,6 +34,10 @@ MRB_FUNCTION(graphicsUpdate)
shState->graphics().update(); shState->graphics().update();
#ifdef __EMSCRIPTEN__
shState->audio().update();
#endif
return mrb_nil_value(); return mrb_nil_value();
} }

View File

@ -302,8 +302,12 @@ void ALStream::startStream(float offset)
startOffset = offset; startOffset = offset;
procFrames = offset * source->sampleRate(); procFrames = offset * source->sampleRate();
#ifdef __EMSCRIPTEN__
streamData();
#else
thread = createSDLThread thread = createSDLThread
<ALStream, &ALStream::streamData>(this, threadName); <ALStream, &ALStream::streamData>(this, threadName);
#endif
} }
void ALStream::pauseStream() void ALStream::pauseStream()
@ -362,7 +366,6 @@ void ALStream::streamData()
{ {
/* Fill up queue */ /* Fill up queue */
bool firstBuffer = true; bool firstBuffer = true;
ALDataSource::Status status;
if (threadTermReq) if (threadTermReq)
return; return;
@ -406,8 +409,22 @@ void ALStream::streamData()
/* Wait for buffers to be consumed, then /* Wait for buffers to be consumed, then
* refill and queue them up again */ * refill and queue them up again */
#ifndef __EMSCRIPTEN__
while (true) while (true)
{ {
streamDevice();
if (threadTermReq)
break;
SDL_Delay(AUDIO_SLEEP);
}
#endif
}
void ALStream::update() {
if (threadTermReq)
return;
shState->rtData().syncPoint.passSecondarySync(); shState->rtData().syncPoint.passSecondarySync();
ALint procBufs = AL::Source::getProcBufferCount(alSrc); ALint procBufs = AL::Source::getProcBufferCount(alSrc);
@ -470,10 +487,4 @@ void ALStream::streamData()
if (status == ALDataSource::EndOfStream) if (status == ALDataSource::EndOfStream)
sourceExhausted.set(); sourceExhausted.set();
} }
if (threadTermReq)
break;
SDL_Delay(AUDIO_SLEEP);
}
} }

View File

@ -23,13 +23,12 @@
#define ALSTREAM_H #define ALSTREAM_H
#include "al-util.h" #include "al-util.h"
#include "aldatasource.h"
#include "sdl-util.h" #include "sdl-util.h"
#include <string> #include <string>
#include <SDL_rwops.h> #include <SDL_rwops.h>
struct ALDataSource;
#define STREAM_BUFS 3 #define STREAM_BUFS 3
/* State-machine like audio playback stream. /* State-machine like audio playback stream.
@ -104,6 +103,8 @@ struct ALStream
float queryOffset(); float queryOffset();
bool queryNativePitch(); bool queryNativePitch();
void update();
private: private:
void closeSource(); void closeSource();
void openSource(const std::string &filename); void openSource(const std::string &filename);
@ -117,6 +118,8 @@ private:
/* thread func */ /* thread func */
void streamData(); void streamData();
ALDataSource::Status status;
}; };
#endif // ALSTREAM_H #endif // ALSTREAM_H

View File

@ -71,22 +71,27 @@ struct AudioPrivate
syncPoint(rtData.syncPoint) syncPoint(rtData.syncPoint)
{ {
meWatch.state = MeNotPlaying; meWatch.state = MeNotPlaying;
#ifndef __EMSCRIPTEN__
meWatch.thread = createSDLThread meWatch.thread = createSDLThread
<AudioPrivate, &AudioPrivate::meWatchFun>(this, "audio_mewatch"); <AudioPrivate, &AudioPrivate::meWatchFun>(this, "audio_mewatch");
#endif
} }
~AudioPrivate() ~AudioPrivate()
{ {
meWatch.termReq.set(); meWatch.termReq.set();
#ifndef __EMSCRIPTEN__
SDL_WaitThread(meWatch.thread, 0); SDL_WaitThread(meWatch.thread, 0);
#endif
} }
void meWatchFun() void meWatchFun()
{ {
const float fadeOutStep = 1.f / (200 / AUDIO_SLEEP); const float fadeOutStep = 1.f / (200 / AUDIO_SLEEP);
const float fadeInStep = 1.f / (1000 / AUDIO_SLEEP); const float fadeInStep = 1.f / (1000 / AUDIO_SLEEP);
#ifndef __EMSCRIPTEN__
while (true) while (true)
#endif
{ {
syncPoint.passSecondarySync(); syncPoint.passSecondarySync();
@ -231,8 +236,9 @@ struct AudioPrivate
break; break;
} }
} }
#ifndef __EMSCRIPTEN__
SDL_Delay(AUDIO_SLEEP); SDL_Delay(AUDIO_SLEEP);
#endif
} }
} }
}; };
@ -247,6 +253,7 @@ void Audio::bgmPlay(const char *filename,
int pitch, int pitch,
float pos) float pos)
{ {
printf("PLAYING BGM %s\n", filename);
p->bgm.play(filename, volume, pitch, pos); p->bgm.play(filename, volume, pitch, pos);
} }
@ -333,4 +340,14 @@ void Audio::reset()
p->se.stop(); p->se.stop();
} }
void Audio::update()
{
#ifdef __EMSCRIPTEN__
p->bgm.update();
p->bgm.update();
p->me.update();
p->meWatchFun();
#endif
}
Audio::~Audio() { delete p; } Audio::~Audio() { delete p; }

View File

@ -69,6 +69,8 @@ public:
void reset(); void reset();
void update();
private: private:
Audio(RGSSThreadData &rtData); Audio(RGSSThreadData &rtData);
~Audio(); ~Audio();

View File

@ -203,12 +203,14 @@ void AudioStream::fadeOut(int duration)
return; return;
} }
#ifdef __EMSCRIPTEN__
if (fade.thread) if (fade.thread)
{ {
fade.reqFini.set(); fade.reqFini.set();
SDL_WaitThread(fade.thread, 0); SDL_WaitThread(fade.thread, 0);
fade.thread = 0; fade.thread = 0;
} }
#endif
fade.active.set(); fade.active.set();
fade.msStep = 1.0f / duration; fade.msStep = 1.0f / duration;
@ -216,8 +218,10 @@ void AudioStream::fadeOut(int duration)
fade.reqTerm.clear(); fade.reqTerm.clear();
fade.startTicks = SDL_GetTicks(); fade.startTicks = SDL_GetTicks();
#ifndef __EMSCRIPTEN__
fade.thread = createSDLThread fade.thread = createSDLThread
<AudioStream, &AudioStream::fadeOutThread>(this, fade.threadName); <AudioStream, &AudioStream::fadeOutThread>(this, fade.threadName);
#endif
unlockStream(); unlockStream();
} }
@ -280,24 +284,38 @@ void AudioStream::finiFadeOutInt()
void AudioStream::startFadeIn() void AudioStream::startFadeIn()
{ {
#ifdef __EMSCRIPTEN__
/* Previous fadein should always be terminated in play() */ /* Previous fadein should always be terminated in play() */
assert(!fadeIn.thread); assert(!fadeIn.thread);
#endif
fadeIn.rqFini.clear(); fadeIn.rqFini.clear();
fadeIn.rqTerm.clear(); fadeIn.rqTerm.clear();
fadeIn.startTicks = SDL_GetTicks(); fadeIn.startTicks = SDL_GetTicks();
#ifdef __EMSCRIPTEN__
fadeInThread();
#else
fadeIn.thread = createSDLThread fadeIn.thread = createSDLThread
<AudioStream, &AudioStream::fadeInThread>(this, fadeIn.threadName); <AudioStream, &AudioStream::fadeInThread>(this, fadeIn.threadName);
#endif
} }
void AudioStream::fadeOutThread() void AudioStream::fadeOutThread()
{ {
#ifndef __EMSCRIPTEN__
while (true) while (true)
#else
if (fade.active)
#endif
{ {
/* Just immediately terminate on request */ /* Just immediately terminate on request */
if (fade.reqTerm) if (fade.reqTerm)
#ifdef __EMSCRIPTEN__
return;
#else
break; break;
#endif
lockStream(); lockStream();
@ -315,18 +333,26 @@ void AudioStream::fadeOutThread()
setVolume(FadeOut, 1.0f); setVolume(FadeOut, 1.0f);
unlockStream(); unlockStream();
#ifdef __EMSCRIPTEN__
fade.active.clear();
return;
#else
break; break;
#endif
} }
setVolume(FadeOut, resVol); setVolume(FadeOut, resVol);
unlockStream(); unlockStream();
#ifndef __EMSCRIPTEN__
SDL_Delay(AUDIO_SLEEP); SDL_Delay(AUDIO_SLEEP);
#endif
} }
#ifndef __EMSCRIPTEN__
fade.active.clear(); fade.active.clear();
#endif
} }
void AudioStream::fadeInThread() void AudioStream::fadeInThread()
@ -363,3 +389,9 @@ void AudioStream::fadeInThread()
SDL_Delay(AUDIO_SLEEP); SDL_Delay(AUDIO_SLEEP);
} }
} }
void AudioStream::update()
{
fadeOutThread();
stream.update();
}

View File

@ -140,6 +140,8 @@ struct AudioStream
float playingOffset(); float playingOffset();
void update();
private: private:
float volumes[VolumeTypeCount]; float volumes[VolumeTypeCount];
void updateVolume(); void updateVolume();

View File

@ -46,6 +46,7 @@ struct SDLSoundSource : ALDataSource
if (!sample) if (!sample)
{ {
SDL_RWclose(&ops); SDL_RWclose(&ops);
printf("ERROR SDL_sound: %s", Sound_GetError());
throw Exception(Exception::SDLError, "SDL_sound: %s", Sound_GetError()); throw Exception(Exception::SDLError, "SDL_sound: %s", Sound_GetError());
} }