mirror of https://github.com/AxioDL/amuse.git
More fixes, better lifetime management
This commit is contained in:
parent
ccefe60a9d
commit
2341b6b7d0
|
@ -2,6 +2,7 @@
|
|||
#define __AMUSE_EMITTER_HPP__
|
||||
|
||||
#include "Entity.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace amuse
|
||||
{
|
||||
|
@ -11,9 +12,12 @@ using Vector3f = float[3];
|
|||
|
||||
class Emitter : public Entity
|
||||
{
|
||||
Voice& m_vox;
|
||||
std::shared_ptr<Voice> m_vox;
|
||||
|
||||
friend class Engine;
|
||||
void _destroy();
|
||||
public:
|
||||
Emitter(Engine& engine, const AudioGroup& group, Voice& vox);
|
||||
Emitter(Engine& engine, const AudioGroup& group, std::shared_ptr<Voice>&& vox);
|
||||
|
||||
void setPos(const Vector3f& pos);
|
||||
void setDir(const Vector3f& dir);
|
||||
|
@ -21,6 +25,8 @@ public:
|
|||
void setMaxVol(float maxVol);
|
||||
void setMinVol(float minVol);
|
||||
void setFalloff(float falloff);
|
||||
|
||||
std::shared_ptr<Voice>& getVoice() {return m_vox;}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ class AudioGroupData;
|
|||
class Engine
|
||||
{
|
||||
friend class Voice;
|
||||
friend class Emitter;
|
||||
|
||||
IBackendVoiceAllocator& m_backend;
|
||||
std::unordered_map<int, std::unique_ptr<AudioGroup>> m_audioGroups;
|
||||
|
|
|
@ -32,7 +32,13 @@ class Entity
|
|||
friend class SoundMacroState;
|
||||
bool m_destroyed = false;
|
||||
protected:
|
||||
void _destroy() {m_destroyed = true;}
|
||||
void _destroy()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
assert(!m_destroyed);
|
||||
#endif
|
||||
m_destroyed = true;
|
||||
}
|
||||
Engine& m_engine;
|
||||
const AudioGroup& m_audioGroup;
|
||||
ObjectId m_objectId; /* if applicable */
|
||||
|
|
|
@ -19,9 +19,9 @@ class Submix;
|
|||
/** State of voice over lifetime */
|
||||
enum class VoiceState
|
||||
{
|
||||
Playing,
|
||||
KeyOff,
|
||||
Finished
|
||||
Playing, /**< SoundMacro actively executing, not in KeyOff */
|
||||
KeyOff, /**< KeyOff event issued, macro beginning fade-out */
|
||||
Finished /**< Default state, causes Engine to remove voice at end of pump cycle */
|
||||
};
|
||||
|
||||
/** Individual source of audio */
|
||||
|
@ -104,8 +104,6 @@ class Voice : public Entity
|
|||
|
||||
float m_lfoPeriods[2]; /**< time-periods for LFO1 and LFO2 */
|
||||
|
||||
bool m_dead = false; /**< sound macro has reached END, voice should be deallocated at end of update cycle */
|
||||
|
||||
void _destroy();
|
||||
void _reset();
|
||||
bool _checkSamplePos();
|
||||
|
@ -113,6 +111,7 @@ class Voice : public Entity
|
|||
bool _advanceSample(int16_t& samp);
|
||||
void _setTotalPitch(int32_t cents);
|
||||
void _bringOutYourDead();
|
||||
std::shared_ptr<Voice> _findVoice(int vid, std::weak_ptr<Voice> thisPtr);
|
||||
|
||||
std::shared_ptr<Voice> _allocateVoice(double sampleRate, bool dynamicPitch);
|
||||
std::list<std::shared_ptr<Voice>>::iterator _destroyVoice(Voice* voice);
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
#include "amuse/Emitter.hpp"
|
||||
#include "amuse/Voice.hpp"
|
||||
#include "amuse/Engine.hpp"
|
||||
|
||||
namespace amuse
|
||||
{
|
||||
|
||||
Emitter::Emitter(Engine& engine, const AudioGroup& group, Voice& vox)
|
||||
: Entity(engine, group, vox.getObjectId()), m_vox(vox)
|
||||
Emitter::Emitter(Engine& engine, const AudioGroup& group, std::shared_ptr<Voice>&& vox)
|
||||
: Entity(engine, group, vox->getObjectId()), m_vox(std::move(vox))
|
||||
{
|
||||
}
|
||||
|
||||
void Emitter::_destroy()
|
||||
{
|
||||
Entity::_destroy();
|
||||
m_engine._destroyVoice(m_vox.get());
|
||||
}
|
||||
|
||||
void Emitter::setPos(const Vector3f& pos)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -53,11 +53,21 @@ std::list<Submix>::iterator Engine::_destroySubmix(Submix* smx)
|
|||
|
||||
void Engine::_bringOutYourDead()
|
||||
{
|
||||
for (auto it = m_activeEmitters.begin() ; it != m_activeEmitters.end() ;)
|
||||
{
|
||||
Emitter* emitter = it->get();
|
||||
if (emitter->getVoice()->m_voxState == VoiceState::Finished)
|
||||
{
|
||||
emitter->_destroy();
|
||||
it = m_activeEmitters.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = m_activeVoices.begin() ; it != m_activeVoices.end() ;)
|
||||
{
|
||||
Voice* vox = it->get();
|
||||
vox->_bringOutYourDead();
|
||||
if (vox->m_dead)
|
||||
if (vox->m_voxState == VoiceState::Finished)
|
||||
{
|
||||
it = _destroyVoice(vox);
|
||||
continue;
|
||||
|
@ -209,6 +219,11 @@ std::shared_ptr<Voice> Engine::fxStart(int sfxId, float vol, float pan, Submix*
|
|||
return nullptr;
|
||||
|
||||
std::shared_ptr<Voice> ret = _allocateVoice(*grp, 32000.0, true, false, smx);
|
||||
if (!ret->loadSoundMacro(search->second.second, 0, 1000.f, 0x3c, 0, 0))
|
||||
{
|
||||
_destroyVoice(ret.get());
|
||||
return {};
|
||||
}
|
||||
ret->setVolume(vol);
|
||||
ret->setPan(pan);
|
||||
return ret;
|
||||
|
@ -227,8 +242,14 @@ std::shared_ptr<Emitter> Engine::addEmitter(const Vector3f& pos, const Vector3f&
|
|||
return nullptr;
|
||||
|
||||
std::shared_ptr<Voice> vox = _allocateVoice(*grp, 32000.0, true, true, smx);
|
||||
m_activeEmitters.emplace(m_activeEmitters.end(), new Emitter(*this, *grp, *vox));
|
||||
m_activeEmitters.emplace(m_activeEmitters.end(), new Emitter(*this, *grp, std::move(vox)));
|
||||
Emitter& ret = *m_activeEmitters.back();
|
||||
if (!ret.getVoice()->loadSoundMacro(search->second.second, 0, 1000.f, 0x3c, 0, 0))
|
||||
{
|
||||
ret._destroy();
|
||||
m_activeEmitters.pop_back();
|
||||
return {};
|
||||
}
|
||||
ret.setPos(pos);
|
||||
ret.setDir(dir);
|
||||
ret.setMaxDist(maxDist);
|
||||
|
@ -249,8 +270,11 @@ std::shared_ptr<Sequencer> Engine::seqPlay(int groupId, int songId, const unsign
|
|||
std::shared_ptr<Voice> Engine::findVoice(int vid)
|
||||
{
|
||||
for (std::shared_ptr<Voice>& vox : m_activeVoices)
|
||||
if (vox->vid() == vid)
|
||||
return vox;
|
||||
{
|
||||
std::shared_ptr<Voice> ret = vox->_findVoice(vid, vox);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@ void Voice::_destroy()
|
|||
Entity::_destroy();
|
||||
if (m_submix)
|
||||
m_submix->m_activeVoices.erase(this);
|
||||
|
||||
for (std::shared_ptr<Voice>& vox : m_childVoices)
|
||||
vox->_destroy();
|
||||
}
|
||||
|
||||
Voice::Voice(Engine& engine, const AudioGroup& group, int vid, bool emitter, Submix* smx)
|
||||
|
@ -96,7 +99,7 @@ void Voice::_bringOutYourDead()
|
|||
{
|
||||
Voice* vox = it->get();
|
||||
vox->_bringOutYourDead();
|
||||
if (vox->m_dead)
|
||||
if (vox->m_voxState == VoiceState::Finished)
|
||||
{
|
||||
it = _destroyVoice(vox);
|
||||
continue;
|
||||
|
@ -105,6 +108,21 @@ void Voice::_bringOutYourDead()
|
|||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Voice> Voice::_findVoice(int vid, std::weak_ptr<Voice> thisPtr)
|
||||
{
|
||||
if (m_vid == vid)
|
||||
return thisPtr.lock();
|
||||
|
||||
for (std::shared_ptr<Voice>& vox : m_childVoices)
|
||||
{
|
||||
std::shared_ptr<Voice> ret = vox->_findVoice(vid, vox);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::shared_ptr<Voice> Voice::_allocateVoice(double sampleRate, bool dynamicPitch)
|
||||
{
|
||||
auto it = m_childVoices.emplace(m_childVoices.end(), new Voice(m_engine, m_audioGroup,
|
||||
|
@ -244,9 +262,10 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
|
|||
{
|
||||
uint32_t samplesRem = samples;
|
||||
size_t samplesProc = 0;
|
||||
bool dead = false;
|
||||
if (m_curSample)
|
||||
{
|
||||
m_dead = m_state.advance(*this, samples / m_sampleRate);
|
||||
dead = m_state.advance(*this, samples / m_sampleRate);
|
||||
|
||||
uint32_t block = m_curSamplePos / 14;
|
||||
uint32_t rem = m_curSamplePos % 14;
|
||||
|
@ -344,11 +363,11 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
|
|||
}
|
||||
else
|
||||
{
|
||||
m_dead = m_state.advance(*this, 0.0);
|
||||
dead = m_state.advance(*this, 0.0);
|
||||
memset(data, 0, sizeof(int16_t) * samples);
|
||||
}
|
||||
|
||||
if (m_dead)
|
||||
if (dead)
|
||||
m_voxState = VoiceState::Finished;
|
||||
return samples;
|
||||
}
|
||||
|
@ -364,8 +383,12 @@ int Voice::maxVid() const
|
|||
std::shared_ptr<Voice> Voice::startChildMacro(int8_t addNote, ObjectId macroId, int macroStep)
|
||||
{
|
||||
std::shared_ptr<Voice> vox = _allocateVoice(32000.0, true);
|
||||
vox->loadSoundMacro(macroId, macroStep, 1000.0, m_state.m_initKey + addNote,
|
||||
m_state.m_initVel, m_state.m_initMod);
|
||||
if (!vox->loadSoundMacro(macroId, macroStep, 1000.0, m_state.m_initKey + addNote,
|
||||
m_state.m_initVel, m_state.m_initMod))
|
||||
{
|
||||
_destroyVoice(vox.get());
|
||||
return {};
|
||||
}
|
||||
return vox;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue