Deallocation fixes and simplification

This commit is contained in:
Jack Andersen 2016-05-16 12:13:24 -10:00
parent 531961be78
commit 2192d45da1
7 changed files with 65 additions and 28 deletions

View File

@ -48,6 +48,7 @@ class Engine
std::list<std::shared_ptr<Voice>>::iterator _destroyVoice(Voice* voice); std::list<std::shared_ptr<Voice>>::iterator _destroyVoice(Voice* voice);
std::list<std::shared_ptr<Sequencer>>::iterator _destroySequencer(Sequencer* sequencer); std::list<std::shared_ptr<Sequencer>>::iterator _destroySequencer(Sequencer* sequencer);
std::list<Submix>::iterator _destroySubmix(Submix* smx); std::list<Submix>::iterator _destroySubmix(Submix* smx);
std::list<Submix>::iterator _removeSubmix(Submix* smx);
void _bringOutYourDead(); void _bringOutYourDead();
public: public:
~Engine(); ~Engine();

View File

@ -30,8 +30,8 @@ class Entity
* but shared_ptrs are issued to the client so it can safely track state */ * but shared_ptrs are issued to the client so it can safely track state */
friend class Engine; friend class Engine;
friend class SoundMacroState; friend class SoundMacroState;
bool m_destroyed = false;
protected: protected:
bool m_destroyed = false;
void _destroy() void _destroy()
{ {
#ifndef NDEBUG #ifndef NDEBUG

View File

@ -26,9 +26,6 @@ class Submix
Submix* m_submix = nullptr; /**< Parent submix of this submix (or NULL if mixing to main output) */ Submix* m_submix = nullptr; /**< Parent submix of this submix (or NULL if mixing to main output) */
std::list<Submix>::iterator m_engineIt; /**< Iterator to self within Engine's list for quick deletion */ std::list<Submix>::iterator m_engineIt; /**< Iterator to self within Engine's list for quick deletion */
std::unique_ptr<IBackendSubmix> m_backendSubmix; /**< Handle to client-implemented backend submix */ std::unique_ptr<IBackendSubmix> m_backendSubmix; /**< Handle to client-implemented backend submix */
std::unordered_set<Voice*> m_activeVoices; /**< Secondary index of Voices within Submix */
std::unordered_set<Sequencer*> m_activeSequencers; /**< Secondary index of Sequencers within Submix */
std::unordered_set<Submix*> m_activeSubmixes; /**< Secondary index of Submixes within Submix */
std::vector<std::unique_ptr<EffectBaseTypeless>> m_effectStack; /**< Ordered list of effects to apply to submix */ std::vector<std::unique_ptr<EffectBaseTypeless>> m_effectStack; /**< Ordered list of effects to apply to submix */
bool m_destroyed = false; bool m_destroyed = false;
void _destroy(); void _destroy();

View File

@ -11,7 +11,17 @@
namespace amuse namespace amuse
{ {
Engine::~Engine() {} Engine::~Engine()
{
while (m_activeSubmixes.size())
removeSubmix(&m_activeSubmixes.front());
for (std::shared_ptr<Emitter>& emitter : m_activeEmitters)
emitter->_destroy();
for (std::shared_ptr<Voice>& vox : m_activeVoices)
vox->_destroy();
for (std::shared_ptr<Sequencer>& seq : m_activeSequencers)
seq->_destroy();
}
Engine::Engine(IBackendVoiceAllocator& backend) Engine::Engine(IBackendVoiceAllocator& backend)
: m_backend(backend) : m_backend(backend)
@ -75,6 +85,8 @@ std::list<std::shared_ptr<Voice>>::iterator Engine::_destroyVoice(Voice* voice)
#ifndef NDEBUG #ifndef NDEBUG
assert(this == &voice->getEngine()); assert(this == &voice->getEngine());
#endif #endif
if (voice->m_destroyed)
return m_activeVoices.begin();
voice->_destroy(); voice->_destroy();
return m_activeVoices.erase(voice->m_engineIt); return m_activeVoices.erase(voice->m_engineIt);
} }
@ -84,6 +96,8 @@ std::list<std::shared_ptr<Sequencer>>::iterator Engine::_destroySequencer(Sequen
#ifndef NDEBUG #ifndef NDEBUG
assert(this == &sequencer->getEngine()); assert(this == &sequencer->getEngine());
#endif #endif
if (sequencer->m_destroyed)
return m_activeSequencers.begin();
sequencer->_destroy(); sequencer->_destroy();
return m_activeSequencers.erase(sequencer->m_engineIt); return m_activeSequencers.erase(sequencer->m_engineIt);
} }
@ -93,6 +107,8 @@ std::list<Submix>::iterator Engine::_destroySubmix(Submix* smx)
#ifndef NDEBUG #ifndef NDEBUG
assert(this == &smx->getEngine()); assert(this == &smx->getEngine());
#endif #endif
if (smx->m_destroyed)
return m_activeSubmixes.begin();
smx->_destroy(); smx->_destroy();
return m_activeSubmixes.erase(smx->m_engineIt); return m_activeSubmixes.erase(smx->m_engineIt);
} }
@ -234,8 +250,7 @@ Submix* Engine::addSubmix(Submix* smx)
return _allocateSubmix(smx); return _allocateSubmix(smx);
} }
/** Remove Submix and deallocate */ std::list<Submix>::iterator Engine::_removeSubmix(Submix* smx)
void Engine::removeSubmix(Submix* smx)
{ {
/* Delete all voices bound to submix */ /* Delete all voices bound to submix */
for (auto it = m_activeVoices.begin() ; it != m_activeVoices.end() ;) for (auto it = m_activeVoices.begin() ; it != m_activeVoices.end() ;)
@ -243,7 +258,7 @@ void Engine::removeSubmix(Submix* smx)
Voice* vox = it->get(); Voice* vox = it->get();
Submix* vsmx = vox->getSubmix(); Submix* vsmx = vox->getSubmix();
if (vsmx && vsmx == smx) if (vsmx == smx)
{ {
vox->_destroy(); vox->_destroy();
it = m_activeVoices.erase(it); it = m_activeVoices.erase(it);
@ -258,7 +273,7 @@ void Engine::removeSubmix(Submix* smx)
Sequencer* seq = it->get(); Sequencer* seq = it->get();
Submix* ssmx = seq->getSubmix(); Submix* ssmx = seq->getSubmix();
if (ssmx && ssmx == smx) if (ssmx == smx)
{ {
seq->_destroy(); seq->_destroy();
it = m_activeSequencers.erase(it); it = m_activeSequencers.erase(it);
@ -271,17 +286,24 @@ void Engine::removeSubmix(Submix* smx)
for (auto it = m_activeSubmixes.begin() ; it != m_activeSubmixes.end() ;) for (auto it = m_activeSubmixes.begin() ; it != m_activeSubmixes.end() ;)
{ {
Submix* ssmx = it->getParentSubmix(); Submix* ssmx = it->getParentSubmix();
if (ssmx && ssmx == smx) if (ssmx == smx)
{ {
it->_destroy(); it = _removeSubmix(&*it);
it = m_activeSubmixes.erase(it);
continue; continue;
} }
++it; ++it;
} }
/* Delete submix */ /* Delete submix */
_destroySubmix(smx); return _destroySubmix(smx);
}
/** Remove Submix and deallocate */
void Engine::removeSubmix(Submix* smx)
{
if (!smx)
return;
_removeSubmix(smx);
} }
/** Start soundFX playing from loaded audio groups */ /** Start soundFX playing from loaded audio groups */

View File

@ -46,7 +46,20 @@ void Sequencer::_destroy()
{ {
Entity::_destroy(); Entity::_destroy();
if (m_submix) if (m_submix)
m_submix->m_activeSequencers.erase(this); {
m_engine.removeSubmix(m_submix);
m_submix = nullptr;
}
for (auto& chan : m_chanStates)
{
ChannelState& st = *chan.second;
if (st.m_submix)
{
m_engine.removeSubmix(st.m_submix);
st.m_submix = nullptr;
}
}
} }
Sequencer::~Sequencer() {} Sequencer::~Sequencer() {}
@ -58,8 +71,6 @@ Sequencer::Sequencer(Engine& engine, const AudioGroup& group, int groupId,
auto it = m_songGroup.m_midiSetups.find(setupId); auto it = m_songGroup.m_midiSetups.find(setupId);
if (it != m_songGroup.m_midiSetups.cend()) if (it != m_songGroup.m_midiSetups.cend())
m_midiSetup = it->second->data(); m_midiSetup = it->second->data();
if (m_submix)
m_submix->m_activeSequencers.insert(this);
} }
Sequencer::ChannelState::~ChannelState() Sequencer::ChannelState::~ChannelState()

View File

@ -6,16 +6,11 @@ namespace amuse
void Submix::_destroy() void Submix::_destroy()
{ {
m_destroyed = true; m_destroyed = true;
if (m_submix)
m_submix->m_activeSubmixes.erase(this);
} }
Submix::Submix(Engine& engine, Submix* smx) Submix::Submix(Engine& engine, Submix* smx)
: m_root(engine), m_submix(smx) : m_root(engine), m_submix(smx)
{ {}
if (m_submix)
m_submix->m_activeSubmixes.insert(this);
}
EffectChorus& Submix::makeChorus(uint32_t baseDelay, uint32_t variation, uint32_t period) EffectChorus& Submix::makeChorus(uint32_t baseDelay, uint32_t variation, uint32_t period)
{ {

View File

@ -15,8 +15,6 @@ namespace amuse
void Voice::_destroy() void Voice::_destroy()
{ {
Entity::_destroy(); Entity::_destroy();
if (m_submix)
m_submix->m_activeVoices.erase(this);
for (std::shared_ptr<Voice>& vox : m_childVoices) for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->_destroy(); vox->_destroy();
@ -31,16 +29,12 @@ Voice::Voice(Engine& engine, const AudioGroup& group, int groupId, int vid, bool
: Entity(engine, group, groupId), m_vid(vid), m_emitter(emitter), m_submix(smx) : Entity(engine, group, groupId), m_vid(vid), m_emitter(emitter), m_submix(smx)
{ {
//fprintf(stderr, "ALLOC %d\n", m_vid); //fprintf(stderr, "ALLOC %d\n", m_vid);
if (m_submix)
m_submix->m_activeVoices.insert(this);
} }
Voice::Voice(Engine& engine, const AudioGroup& group, int groupId, ObjectId oid, int vid, bool emitter, Submix* smx) Voice::Voice(Engine& engine, const AudioGroup& group, int groupId, ObjectId oid, int vid, bool emitter, Submix* smx)
: Entity(engine, group, groupId, oid), m_vid(vid), m_emitter(emitter), m_submix(smx) : Entity(engine, group, groupId, oid), m_vid(vid), m_emitter(emitter), m_submix(smx)
{ {
//fprintf(stderr, "ALLOC %d\n", m_vid); //fprintf(stderr, "ALLOC %d\n", m_vid);
if (m_submix)
m_submix->m_activeVoices.insert(this);
} }
void Voice::_reset() void Voice::_reset()
@ -197,6 +191,9 @@ std::shared_ptr<Voice> Voice::_allocateVoice(double sampleRate, bool dynamicPitc
std::list<std::shared_ptr<Voice>>::iterator Voice::_destroyVoice(Voice* voice) std::list<std::shared_ptr<Voice>>::iterator Voice::_destroyVoice(Voice* voice)
{ {
if (voice->m_destroyed)
return m_childVoices.begin();
voice->_destroy(); voice->_destroy();
return m_childVoices.erase(voice->m_engineIt); return m_childVoices.erase(voice->m_engineIt);
} }
@ -644,16 +641,22 @@ void Voice::stopSample()
void Voice::setVolume(float vol) void Voice::setVolume(float vol)
{ {
m_userVol = clamp(0.f, vol, 1.f); m_userVol = clamp(0.f, vol, 1.f);
for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->setVolume(vol);
} }
void Voice::setPan(float pan) void Voice::setPan(float pan)
{ {
m_curPan = clamp(-1.f, pan, 1.f); m_curPan = clamp(-1.f, pan, 1.f);
for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->setPan(pan);
} }
void Voice::setSurroundPan(float span) void Voice::setSurroundPan(float span)
{ {
m_curSpan = clamp(-1.f, span, 1.f); m_curSpan = clamp(-1.f, span, 1.f);
for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->setSurroundPan(span);
} }
void Voice::startEnvelope(double dur, float vol, const Curve* envCurve) void Voice::startEnvelope(double dur, float vol, const Curve* envCurve)
@ -794,6 +797,9 @@ void Voice::setPitchWheel(float pitchWheel)
else else
m_pitchWheelVal = 0; m_pitchWheelVal = 0;
m_pitchDirty = true; m_pitchDirty = true;
for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->setPitchWheel(pitchWheel);
} }
void Voice::setPitchWheelRange(int8_t up, int8_t down) void Voice::setPitchWheelRange(int8_t up, int8_t down)
@ -806,6 +812,8 @@ void Voice::setPitchWheelRange(int8_t up, int8_t down)
void Voice::setAftertouch(uint8_t aftertouch) void Voice::setAftertouch(uint8_t aftertouch)
{ {
m_curAftertouch = aftertouch; m_curAftertouch = aftertouch;
for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->setAftertouch(aftertouch);
} }
void Voice::notifyCtrlChange(uint8_t ctrl, int8_t val) void Voice::notifyCtrlChange(uint8_t ctrl, int8_t val)
@ -817,6 +825,9 @@ void Voice::notifyCtrlChange(uint8_t ctrl, int8_t val)
else else
setPedal(false); setPedal(false);
} }
for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->notifyCtrlChange(ctrl, val);
} }
size_t Voice::getTotalVoices() const size_t Voice::getTotalVoices() const