From a23af16349383be647494e9ae245568cc5194eae Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sun, 26 Feb 2017 19:24:58 -1000 Subject: [PATCH] Add sequencer fade times --- driver/amuseplay.cpp | 2 +- include/amuse/Sequencer.hpp | 9 +++-- lib/Sequencer.cpp | 68 ++++++++++++++++++++++++++++++++----- 3 files changed, 67 insertions(+), 12 deletions(-) diff --git a/driver/amuseplay.cpp b/driver/amuseplay.cpp index c62c16e..dbac021 100644 --- a/driver/amuseplay.cpp +++ b/driver/amuseplay.cpp @@ -113,7 +113,7 @@ struct AppCallback : boo::IApplicationCallback m_setupId = setupId; if (m_seq) { - m_seq->stopSong(true); + m_seq->stopSong(0.f, true); m_seq->kill(); } m_seq = m_engine->seqPlay(m_groupId, setupId, nullptr); diff --git a/include/amuse/Sequencer.hpp b/include/amuse/Sequencer.hpp index e715f62..b275e57 100644 --- a/include/amuse/Sequencer.hpp +++ b/include/amuse/Sequencer.hpp @@ -40,6 +40,11 @@ class Sequencer : public Entity bool m_dieOnEnd = false; /**< Sequencer will be killed when current arrangement completes */ float m_curVol = 1.f; /**< Current volume of sequencer */ + float m_volFadeTime = 0.f; + float m_volFadeTarget = 0.f; + float m_volFadeStart = 0.f; + float m_stopFadeTime = 0.f; + float m_stopFadeBeginVol = 0.f; /** State of a single MIDI channel */ struct ChannelState @@ -135,10 +140,10 @@ public: void playSong(const unsigned char* arrData, bool dieOnEnd = true); /** Stop current MIDI arrangement */ - void stopSong(bool now = false); + void stopSong(float fadeTime = 0.f, bool now = false); /** Set total volume of sequencer */ - void setVolume(float vol); + void setVolume(float vol, float fadeTime = 0.f); /** Get current program number of channel */ int8_t getChanProgram(int8_t chanId) const; diff --git a/lib/Sequencer.cpp b/lib/Sequencer.cpp index d98f166..cc51dac 100644 --- a/lib/Sequencer.cpp +++ b/lib/Sequencer.cpp @@ -149,12 +149,45 @@ Sequencer::ChannelState::ChannelState(Sequencer& parent, uint8_t chanId) : m_par void Sequencer::advance(double dt) { if (m_state == SequencerState::Playing) + { + if (m_stopFadeTime) + { + float step = dt / m_stopFadeTime * m_stopFadeBeginVol; + float vol = std::max(0.f, m_curVol - step); + if (vol == 0.f) + { + m_arrData = nullptr; + m_state = SequencerState::Interactive; + allOff(true); + m_stopFadeTime = 0.f; + return; + } + else + { + setVolume(vol); + } + } + else if (m_volFadeTime) + { + float step = dt / m_volFadeTime * std::fabsf(m_volFadeTarget - m_volFadeStart); + float vol; + if (m_curVol < m_volFadeTarget) + vol = std::min(m_volFadeTarget, m_curVol + step); + else if (m_curVol >= m_volFadeTarget) + vol = std::max(m_volFadeTarget, m_curVol - step); + if (vol == m_volFadeTarget) + m_volFadeTime = 0.f; + else + setVolume(vol); + } + if (m_songState.advance(*this, dt)) { m_arrData = nullptr; m_state = SequencerState::Interactive; allOff(); } + } } size_t Sequencer::ChannelState::getVoiceCount() const @@ -536,11 +569,19 @@ void Sequencer::playSong(const unsigned char* arrData, bool dieOnEnd) m_state = SequencerState::Playing; } -void Sequencer::stopSong(bool now) +void Sequencer::stopSong(float fadeTime, bool now) { - allOff(now); - m_arrData = nullptr; - m_state = SequencerState::Interactive; + if (fadeTime == 0.f) + { + allOff(now); + m_arrData = nullptr; + m_state = SequencerState::Interactive; + } + else + { + m_stopFadeTime = fadeTime; + m_stopFadeBeginVol = m_curVol; + } } void Sequencer::ChannelState::setVolume(float vol) @@ -574,12 +615,21 @@ void Sequencer::ChannelState::setPan(float pan) } } -void Sequencer::setVolume(float vol) +void Sequencer::setVolume(float vol, float fadeTime) { - m_curVol = vol; - for (auto& chan : m_chanStates) - if (chan) - chan->setVolume(chan->m_curVol); + if (fadeTime == 0.f) + { + m_curVol = vol; + for (auto& chan : m_chanStates) + if (chan) + chan->setVolume(chan->m_curVol); + } + else + { + m_volFadeTime = fadeTime; + m_volFadeTarget = vol; + m_volFadeStart = m_curVol; + } } int8_t Sequencer::getChanProgram(int8_t chanId) const