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<Sequencer>>::iterator _destroySequencer(Sequencer* sequencer);
std::list<Submix>::iterator _destroySubmix(Submix* smx);
std::list<Submix>::iterator _removeSubmix(Submix* smx);
void _bringOutYourDead();
public:
~Engine();

View File

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

View File

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

View File

@ -46,7 +46,20 @@ void Sequencer::_destroy()
{
Entity::_destroy();
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() {}
@ -58,8 +71,6 @@ Sequencer::Sequencer(Engine& engine, const AudioGroup& group, int groupId,
auto it = m_songGroup.m_midiSetups.find(setupId);
if (it != m_songGroup.m_midiSetups.cend())
m_midiSetup = it->second->data();
if (m_submix)
m_submix->m_activeSequencers.insert(this);
}
Sequencer::ChannelState::~ChannelState()

View File

@ -6,16 +6,11 @@ namespace amuse
void Submix::_destroy()
{
m_destroyed = true;
if (m_submix)
m_submix->m_activeSubmixes.erase(this);
}
Submix::Submix(Engine& engine, 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)
{

View File

@ -15,8 +15,6 @@ namespace amuse
void Voice::_destroy()
{
Entity::_destroy();
if (m_submix)
m_submix->m_activeVoices.erase(this);
for (std::shared_ptr<Voice>& vox : m_childVoices)
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)
{
//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)
: Entity(engine, group, groupId, oid), m_vid(vid), m_emitter(emitter), m_submix(smx)
{
//fprintf(stderr, "ALLOC %d\n", m_vid);
if (m_submix)
m_submix->m_activeVoices.insert(this);
}
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)
{
if (voice->m_destroyed)
return m_childVoices.begin();
voice->_destroy();
return m_childVoices.erase(voice->m_engineIt);
}
@ -644,16 +641,22 @@ void Voice::stopSample()
void Voice::setVolume(float vol)
{
m_userVol = clamp(0.f, vol, 1.f);
for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->setVolume(vol);
}
void Voice::setPan(float pan)
{
m_curPan = clamp(-1.f, pan, 1.f);
for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->setPan(pan);
}
void Voice::setSurroundPan(float span)
{
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)
@ -794,6 +797,9 @@ void Voice::setPitchWheel(float pitchWheel)
else
m_pitchWheelVal = 0;
m_pitchDirty = true;
for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->setPitchWheel(pitchWheel);
}
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)
{
m_curAftertouch = aftertouch;
for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->setAftertouch(aftertouch);
}
void Voice::notifyCtrlChange(uint8_t ctrl, int8_t val)
@ -817,6 +825,9 @@ void Voice::notifyCtrlChange(uint8_t ctrl, int8_t val)
else
setPedal(false);
}
for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->notifyCtrlChange(ctrl, val);
}
size_t Voice::getTotalVoices() const