From 4356397f407d4bacafda410d7f8b37d493bad1c3 Mon Sep 17 00:00:00 2001 From: casey langen Date: Sat, 24 Dec 2016 14:08:28 -0800 Subject: [PATCH] Fixed the CrossfadeTransport to work properly with muted streams -- or streams that become muted during the fading process. --- src/core/audio/CrossfadeTransport.cpp | 21 +++++-- src/core/audio/Crossfader.cpp | 89 ++++++++++++++++----------- src/core/audio/Crossfader.h | 3 +- 3 files changed, 71 insertions(+), 42 deletions(-) diff --git a/src/core/audio/CrossfadeTransport.cpp b/src/core/audio/CrossfadeTransport.cpp index 9f4f7596e..2f8de3a14 100644 --- a/src/core/audio/CrossfadeTransport.cpp +++ b/src/core/audio/CrossfadeTransport.cpp @@ -40,7 +40,7 @@ #include #include -#define CROSSFADE_DURATION_MS 1250 +#define CROSSFADE_DURATION_MS 3000 #define END_OF_TRACK_MIXPOINT 1001 using namespace musik::core::audio; @@ -168,11 +168,22 @@ bool CrossfadeTransport::IsMuted() { void CrossfadeTransport::SetMuted(bool muted) { if (this->muted != muted) { this->muted = muted; - this->active.SetVolume(muted ? 0.0f : this->volume); - this->next.SetVolume(muted ? 0.0f : this->volume); - if (muted) { // TODO FIXME - this->crossfader.Reset(); + /* unconditionally set the volume to zero when we mute. */ + if (muted) { + this->active.SetVolume(0.0f); + this->next.SetVolume(0.0f); + } + /* if we're no longer muted, and the streams aren't currently + in the crossfader, set their volume appropriately. */ + else { + if (!crossfader.Contains(this->active.player)) { + this->active.SetVolume(this->volume); + } + + if (!crossfader.Contains(this->next.player)) { + this->next.SetVolume(this->volume); + } } this->VolumeChanged(); diff --git a/src/core/audio/Crossfader.cpp b/src/core/audio/Crossfader.cpp index b83edc362..71f4351d6 100644 --- a/src/core/audio/Crossfader.cpp +++ b/src/core/audio/Crossfader.cpp @@ -54,7 +54,7 @@ using namespace musik::core::runtime; this, MESSAGE_TICK, 0, 0), TICK_TIME_MILLIS) #define LOCK(x) \ - std::unique_lock lock(x); + std::unique_lock lock(x); #define MESSAGE_QUIT 0 #define MESSAGE_TICK 1 @@ -82,15 +82,8 @@ void Crossfader::Fade( { LOCK(this->contextListLock); - bool exists = std::any_of( - this->contextList.begin(), - this->contextList.end(), - [player](FadeContextPtr context) { - return (context->player == player); - }); - /* don't add the same player more than once! */ - if (!exists) { + if (!this->Contains(player)) { std::shared_ptr context = std::make_shared(); context->output = output; context->player = player; @@ -133,26 +126,45 @@ void Crossfader::Stop() { } void Crossfader::OnPlayerDestroyed(Player* player) { - LOCK(this->contextListLock); + if (player) { + LOCK(this->contextListLock); - std::for_each( - this->contextList.begin(), - this->contextList.end(), - [player](FadeContextPtr context) { - if (context->player == player) { - context->player = nullptr; - } - }); + std::for_each( + this->contextList.begin(), + this->contextList.end(), + [player](FadeContextPtr context) { + if (context->player == player) { + context->player = nullptr; + } + }); + } } void Crossfader::Cancel(Player* player, Direction direction) { + if (player) { + LOCK(this->contextListLock); + + this->contextList.remove_if( + [player, direction](FadeContextPtr context) { + return + context->player == player && + context->direction == direction; + }); + } +} + +bool Crossfader::Contains(Player* player) { + if (!player) { + return false; + } + LOCK(this->contextListLock); - this->contextList.remove_if( - [player, direction](FadeContextPtr context) { - return - context->player == player && - context->direction == direction; + return std::any_of( + this->contextList.begin(), + this->contextList.end(), + [player](FadeContextPtr context) { + return player == context->player; }); } @@ -206,23 +218,28 @@ void Crossfader::ProcessMessage(IMessage &message) { if (fade->ticksCounted < fade->ticksTotal) { ++fade->ticksCounted; - double percent = - (float)fade->ticksCounted / - (float)fade->ticksTotal; - - if (fade->direction == FadeOut) { - percent = (1.0f - percent); + if (this->transport.IsMuted()) { + fade->output->SetVolume(0.0); } + else { + double percent = + (float)fade->ticksCounted / + (float)fade->ticksTotal; - double outputVolume = globalVolume * percent; + if (fade->direction == FadeOut) { + percent = (1.0f - percent); + } -#if 0 - std::string dir = (fade->direction == FadeIn) ? "in" : "out"; - std::string dbg = boost::str(boost::format("%s %f\n") % dir % outputVolume); - OutputDebugStringA(dbg.c_str()); -#endif + double outputVolume = globalVolume * percent; - fade->output->SetVolume(outputVolume); + #if 0 + std::string dir = (fade->direction == FadeIn) ? "in" : "out"; + std::string dbg = boost::str(boost::format("%s %f\n") % dir % outputVolume); + OutputDebugStringA(dbg.c_str()); + #endif + + fade->output->SetVolume(outputVolume); + } } if (fade->ticksCounted >= fade->ticksTotal) { diff --git a/src/core/audio/Crossfader.h b/src/core/audio/Crossfader.h index c708bc7cc..ebd3742d4 100644 --- a/src/core/audio/Crossfader.h +++ b/src/core/audio/Crossfader.h @@ -69,6 +69,7 @@ namespace musik { namespace core { namespace audio { void OnPlayerDestroyed(Player* player); void Cancel(Player* player, Direction direction); + bool Contains(Player* player); void Reset(); void Pause(); @@ -88,7 +89,7 @@ namespace musik { namespace core { namespace audio { using FadeContextPtr = std::shared_ptr; - std::mutex contextListLock; + std::recursive_mutex contextListLock; std::unique_ptr thread; musik::core::runtime::MessageQueue messageQueue; std::list contextList;