mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-09-10 12:02:53 +02:00
Implement audio fading in libretro builds
This commit is contained in:
parent
9f3329e1cb
commit
8fa20c660a
6 changed files with 335 additions and 180 deletions
|
@ -27,10 +27,6 @@
|
|||
|
||||
namespace mkxp_sandbox {
|
||||
SANDBOX_COROUTINE(audio_binding_init,
|
||||
static VALUE todo(int32_t argc, wasm_ptr_t argv, VALUE self) {
|
||||
return SANDBOX_NIL;
|
||||
}
|
||||
|
||||
static VALUE bgm_play(int32_t argc, wasm_ptr_t argv, VALUE self) {
|
||||
SANDBOX_COROUTINE(coro,
|
||||
wasm_ptr_t filename;
|
||||
|
@ -81,6 +77,28 @@ namespace mkxp_sandbox {
|
|||
return SANDBOX_NIL;
|
||||
}
|
||||
|
||||
static VALUE bgm_fade(int32_t argc, wasm_ptr_t argv, VALUE self) {
|
||||
SANDBOX_COROUTINE(coro,
|
||||
int32_t time;
|
||||
int32_t track;
|
||||
|
||||
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
|
||||
BOOST_ASIO_CORO_REENTER (this) {
|
||||
track = -127;
|
||||
SANDBOX_AWAIT_AND_SET(time, rb_num2int, ((VALUE *)(**sb() + argv))[0]);
|
||||
if (argc >= 2) {
|
||||
SANDBOX_AWAIT_AND_SET(track, rb_num2int, ((VALUE *)(**sb() + argv))[1]);
|
||||
}
|
||||
mkxp_retro::audio->bgmFade(time, track);
|
||||
}
|
||||
|
||||
return SANDBOX_NIL;
|
||||
}
|
||||
)
|
||||
|
||||
return sb()->bind<struct coro>()()(argc, argv, self);
|
||||
}
|
||||
|
||||
static VALUE bgm_pos(int32_t argc, wasm_ptr_t argv, VALUE self) {
|
||||
SANDBOX_COROUTINE(coro,
|
||||
int32_t track;
|
||||
|
@ -188,6 +206,23 @@ namespace mkxp_sandbox {
|
|||
return SANDBOX_NIL;
|
||||
}
|
||||
|
||||
static VALUE bgs_fade(VALUE self, VALUE value) {
|
||||
SANDBOX_COROUTINE(coro,
|
||||
int32_t time;
|
||||
|
||||
VALUE operator()(VALUE self, VALUE value) {
|
||||
BOOST_ASIO_CORO_REENTER (this) {
|
||||
SANDBOX_AWAIT_AND_SET(time, rb_num2int, value);
|
||||
mkxp_retro::audio->bgsFade(time);
|
||||
}
|
||||
|
||||
return SANDBOX_NIL;
|
||||
}
|
||||
)
|
||||
|
||||
return sb()->bind<struct coro>()()(self, value);
|
||||
}
|
||||
|
||||
static VALUE bgs_pos(VALUE self) {
|
||||
SANDBOX_COROUTINE(coro,
|
||||
double pos;
|
||||
|
@ -240,6 +275,23 @@ namespace mkxp_sandbox {
|
|||
return SANDBOX_NIL;
|
||||
}
|
||||
|
||||
static VALUE me_fade(VALUE self, VALUE value) {
|
||||
SANDBOX_COROUTINE(coro,
|
||||
int32_t time;
|
||||
|
||||
VALUE operator()(VALUE self, VALUE value) {
|
||||
BOOST_ASIO_CORO_REENTER (this) {
|
||||
SANDBOX_AWAIT_AND_SET(time, rb_num2int, value);
|
||||
mkxp_retro::audio->meFade(time);
|
||||
}
|
||||
|
||||
return SANDBOX_NIL;
|
||||
}
|
||||
)
|
||||
|
||||
return sb()->bind<struct coro>()()(self, value);
|
||||
}
|
||||
|
||||
static VALUE se_play(int32_t argc, wasm_ptr_t argv, VALUE self) {
|
||||
SANDBOX_COROUTINE(coro,
|
||||
wasm_ptr_t filename;
|
||||
|
@ -281,17 +333,17 @@ namespace mkxp_sandbox {
|
|||
SANDBOX_AWAIT_AND_SET(module, rb_define_module, "Audio");
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "bgm_play", (VALUE (*)(ANYARGS))bgm_play, -1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "bgm_stop", (VALUE (*)(ANYARGS))bgm_stop, 0);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "bgm_fade", (VALUE (*)(ANYARGS))todo, -1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "bgm_fade", (VALUE (*)(ANYARGS))bgm_fade, -1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "bgm_pos", (VALUE (*)(ANYARGS))bgm_pos, -1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "bgm_volume", (VALUE (*)(ANYARGS))bgm_volume, -1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "bgm_set_volume", (VALUE (*)(ANYARGS))bgm_set_volume, -1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "bgs_play", (VALUE (*)(ANYARGS))bgs_play, -1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "bgs_stop", (VALUE (*)(ANYARGS))bgs_stop, 0);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "bgs_fade", (VALUE (*)(ANYARGS))todo, -1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "bgs_fade", (VALUE (*)(ANYARGS))bgs_fade, 1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "bgs_pos", (VALUE (*)(ANYARGS))bgs_pos, 0);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "me_play", (VALUE (*)(ANYARGS))me_play, -1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "me_stop", (VALUE (*)(ANYARGS))me_stop, 0);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "me_fade", (VALUE (*)(ANYARGS))todo, -1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "me_fade", (VALUE (*)(ANYARGS))me_fade, 1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "se_play", (VALUE (*)(ANYARGS))se_play, -1);
|
||||
SANDBOX_AWAIT(rb_define_module_function, module, "se_stop", (VALUE (*)(ANYARGS))se_stop, 0);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace mkxp_retro {
|
|||
extern retro_input_state_t input_state;
|
||||
extern struct retro_perf_callback perf;
|
||||
extern struct retro_hw_render_callback hw_render;
|
||||
|
||||
uint64_t get_ticks() noexcept;
|
||||
}
|
||||
|
||||
#endif // MKXPZ_CORE_H
|
||||
|
|
|
@ -65,14 +65,14 @@ struct AudioPrivate
|
|||
BgmFadingIn
|
||||
};
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
struct
|
||||
{
|
||||
#ifndef MKXPZ_RETRO
|
||||
SDL_Thread *thread;
|
||||
#endif // MKXPZ_RETRO
|
||||
AtomicFlag termReq;
|
||||
MeWatchState state;
|
||||
} meWatch;
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
AudioPrivate()
|
||||
|
@ -96,10 +96,10 @@ struct AudioPrivate
|
|||
bgmTracks.push_back(new AudioStream(ALStream::Looped, id.c_str()));
|
||||
}
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
meWatch.state = MeNotPlaying;
|
||||
#ifndef MKXPZ_RETRO
|
||||
meWatch.thread = createSDLThread
|
||||
<AudioPrivate, &AudioPrivate::meWatchFun>(this, "audio_mewatch");
|
||||
<AudioPrivate, &AudioPrivate::meWatchThread>(this, "audio_mewatch");
|
||||
#endif // MKXPZ_RETRO
|
||||
}
|
||||
|
||||
|
@ -121,21 +121,18 @@ struct AudioPrivate
|
|||
return bgmTracks[index];
|
||||
}
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
void meWatchFun()
|
||||
void meWatchProc()
|
||||
{
|
||||
#ifdef MKXPZ_RETRO // TODO: use FPS
|
||||
const float fadeOutStep = 1.f / (200 / 17);
|
||||
const float fadeInStep = 1.f / (1000 / 17);
|
||||
#else
|
||||
const float fadeOutStep = 1.f / (200 / AUDIO_SLEEP);
|
||||
const float fadeInStep = 1.f / (1000 / AUDIO_SLEEP);
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
while (true)
|
||||
switch (meWatch.state)
|
||||
{
|
||||
syncPoint.passSecondarySync();
|
||||
|
||||
if (meWatch.termReq)
|
||||
return;
|
||||
|
||||
switch (meWatch.state)
|
||||
{
|
||||
case MeNotPlaying:
|
||||
{
|
||||
me.lockStream();
|
||||
|
@ -143,9 +140,9 @@ struct AudioPrivate
|
|||
if (me.stream.queryState() == ALStream::Playing)
|
||||
{
|
||||
/* ME playing detected. -> FadeOutBGM */
|
||||
for (auto track : bgmTracks)
|
||||
track->extPaused = true;
|
||||
|
||||
for (auto track : bgmTracks)
|
||||
track->extPaused = true;
|
||||
|
||||
meWatch.state = BgmFadingOut;
|
||||
}
|
||||
|
||||
|
@ -166,45 +163,45 @@ struct AudioPrivate
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
bool shouldBreak = false;
|
||||
|
||||
for (int i = 0; i < (int)(bgmTracks.size()); i++) {
|
||||
AudioStream *track = bgmTracks[i];
|
||||
|
||||
track->lockStream();
|
||||
|
||||
float vol = track->getVolume(AudioStream::External);
|
||||
vol -= fadeOutStep;
|
||||
|
||||
if (vol < 0 || track->stream.queryState() != ALStream::Playing) {
|
||||
/* Either BGM has fully faded out, or stopped midway. -> MePlaying */
|
||||
track->setVolume(AudioStream::External, 0);
|
||||
track->stream.pause();
|
||||
track->unlockStream();
|
||||
|
||||
// check to see if there are any tracks still playing,
|
||||
// and if the last one was ended this round, this branch should exit
|
||||
std::vector<AudioStream*> playingTracks;
|
||||
for (auto t : bgmTracks)
|
||||
if (t->stream.queryState() == ALStream::Playing)
|
||||
playingTracks.push_back(t);
|
||||
|
||||
|
||||
if (playingTracks.size() <= 0 && !shouldBreak) shouldBreak = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
track->setVolume(AudioStream::External, vol);
|
||||
track->unlockStream();
|
||||
|
||||
}
|
||||
if (shouldBreak) {
|
||||
meWatch.state = MePlaying;
|
||||
me.unlockStream();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
bool shouldBreak = false;
|
||||
|
||||
for (int i = 0; i < (int)(bgmTracks.size()); i++) {
|
||||
AudioStream *track = bgmTracks[i];
|
||||
|
||||
track->lockStream();
|
||||
|
||||
float vol = track->getVolume(AudioStream::External);
|
||||
vol -= fadeOutStep;
|
||||
|
||||
if (vol < 0 || track->stream.queryState() != ALStream::Playing) {
|
||||
/* Either BGM has fully faded out, or stopped midway. -> MePlaying */
|
||||
track->setVolume(AudioStream::External, 0);
|
||||
track->stream.pause();
|
||||
track->unlockStream();
|
||||
|
||||
// check to see if there are any tracks still playing,
|
||||
// and if the last one was ended this round, this branch should exit
|
||||
std::vector<AudioStream*> playingTracks;
|
||||
for (auto t : bgmTracks)
|
||||
if (t->stream.queryState() == ALStream::Playing)
|
||||
playingTracks.push_back(t);
|
||||
|
||||
|
||||
if (playingTracks.size() <= 0 && !shouldBreak) shouldBreak = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
track->setVolume(AudioStream::External, vol);
|
||||
track->unlockStream();
|
||||
}
|
||||
|
||||
if (shouldBreak) {
|
||||
meWatch.state = MePlaying;
|
||||
me.unlockStream();
|
||||
break;
|
||||
}
|
||||
|
||||
me.unlockStream();
|
||||
|
||||
break;
|
||||
|
@ -215,51 +212,51 @@ struct AudioPrivate
|
|||
me.lockStream();
|
||||
|
||||
if (me.stream.queryState() != ALStream::Playing)
|
||||
{
|
||||
/* ME has ended */
|
||||
for (auto track : bgmTracks) {
|
||||
track->lockStream();
|
||||
track->extPaused = false;
|
||||
|
||||
ALStream::State sState = track->stream.queryState();
|
||||
|
||||
if (sState == ALStream::Paused) {
|
||||
/* BGM is paused. -> FadeInBGM */
|
||||
track->stream.play();
|
||||
meWatch.state = BgmFadingIn;
|
||||
}
|
||||
else {
|
||||
/* BGM is stopped. -> MeNotPlaying */
|
||||
track->setVolume(AudioStream::External, 1.0f);
|
||||
|
||||
if (!track->noResumeStop)
|
||||
track->stream.play();
|
||||
|
||||
meWatch.state = MeNotPlaying;
|
||||
}
|
||||
|
||||
track->unlockStream();
|
||||
}
|
||||
{
|
||||
/* ME has ended */
|
||||
for (auto track : bgmTracks) {
|
||||
track->lockStream();
|
||||
track->extPaused = false;
|
||||
|
||||
ALStream::State sState = track->stream.queryState();
|
||||
|
||||
if (sState == ALStream::Paused) {
|
||||
/* BGM is paused. -> FadeInBGM */
|
||||
track->stream.play();
|
||||
meWatch.state = BgmFadingIn;
|
||||
}
|
||||
else {
|
||||
/* BGM is stopped. -> MeNotPlaying */
|
||||
track->setVolume(AudioStream::External, 1.0f);
|
||||
|
||||
if (!track->noResumeStop)
|
||||
track->stream.play();
|
||||
|
||||
meWatch.state = MeNotPlaying;
|
||||
}
|
||||
|
||||
track->unlockStream();
|
||||
}
|
||||
}
|
||||
|
||||
me.unlockStream();
|
||||
me.unlockStream();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BgmFadingIn :
|
||||
{
|
||||
for (auto track : bgmTracks)
|
||||
track->lockStream();
|
||||
for (auto track : bgmTracks)
|
||||
track->lockStream();
|
||||
|
||||
if (bgmTracks[0]->stream.queryState() == ALStream::Stopped)
|
||||
{
|
||||
/* BGM stopped midway fade in. -> MeNotPlaying */
|
||||
for (auto track : bgmTracks)
|
||||
track->setVolume(AudioStream::External, 1.0f);
|
||||
for (auto track : bgmTracks)
|
||||
track->setVolume(AudioStream::External, 1.0f);
|
||||
meWatch.state = MeNotPlaying;
|
||||
for (auto track : bgmTracks)
|
||||
track->unlockStream();
|
||||
for (auto track : bgmTracks)
|
||||
track->unlockStream();
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -269,12 +266,12 @@ struct AudioPrivate
|
|||
if (me.stream.queryState() == ALStream::Playing)
|
||||
{
|
||||
/* ME started playing midway BGM fade in. -> FadeOutBGM */
|
||||
for (auto track : bgmTracks)
|
||||
track->extPaused = true;
|
||||
for (auto track : bgmTracks)
|
||||
track->extPaused = true;
|
||||
meWatch.state = BgmFadingOut;
|
||||
me.unlockStream();
|
||||
for (auto track : bgmTracks)
|
||||
track->unlockStream();
|
||||
for (auto track : bgmTracks)
|
||||
track->unlockStream();
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -289,16 +286,29 @@ struct AudioPrivate
|
|||
meWatch.state = MeNotPlaying;
|
||||
}
|
||||
|
||||
for (auto track : bgmTracks)
|
||||
track->setVolume(AudioStream::External, vol);
|
||||
for (auto track : bgmTracks)
|
||||
track->setVolume(AudioStream::External, vol);
|
||||
|
||||
me.unlockStream();
|
||||
for (auto track : bgmTracks)
|
||||
track->unlockStream();
|
||||
for (auto track : bgmTracks)
|
||||
track->unlockStream();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
void meWatchThread()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
syncPoint.passSecondarySync();
|
||||
|
||||
if (meWatch.termReq)
|
||||
return;
|
||||
|
||||
meWatchProc();
|
||||
|
||||
SDL_Delay(AUDIO_SLEEP);
|
||||
}
|
||||
|
@ -318,13 +328,14 @@ Audio::Audio(RGSSThreadData &rtData)
|
|||
|
||||
#ifdef MKXPZ_RETRO
|
||||
void Audio::render() {
|
||||
p->meWatchProc();
|
||||
for (int i = 0; i < (int)p->bgmTracks.size(); i++) {
|
||||
p->bgmTracks[i]->stream.render();
|
||||
p->bgmTracks[i]->render();
|
||||
}
|
||||
p->bgs.stream.render();
|
||||
p->me.stream.render();
|
||||
p->bgs.render();
|
||||
p->me.render();
|
||||
}
|
||||
#endif
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
void Audio::bgmPlay(const char *filename,
|
||||
int volume,
|
||||
|
@ -464,9 +475,7 @@ void Audio::reset()
|
|||
|
||||
p->bgs.stop();
|
||||
p->me.stop();
|
||||
#ifndef MKXPZ_RETRO
|
||||
p->se.stop();
|
||||
#endif // MKXPZ_RETRO
|
||||
}
|
||||
|
||||
Audio::~Audio() { delete p; }
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
#include "util.h"
|
||||
#include "exception.h"
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
#ifdef MKXPZ_RETRO
|
||||
# include "core.h"
|
||||
#else
|
||||
# include <SDL_mutex.h>
|
||||
# include <SDL_thread.h>
|
||||
# include <SDL_timer.h>
|
||||
|
@ -42,7 +44,10 @@ AudioStream::AudioStream(ALStream::LoopMode loopMode,
|
|||
for (size_t i = 0; i < VolumeTypeCount; ++i)
|
||||
volumes[i] = 1.0f;
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
#ifdef MKXPZ_RETRO
|
||||
fade.enabled = false;
|
||||
fadeIn.enabled = false;
|
||||
#else
|
||||
fade.thread = 0;
|
||||
fade.threadName = std::string("audio_fadeout (") + threadId + ")";
|
||||
|
||||
|
@ -184,14 +189,12 @@ void AudioStream::fadeOut(int duration)
|
|||
ALStream::State sState = stream.queryState();
|
||||
noResumeStop = true;
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
if (fade.active)
|
||||
{
|
||||
unlockStream();
|
||||
|
||||
return;
|
||||
}
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
if (sState == ALStream::Paused)
|
||||
{
|
||||
|
@ -208,20 +211,34 @@ void AudioStream::fadeOut(int duration)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
#ifdef MKXPZ_RETRO
|
||||
if (fade.enabled)
|
||||
#else
|
||||
if (fade.thread)
|
||||
#endif // MKXPZ_RETRO
|
||||
{
|
||||
fade.reqFini.set();
|
||||
fadeOutProc();
|
||||
fade.enabled = false;
|
||||
#ifndef MKXPZ_RETRO
|
||||
SDL_WaitThread(fade.thread, 0);
|
||||
fade.thread = 0;
|
||||
#endif // MKXPZ_RETRO
|
||||
}
|
||||
|
||||
fade.active.set();
|
||||
fade.msStep = 1.0f / duration;
|
||||
fade.reqFini.clear();
|
||||
fade.reqTerm.clear();
|
||||
#ifdef MKXPZ_RETRO
|
||||
fade.startTicks = mkxp_retro::get_ticks();
|
||||
#else
|
||||
fade.startTicks = SDL_GetTicks64();
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
fade.enabled = true;
|
||||
#else
|
||||
fade.thread = createSDLThread
|
||||
<AudioStream, &AudioStream::fadeOutThread>(this, fade.threadName);
|
||||
#endif // MKXPZ_RETRO
|
||||
|
@ -281,107 +298,158 @@ void AudioStream::updateVolume()
|
|||
|
||||
void AudioStream::finiFadeOutInt()
|
||||
{
|
||||
#ifndef MKXPZ_RETRO
|
||||
#ifdef MKXPZ_RETRO
|
||||
if (fade.enabled)
|
||||
#else
|
||||
if (fade.thread)
|
||||
#endif // MKXPZ_RETRO
|
||||
{
|
||||
fade.reqFini.set();
|
||||
fadeOutProc();
|
||||
fade.enabled = false;
|
||||
#ifndef MKXPZ_RETRO
|
||||
SDL_WaitThread(fade.thread, 0);
|
||||
fade.thread = 0;
|
||||
#endif // MKXPZ_RETRO
|
||||
}
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
if (fadeIn.enabled)
|
||||
#else
|
||||
if (fadeIn.thread)
|
||||
#endif // MKXPZ_RETRO
|
||||
{
|
||||
fadeIn.rqFini.set();
|
||||
fadeInProc();
|
||||
fadeIn.enabled = false;
|
||||
#ifndef MKXPZ_RETRO
|
||||
SDL_WaitThread(fadeIn.thread, 0);
|
||||
fadeIn.thread = 0;
|
||||
}
|
||||
#endif // MKXPZ_RETRO
|
||||
}
|
||||
}
|
||||
|
||||
void AudioStream::startFadeIn()
|
||||
{
|
||||
#ifndef MKXPZ_RETRO
|
||||
/* Previous fadein should always be terminated in play() */
|
||||
#ifdef MKXPZ_RETRO
|
||||
assert(!fadeIn.enabled);
|
||||
#else
|
||||
assert(!fadeIn.thread);
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
fadeIn.rqFini.clear();
|
||||
fadeIn.rqTerm.clear();
|
||||
#ifdef MKXPZ_RETRO
|
||||
fadeIn.startTicks = mkxp_retro::get_ticks();
|
||||
#else
|
||||
fadeIn.startTicks = SDL_GetTicks64();
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
fadeIn.enabled = true;
|
||||
#else
|
||||
fadeIn.thread = createSDLThread
|
||||
<AudioStream, &AudioStream::fadeInThread>(this, fadeIn.threadName);
|
||||
#endif // MKXPZ_RETRO
|
||||
}
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
void AudioStream::fadeOutThread()
|
||||
bool AudioStream::fadeOutProc()
|
||||
{
|
||||
while (true)
|
||||
/* Just immediately terminate on request */
|
||||
if (fade.reqTerm)
|
||||
{
|
||||
/* Just immediately terminate on request */
|
||||
if (fade.reqTerm)
|
||||
break;
|
||||
|
||||
lockStream();
|
||||
|
||||
uint64_t curDur = SDL_GetTicks64() - fade.startTicks;
|
||||
float resVol = 1.0f - (curDur*fade.msStep);
|
||||
|
||||
ALStream::State state = stream.queryState();
|
||||
|
||||
if (state != ALStream::Playing
|
||||
|| resVol < 0
|
||||
|| fade.reqFini)
|
||||
{
|
||||
if (state != ALStream::Paused)
|
||||
stream.stop();
|
||||
|
||||
setVolume(FadeOut, 1.0f);
|
||||
unlockStream();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
setVolume(FadeOut, resVol);
|
||||
|
||||
unlockStream();
|
||||
|
||||
SDL_Delay(AUDIO_SLEEP);
|
||||
fade.active.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
fade.active.clear();
|
||||
lockStream();
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
uint64_t curDur = mkxp_retro::get_ticks() - fade.startTicks;
|
||||
#else
|
||||
uint64_t curDur = SDL_GetTicks64() - fade.startTicks;
|
||||
#endif // MKXPZ_RETRO
|
||||
float resVol = 1.0f - (curDur*fade.msStep);
|
||||
|
||||
ALStream::State state = stream.queryState();
|
||||
|
||||
if (state != ALStream::Playing
|
||||
|| resVol < 0
|
||||
|| fade.reqFini)
|
||||
{
|
||||
if (state != ALStream::Paused)
|
||||
stream.stop();
|
||||
|
||||
setVolume(FadeOut, 1.0f);
|
||||
unlockStream();
|
||||
|
||||
fade.active.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
setVolume(FadeOut, resVol);
|
||||
|
||||
unlockStream();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioStream::fadeInProc()
|
||||
{
|
||||
if (fadeIn.rqTerm)
|
||||
return false;
|
||||
|
||||
lockStream();
|
||||
|
||||
/* Fade in duration is always 1 second */
|
||||
#ifdef MKXPZ_RETRO
|
||||
uint64_t cur = mkxp_retro::get_ticks() - fadeIn.startTicks;
|
||||
#else
|
||||
uint64_t cur = SDL_GetTicks64() - fadeIn.startTicks;
|
||||
#endif // MKXPZ_RETRO
|
||||
float prog = cur / 1000.0f;
|
||||
|
||||
ALStream::State state = stream.queryState();
|
||||
|
||||
if (state != ALStream::Playing
|
||||
|| prog >= 1.0f
|
||||
|| fadeIn.rqFini)
|
||||
{
|
||||
setVolume(FadeIn, 1.0f);
|
||||
unlockStream();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
setVolume(FadeIn, prog);
|
||||
|
||||
unlockStream();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
void AudioStream::render()
|
||||
{
|
||||
if (fade.enabled && !fadeOutProc())
|
||||
fade.enabled = false;
|
||||
|
||||
if (fadeIn.enabled && !fadeInProc())
|
||||
fadeIn.enabled = false;
|
||||
|
||||
stream.render();
|
||||
}
|
||||
#else
|
||||
void AudioStream::fadeOutThread()
|
||||
{
|
||||
while (fadeOutProc())
|
||||
SDL_Delay(AUDIO_SLEEP);
|
||||
}
|
||||
|
||||
void AudioStream::fadeInThread()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (fadeIn.rqTerm)
|
||||
break;
|
||||
|
||||
lockStream();
|
||||
|
||||
/* Fade in duration is always 1 second */
|
||||
uint64_t cur = SDL_GetTicks64() - fadeIn.startTicks;
|
||||
float prog = cur / 1000.0f;
|
||||
|
||||
ALStream::State state = stream.queryState();
|
||||
|
||||
if (state != ALStream::Playing
|
||||
|| prog >= 1.0f
|
||||
|| fadeIn.rqFini)
|
||||
{
|
||||
setVolume(FadeIn, 1.0f);
|
||||
unlockStream();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
setVolume(FadeIn, prog);
|
||||
|
||||
unlockStream();
|
||||
|
||||
while (fadeInProc())
|
||||
SDL_Delay(AUDIO_SLEEP);
|
||||
}
|
||||
}
|
||||
#endif // MKXPZ_RETRO
|
||||
|
|
|
@ -84,6 +84,7 @@ struct AudioStream
|
|||
|
||||
#ifndef MKXPZ_RETRO
|
||||
SDL_mutex *streamMut;
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
/* Fade out */
|
||||
struct
|
||||
|
@ -99,8 +100,12 @@ struct AudioStream
|
|||
* immediately */
|
||||
AtomicFlag reqTerm;
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
bool enabled;
|
||||
#else
|
||||
SDL_Thread *thread;
|
||||
std::string threadName;
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
/* Amount of reduced absolute volume
|
||||
* per ms of fade time */
|
||||
|
@ -116,12 +121,15 @@ struct AudioStream
|
|||
AtomicFlag rqFini;
|
||||
AtomicFlag rqTerm;
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
bool enabled;
|
||||
#else
|
||||
SDL_Thread *thread;
|
||||
std::string threadName;
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
uint64_t startTicks;
|
||||
} fadeIn;
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
AudioStream(ALStream::LoopMode loopMode,
|
||||
const std::string &threadId);
|
||||
|
@ -146,6 +154,10 @@ struct AudioStream
|
|||
|
||||
double playingOffset();
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
void render();
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
private:
|
||||
float volumes[VolumeTypeCount];
|
||||
void updateVolume();
|
||||
|
@ -153,6 +165,9 @@ private:
|
|||
void finiFadeOutInt();
|
||||
void startFadeIn();
|
||||
|
||||
bool fadeOutProc();
|
||||
bool fadeInProc();
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
void fadeOutThread();
|
||||
void fadeInThread();
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
using namespace mkxp_retro;
|
||||
using namespace mkxp_sandbox;
|
||||
|
||||
static uint64_t frame_count;
|
||||
|
||||
namespace mkxp_retro {
|
||||
retro_log_printf_t log_printf;
|
||||
retro_video_refresh_t video_refresh;
|
||||
|
@ -52,6 +54,10 @@ namespace mkxp_retro {
|
|||
retro_input_state_t input_state;
|
||||
struct retro_perf_callback perf;
|
||||
retro_hw_render_callback hw_render;
|
||||
|
||||
uint64_t get_ticks() noexcept {
|
||||
return (frame_count * 1000) / 60;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void *malloc_align(size_t alignment, size_t size) {
|
||||
|
@ -314,6 +320,7 @@ static bool init_sandbox() {
|
|||
return false;
|
||||
}
|
||||
|
||||
frame_count = 0;
|
||||
shared_state_initialized = false;
|
||||
|
||||
return true;
|
||||
|
@ -469,6 +476,8 @@ extern "C" RETRO_API void retro_run() {
|
|||
alcRenderSamplesSOFT(al_device, sound_buf, 735);
|
||||
audio_sample_batch(sound_buf, 735);
|
||||
}
|
||||
|
||||
++frame_count;
|
||||
}
|
||||
|
||||
extern "C" RETRO_API size_t retro_serialize_size() {
|
||||
|
|
Loading…
Add table
Reference in a new issue