diff --git a/driver/main.cpp b/driver/main.cpp index 229344b..888b2e9 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -204,7 +204,10 @@ struct AppCallback : boo::IApplicationCallback { m_setupId = setupId; if (m_seq) - m_seq->allOff(); + { + m_seq->stopSong(); + m_seq->kill(); + } m_seq = m_engine->seqPlay(m_groupId, setupId, nullptr); m_seq->setVolume(m_volume * VOL_FACTOR); @@ -291,7 +294,7 @@ struct AppCallback : boo::IApplicationCallback UpdateSongDisplay(); } - m_engine->pumpEngine(1.0 / 60.0); + m_engine->pumpEngine(); size_t voxCount; if (m_seq) @@ -377,7 +380,7 @@ struct AppCallback : boo::IApplicationCallback UpdateSFXDisplay(); } - m_engine->pumpEngine(1.0 / 60.0); + m_engine->pumpEngine(); if (m_vox && m_vox->state() == amuse::VoiceState::Dead) { diff --git a/include/amuse/BooBackend.hpp b/include/amuse/BooBackend.hpp index f4ae903..3502ac2 100644 --- a/include/amuse/BooBackend.hpp +++ b/include/amuse/BooBackend.hpp @@ -69,6 +69,7 @@ public: BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine); std::unique_ptr allocateVoice(Voice& clientVox, double sampleRate, bool dynamicPitch); std::unique_ptr allocateSubmix(Submix& clientSmx); + void register5MsCallback(std::function&& callback); AudioChannelSet getAvailableSet(); void pumpAndMixVoices(); }; diff --git a/include/amuse/Engine.hpp b/include/amuse/Engine.hpp index 7c00d9f..05c11dc 100644 --- a/include/amuse/Engine.hpp +++ b/include/amuse/Engine.hpp @@ -50,6 +50,7 @@ class Engine std::list::iterator _destroySubmix(Submix* smx); std::list::iterator _removeSubmix(Submix* smx); void _bringOutYourDead(); + void _5MsCallback(double dt); public: ~Engine(); Engine(IBackendVoiceAllocator& backend); @@ -58,7 +59,7 @@ public: IBackendVoiceAllocator& getBackend() {return m_backend;} /** Update all active audio entities and fill OS audio buffers as needed */ - void pumpEngine(double dt); + void pumpEngine(); /** Add audio group data pointers to engine; must remain resident! */ const AudioGroup* addAudioGroup(const AudioGroupData& data); diff --git a/include/amuse/Envelope.hpp b/include/amuse/Envelope.hpp index 2cbc6ed..5f2fbf5 100644 --- a/include/amuse/Envelope.hpp +++ b/include/amuse/Envelope.hpp @@ -24,8 +24,8 @@ private: double m_decayTime = 0.0; /**< Time of decay in seconds */ double m_sustainFactor = 1.0; /**< Evaluated sustain percentage */ double m_releaseTime = 0.0; /**< Time of release in seconds */ - double m_releaseStartFactor; /**< Level at whenever release event occurs */ - double m_curTime; /**< Current time of envelope stage in seconds */ + double m_releaseStartFactor = 0.0; /**< Level at whenever release event occurs */ + double m_curTime = 0.0; /**< Current time of envelope stage in seconds */ public: void reset(const ADSR* adsr); void reset(const ADSRDLS* adsr, int8_t note, int8_t vel); diff --git a/include/amuse/IBackendVoiceAllocator.hpp b/include/amuse/IBackendVoiceAllocator.hpp index 8283573..632ea67 100644 --- a/include/amuse/IBackendVoiceAllocator.hpp +++ b/include/amuse/IBackendVoiceAllocator.hpp @@ -2,6 +2,7 @@ #define __AMUSE_IBACKENDVOICEALLOCATOR_HPP__ #include +#include namespace amuse { @@ -39,6 +40,9 @@ public: /** Amuse flushes voice samples to the backend this way */ virtual void pumpAndMixVoices()=0; + + /** Amuse may request callbacks 200-updates-per-second virtually */ + virtual void register5MsCallback(std::function&& callback)=0; }; } diff --git a/include/amuse/Sequencer.hpp b/include/amuse/Sequencer.hpp index 610503a..90ad721 100644 --- a/include/amuse/Sequencer.hpp +++ b/include/amuse/Sequencer.hpp @@ -127,6 +127,9 @@ public: /** Play MIDI arrangement */ void playSong(const unsigned char* arrData, bool dieOnEnd=true); + /** Stop current MIDI arrangement */ + void stopSong(bool now=false); + /** Set total volume of sequencer */ void setVolume(float vol); diff --git a/lib/BooBackend.cpp b/lib/BooBackend.cpp index 72d1c5c..df1926c 100644 --- a/lib/BooBackend.cpp +++ b/lib/BooBackend.cpp @@ -115,6 +115,11 @@ std::unique_ptr BooBackendVoiceAllocator::allocateSubmix(Submix& return std::make_unique(m_booEngine, clientSmx); } +void BooBackendVoiceAllocator::register5MsCallback(std::function&& callback) +{ + m_booEngine.register5MsCallback(std::move(callback)); +} + AudioChannelSet BooBackendVoiceAllocator::getAvailableSet() { return AudioChannelSet(m_booEngine.getAvailableSet()); diff --git a/lib/Engine.cpp b/lib/Engine.cpp index 49dc825..5f94c7d 100644 --- a/lib/Engine.cpp +++ b/lib/Engine.cpp @@ -25,7 +25,9 @@ Engine::~Engine() Engine::Engine(IBackendVoiceAllocator& backend) : m_backend(backend) -{} +{ + backend.register5MsCallback(std::bind(&Engine::_5MsCallback, this, std::placeholders::_1)); +} std::pair Engine::_findSongGroup(int groupId) const { @@ -152,12 +154,15 @@ void Engine::_bringOutYourDead() } } -/** Update all active audio entities and fill OS audio buffers as needed */ -void Engine::pumpEngine(double dt) +void Engine::_5MsCallback(double dt) { for (std::shared_ptr& seq : m_activeSequencers) seq->advance(dt); +} +/** Update all active audio entities and fill OS audio buffers as needed */ +void Engine::pumpEngine() +{ m_backend.pumpAndMixVoices(); _bringOutYourDead(); @@ -321,7 +326,8 @@ std::shared_ptr Engine::fxStart(int sfxId, float vol, float pan, Submix* if (!grp) return nullptr; - std::shared_ptr ret = _allocateVoice(*grp, std::get<1>(search->second), 32000.0, true, false, smx); + std::shared_ptr ret = _allocateVoice(*grp, std::get<1>(search->second), + 32000.0, true, false, smx); if (!ret->loadSoundObject(SBig(entry->objId), 0, 1000.f, entry->defKey, entry->defVel, 0)) { _destroyVoice(ret.get()); @@ -345,7 +351,8 @@ std::shared_ptr Engine::addEmitter(const Vector3f& pos, const Vector3f& if (!grp) return nullptr; - std::shared_ptr vox = _allocateVoice(*grp, std::get<1>(search->second), 32000.0, true, true, smx); + std::shared_ptr vox = _allocateVoice(*grp, std::get<1>(search->second), + 32000.0, true, true, smx); m_activeEmitters.emplace(m_activeEmitters.end(), new Emitter(*this, *grp, std::move(vox))); Emitter& ret = *m_activeEmitters.back(); if (!ret.getVoice()->loadSoundObject(entry->objId, 0, 1000.f, entry->defKey, entry->defVel, 0)) diff --git a/lib/Sequencer.cpp b/lib/Sequencer.cpp index 8003357..dc3c013 100644 --- a/lib/Sequencer.cpp +++ b/lib/Sequencer.cpp @@ -409,6 +409,13 @@ void Sequencer::playSong(const unsigned char* arrData, bool dieOnEnd) m_state = SequencerState::Playing; } +void Sequencer::stopSong(bool now) +{ + allOff(now); + m_arrData = nullptr; + m_state = SequencerState::Interactive; +} + void Sequencer::ChannelState::setVolume(float vol) { m_curVol = vol; diff --git a/lib/SongState.cpp b/lib/SongState.cpp index 37b3b37..749fa34 100644 --- a/lib/SongState.cpp +++ b/lib/SongState.cpp @@ -190,7 +190,7 @@ bool SongState::Channel::advance(Sequencer& seq, int32_t ticks) m_lastPitchTick = nextTick; remPitchTicks -= (nextTick - pitchTick); pitchTick = nextTick; - seq.setPitchWheel(m_midiChan, clamp(-1.f, m_lastPitchVal / 8192.f, 1.f)); + seq.setPitchWheel(m_midiChan, clamp(-1.f, m_lastPitchVal / 32768.f, 1.f)); continue; } remPitchTicks -= (nextTick - pitchTick); diff --git a/lib/Voice.cpp b/lib/Voice.cpp index 0a01a5c..dc54120 100644 --- a/lib/Voice.cpp +++ b/lib/Voice.cpp @@ -224,7 +224,8 @@ bool Voice::_advanceSample(int16_t& samp, int32_t& newPitch) } /* Factor in ADSR envelope state */ - float totalVol = m_userVol * m_curVol * m_volAdsr.nextSample(m_sampleRate) * (m_state.m_curVel / 127.f); + float adsr = m_volAdsr.nextSample(m_sampleRate); + float totalVol = m_userVol * m_curVol * adsr * (m_state.m_curVel / 127.f); /* Apply tremolo */ if (m_state.m_tremoloSel && (m_tremoloScale || m_tremoloModScale))