From 0c8d8f571ce8143ca3d3bd6d11acd71888ade0fa Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 31 May 2016 00:16:52 -1000 Subject: [PATCH] Envelope command fixes, 20ms default envelope --- driver/main.cpp | 283 ++++++++++++++++++++----------------- include/amuse/Envelope.hpp | 4 +- lib/Engine.cpp | 7 +- lib/Envelope.cpp | 7 +- lib/Sequencer.cpp | 2 +- lib/Voice.cpp | 22 +-- 6 files changed, 182 insertions(+), 143 deletions(-) diff --git a/driver/main.cpp b/driver/main.cpp index a09f63f..060e54a 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -80,13 +80,14 @@ struct AppCallback : boo::IApplicationCallback int8_t m_lastChanProg = -1; /* Control state */ - float m_volume = 0.8f; + float m_volume = 0.5f; float m_modulation = 0.f; float m_pitchBend = 0.f; bool m_updateDisp = false; bool m_running = true; bool m_wantsNext = false; bool m_wantsPrev = false; + bool m_breakout = false; int m_panicCount = 0; void UpdateSongDisplay() @@ -219,6 +220,14 @@ struct AppCallback : boo::IApplicationCallback UpdateSongDisplay(); } + if (m_breakout) + { + m_breakout = false; + m_seq->allOff(true); + m_seq.reset(); + break; + } + m_win->waitForRetrace(); } } @@ -298,6 +307,13 @@ struct AppCallback : boo::IApplicationCallback UpdateSFXDisplay(); } + if (m_breakout) + { + m_breakout = false; + m_vox.reset(); + break; + } + m_win->waitForRetrace(); } } @@ -604,148 +620,161 @@ struct AppCallback : boo::IApplicationCallback allSFXGroups[it->first] = std::make_pair(&grp, &it->second); } - /* Attempt loading song */ - std::vector> songs; - if (m_argc > 2) + while (m_running) { - songs = amuse::ContainerRegistry::LoadSongs(m_argv[2]); + m_groupId = -1; + m_setupId = -1; - /* Get song selection from user */ - if (songs.size() > 1) + /* Attempt loading song */ + std::vector> songs; + if (m_argc > 2) { - /* Ask user to specify which song */ - printf("Multiple Songs discovered:\n"); - int idx = 0; - for (const auto& pair : songs) +#if _WIN32 + char utf8Path[1024]; + WideCharToMultiByte(CP_UTF8, 0, m_argv[2], -1, utf8Path, 1024, nullptr, nullptr); +#else + const char* utf8Path = m_argv[2]; +#endif + + songs = amuse::ContainerRegistry::LoadSongs(utf8Path); + + /* Get song selection from user */ + if (songs.size() > 1) { - printf(" %d %s (Group %d, Setup %d)\n", idx++, - pair.first.c_str(), pair.second.m_groupId, pair.second.m_setupId); + /* Ask user to specify which song */ + printf("Multiple Songs discovered:\n"); + int idx = 0; + for (const auto& pair : songs) + { + printf(" %d %s (Group %d, Setup %d)\n", idx++, + pair.first.c_str(), pair.second.m_groupId, pair.second.m_setupId); + } + + int userSel = 0; + printf("Enter Song Number: "); + if (scanf("%d", &userSel) <= 0) + Log.report(logvisor::Fatal, "unable to parse prompt"); + + if (userSel < songs.size()) + { + m_arrData = &songs[userSel].second; + m_groupId = m_arrData->m_groupId; + m_setupId = m_arrData->m_setupId; + } + else + Log.report(logvisor::Fatal, "unable to find Song %d", userSel); } - - int userSel = 0; - printf("Enter Song Number: "); - if (scanf("%d", &userSel) <= 0) - Log.report(logvisor::Fatal, "unable to parse prompt"); - - if (userSel < songs.size()) + else { - m_arrData = &songs[userSel].second; + m_arrData = &songs[0].second; m_groupId = m_arrData->m_groupId; m_setupId = m_arrData->m_setupId; } + } + + /* Get group selection from user */ + if (m_groupId != -1) + { + if (allSongGroups.find(m_groupId) != allSongGroups.end()) + m_sfxGroup = false; + else if (allSFXGroups.find(m_groupId) != allSFXGroups.end()) + m_sfxGroup = true; else - Log.report(logvisor::Fatal, "unable to find Song %d", userSel); + Log.report(logvisor::Fatal, "unable to find Group %d", m_groupId); + } + else if (totalGroups > 1) + { + /* Ask user to specify which group in project */ + printf("Multiple Audio Groups discovered:\n"); + for (const auto& pair : allSFXGroups) + { + printf(" %d %s (SFXGroup) %" PRISize " sfx-entries\n", + pair.first, pair.second.first->first.c_str(), + pair.second.second->m_sfxEntries.size()); + } + for (const auto& pair : allSongGroups) + { + printf(" %d %s (SongGroup) %" PRISize " normal-pages, %" PRISize " drum-pages\n", + pair.first, pair.second.first->first.c_str(), + pair.second.second->m_normPages.size(), pair.second.second->m_drumPages.size()); + } + + int userSel = 0; + printf("Enter Group Number: "); + if (scanf("%d", &userSel) <= 0) + Log.report(logvisor::Fatal, "unable to parse prompt"); + + if (allSongGroups.find(userSel) != allSongGroups.end()) + { + m_groupId = userSel; + m_sfxGroup = false; + } + else if (allSFXGroups.find(userSel) != allSFXGroups.end()) + { + m_groupId = userSel; + m_sfxGroup = true; + } + else + Log.report(logvisor::Fatal, "unable to find Group %d", userSel); + } + else if (totalGroups == 1) + { + /* Load one and only group */ + if (allSongGroups.size()) + { + const auto& pair = *allSongGroups.cbegin(); + m_groupId = pair.first; + m_sfxGroup = false; + } + else + { + const auto& pair = *allSFXGroups.cbegin(); + m_groupId = pair.first; + m_sfxGroup = true; + } + } + else + Log.report(logvisor::Fatal, "empty project"); + + /* Make final group selection */ + amuse::IntrusiveAudioGroupData* selData = nullptr; + const amuse::SongGroupIndex* songIndex = nullptr; + const amuse::SFXGroupIndex* sfxIndex = nullptr; + auto songSearch = allSongGroups.find(m_groupId); + if (songSearch != allSongGroups.end()) + { + selData = &songSearch->second.first->second; + songIndex = songSearch->second.second; } else { - m_arrData = &songs[0].second; - m_groupId = m_arrData->m_groupId; - m_setupId = m_arrData->m_setupId; + auto sfxSearch = allSFXGroups.find(m_groupId); + if (sfxSearch != allSFXGroups.end()) + { + selData = &sfxSearch->second.first->second; + sfxIndex = sfxSearch->second.second; + } } - } - /* Get group selection from user */ - if (m_groupId != -1) - { - if (allSongGroups.find(m_groupId) != allSongGroups.end()) - m_sfxGroup = false; - else if (allSFXGroups.find(m_groupId) != allSFXGroups.end()) - m_sfxGroup = true; + if (!selData) + Log.report(logvisor::Fatal, "unable to select audio group data"); + + /* Build voice engine */ + std::unique_ptr voxEngine = boo::NewAudioVoiceEngine(); + amuse::BooBackendVoiceAllocator booBackend(*voxEngine); + m_engine.emplace(booBackend, amuse::AmplitudeMode::PerSample); + + /* Load group into engine */ + const amuse::AudioGroup* group = m_engine->addAudioGroup(*selData); + if (!group) + Log.report(logvisor::Fatal, "unable to add audio group"); + + /* Enter playback loop */ + if (m_sfxGroup) + SFXLoop(*sfxIndex); else - Log.report(logvisor::Fatal, "unable to find Group %d", m_groupId); + SongLoop(*songIndex); } - else if (totalGroups > 1) - { - /* Ask user to specify which group in project */ - printf("Multiple Audio Groups discovered:\n"); - for (const auto& pair : allSFXGroups) - { - printf(" %d %s (SFXGroup) %" PRISize " sfx-entries\n", - pair.first, pair.second.first->first.c_str(), - pair.second.second->m_sfxEntries.size()); - } - for (const auto& pair : allSongGroups) - { - printf(" %d %s (SongGroup) %" PRISize " normal-pages, %" PRISize " drum-pages\n", - pair.first, pair.second.first->first.c_str(), - pair.second.second->m_normPages.size(), pair.second.second->m_drumPages.size()); - } - - int userSel = 0; - printf("Enter Group Number: "); - if (scanf("%d", &userSel) <= 0) - Log.report(logvisor::Fatal, "unable to parse prompt"); - - if (allSongGroups.find(userSel) != allSongGroups.end()) - { - m_groupId = userSel; - m_sfxGroup = false; - } - else if (allSFXGroups.find(userSel) != allSFXGroups.end()) - { - m_groupId = userSel; - m_sfxGroup = true; - } - else - Log.report(logvisor::Fatal, "unable to find Group %d", userSel); - } - else if (totalGroups == 1) - { - /* Load one and only group */ - if (allSongGroups.size()) - { - const auto& pair = *allSongGroups.cbegin(); - m_groupId = pair.first; - m_sfxGroup = false; - } - else - { - const auto& pair = *allSFXGroups.cbegin(); - m_groupId = pair.first; - m_sfxGroup = true; - } - } - else - Log.report(logvisor::Fatal, "empty project"); - - /* Make final group selection */ - amuse::IntrusiveAudioGroupData* selData = nullptr; - const amuse::SongGroupIndex* songIndex = nullptr; - const amuse::SFXGroupIndex* sfxIndex = nullptr; - auto songSearch = allSongGroups.find(m_groupId); - if (songSearch != allSongGroups.end()) - { - selData = &songSearch->second.first->second; - songIndex = songSearch->second.second; - } - else - { - auto sfxSearch = allSFXGroups.find(m_groupId); - if (sfxSearch != allSFXGroups.end()) - { - selData = &sfxSearch->second.first->second; - sfxIndex = sfxSearch->second.second; - } - } - - if (!selData) - Log.report(logvisor::Fatal, "unable to select audio group data"); - - /* Build voice engine */ - std::unique_ptr voxEngine = boo::NewAudioVoiceEngine(); - amuse::BooBackendVoiceAllocator booBackend(*voxEngine); - m_engine.emplace(booBackend, amuse::AmplitudeMode::BlockLinearized); - - /* Load group into engine */ - const amuse::AudioGroup* group = m_engine->addAudioGroup(*selData); - if (!group) - Log.report(logvisor::Fatal, "unable to add audio group"); - - /* Enter playback loop */ - if (m_sfxGroup) - SFXLoop(*sfxIndex); - else - SongLoop(*songIndex); return 0; } @@ -800,6 +829,8 @@ void EventCallback::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, m_app.m_seq->setVolume(m_app.m_volume); m_app.m_updateDisp = true; break; + case boo::ESpecialKey::Esc: + m_app.m_breakout = true; default: break; } } diff --git a/include/amuse/Envelope.hpp b/include/amuse/Envelope.hpp index 97b1076..79604a9 100644 --- a/include/amuse/Envelope.hpp +++ b/include/amuse/Envelope.hpp @@ -20,10 +20,10 @@ public: }; private: State m_phase = State::Attack; /**< Current envelope state */ - double m_attackTime = 0.005; /**< Time of attack in seconds */ + double m_attackTime = 0.02; /**< Time of attack in seconds */ double m_decayTime = 0.0; /**< Time of decay in seconds */ double m_sustainFactor = 1.0; /**< Evaluated sustain percentage */ - double m_releaseTime = 0.005; /**< Time of release in seconds */ + double m_releaseTime = 0.02; /**< Time of release 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: diff --git a/lib/Engine.cpp b/lib/Engine.cpp index dda8343..b945eda 100644 --- a/lib/Engine.cpp +++ b/lib/Engine.cpp @@ -13,8 +13,8 @@ namespace amuse Engine::~Engine() { - for (std::shared_ptr& seq : m_activeSequencers) - seq->_destroy(); + while (m_activeSequencers.size()) + m_activeSequencers.front()->_destroy(); while (m_activeSubmixes.size()) removeSubmix(&m_activeSubmixes.front()); for (std::shared_ptr& emitter : m_activeEmitters) @@ -308,7 +308,8 @@ std::list::iterator Engine::_removeSubmix(Submix* smx) Submix* ssmx = seq->getSubmix(); if (ssmx == smx) { - seq->_destroy(); + if (!seq->m_destroyed) + seq->_destroy(); it = m_activeSequencers.erase(it); continue; } diff --git a/lib/Envelope.cpp b/lib/Envelope.cpp index e37e029..f94cb9d 100644 --- a/lib/Envelope.cpp +++ b/lib/Envelope.cpp @@ -33,6 +33,7 @@ void Envelope::keyOff() float Envelope::advance(double dt) { + double thisTime = m_curTime; m_curTime += dt; switch (m_phase) @@ -46,7 +47,7 @@ float Envelope::advance(double dt) m_releaseStartFactor = 1.f; return 1.f; } - double attackFac = m_curTime / m_attackTime; + double attackFac = thisTime / m_attackTime; if (attackFac >= 1.0) { m_phase = State::Decay; @@ -66,7 +67,7 @@ float Envelope::advance(double dt) m_releaseStartFactor = m_sustainFactor; return m_sustainFactor; } - double decayFac = m_curTime / m_decayTime; + double decayFac = thisTime / m_decayTime; if (decayFac >= 1.0) { m_phase = State::Sustain; @@ -88,7 +89,7 @@ float Envelope::advance(double dt) m_phase = State::Complete; return 0.f; } - double releaseFac = m_curTime / m_releaseTime; + double releaseFac = thisTime / m_releaseTime; if (releaseFac >= 1.0) { m_phase = State::Complete; diff --git a/lib/Sequencer.cpp b/lib/Sequencer.cpp index c01ef6a..dcdaf4e 100644 --- a/lib/Sequencer.cpp +++ b/lib/Sequencer.cpp @@ -50,7 +50,7 @@ void Sequencer::_destroy() { m_engine.removeSubmix(m_submix); m_submix = nullptr; - } + } } Sequencer::~Sequencer() diff --git a/lib/Voice.cpp b/lib/Voice.cpp index 2af33e7..a148ceb 100644 --- a/lib/Voice.cpp +++ b/lib/Voice.cpp @@ -254,12 +254,12 @@ bool Voice::_advanceSample(int16_t& samp, int32_t& newPitch) if (m_envelopeTime >= 0.0) { m_envelopeTime += dt; - float start = m_envelopeStart / 127.f; - float end = m_envelopeEnd / 127.f; - double t = std::max(0.0, std::min(1.0, m_envelopeTime / m_envelopeDur)); + float start = m_envelopeStart; + float end = m_envelopeEnd; + float t = std::max(0.f, std::min(1.f, float(m_envelopeTime / m_envelopeDur))); if (m_envelopeCurve) t = (*m_envelopeCurve)[int(t*127.f)] / 127.f; - m_curVol = (start * (1.0f - t)) + (end * t); + m_curVol = clamp(0.f, (start * (1.0f - t)) + (end * t), 1.f); /* Done with envelope */ if (m_envelopeTime > m_envelopeDur) @@ -848,7 +848,7 @@ void Voice::setSurroundPan(float span) void Voice::startEnvelope(double dur, float vol, const Curve* envCurve) { - m_envelopeTime = m_voiceTime; + m_envelopeTime = 0.f; m_envelopeDur = dur; m_envelopeStart = clamp(0.f, m_curVol, 1.f); m_envelopeEnd = clamp(0.f, vol, 1.f); @@ -857,7 +857,7 @@ void Voice::startEnvelope(double dur, float vol, const Curve* envCurve) void Voice::startFadeIn(double dur, float vol, const Curve* envCurve) { - m_envelopeTime = m_voiceTime; + m_envelopeTime = 0.f; m_envelopeDur = dur; m_envelopeStart = 0.f; m_envelopeEnd = clamp(0.f, vol, 1.f); @@ -1018,15 +1018,21 @@ void Voice::setAftertouch(uint8_t aftertouch) void Voice::_notifyCtrlChange(uint8_t ctrl, int8_t val) { - if (ctrl == 64) + if (ctrl == 0x40) { - if (val >= 64) + if (val >= 0x40) setPedal(true); else setPedal(false); } + else if (ctrl == 0x41) + { + printf("PORTAMENTO %d\n", val); + } else if (ctrl == 0x5b) + { setReverbVol(val / 127.f); + } for (std::shared_ptr& vox : m_childVoices) vox->_notifyCtrlChange(ctrl, val);