mirror of https://github.com/AxioDL/amuse.git
Timing fixes for SON playback
This commit is contained in:
parent
3433a70462
commit
2115a958b1
|
@ -10,6 +10,8 @@
|
|||
#include <thread>
|
||||
#include <map>
|
||||
|
||||
#define VOL_FACTOR 0.25
|
||||
|
||||
static logvisor::Module Log("amuseplay");
|
||||
|
||||
static amuse::IntrusiveAudioGroupData LoadFromArgs(int argc, const boo::SystemChar** argv,
|
||||
|
@ -204,7 +206,7 @@ struct AppCallback : boo::IApplicationCallback
|
|||
if (m_seq)
|
||||
m_seq->allOff();
|
||||
m_seq = m_engine->seqPlay(m_groupId, setupId, nullptr);
|
||||
m_seq->setVolume(m_volume);
|
||||
m_seq->setVolume(m_volume * VOL_FACTOR);
|
||||
|
||||
if (m_arrData)
|
||||
m_seq->playSong(m_arrData.get(), false);
|
||||
|
@ -804,18 +806,18 @@ void EventCallback::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods,
|
|||
if (m_app.m_volume < 1.f)
|
||||
m_app.m_volume = amuse::clamp(0.f, m_app.m_volume + 0.05f, 1.f);
|
||||
if (m_app.m_vox)
|
||||
m_app.m_vox->setVolume(m_app.m_volume);
|
||||
m_app.m_vox->setVolume(m_app.m_volume * VOL_FACTOR);
|
||||
if (m_app.m_seq)
|
||||
m_app.m_seq->setVolume(m_app.m_volume);
|
||||
m_app.m_seq->setVolume(m_app.m_volume * VOL_FACTOR);
|
||||
m_app.m_updateDisp = true;
|
||||
break;
|
||||
case boo::ESpecialKey::Down:
|
||||
if (m_app.m_volume > 0.f)
|
||||
m_app.m_volume = amuse::clamp(0.f, m_app.m_volume - 0.05f, 1.f);
|
||||
if (m_app.m_vox)
|
||||
m_app.m_vox->setVolume(m_app.m_volume);
|
||||
m_app.m_vox->setVolume(m_app.m_volume * VOL_FACTOR);
|
||||
if (m_app.m_seq)
|
||||
m_app.m_seq->setVolume(m_app.m_volume);
|
||||
m_app.m_seq->setVolume(m_app.m_volume * VOL_FACTOR);
|
||||
m_app.m_updateDisp = true;
|
||||
break;
|
||||
default: break;
|
||||
|
|
|
@ -98,6 +98,7 @@ class SongState
|
|||
|
||||
uint32_t m_curTick = 0; /**< Current playback position for all channels */
|
||||
SongPlayState m_songState = SongPlayState::Playing; /**< High-level state of Song playback */
|
||||
double m_curDt = 0.f; /**< Cumulative dt value for time-remainder tracking */
|
||||
|
||||
public:
|
||||
/** initialize state for Song data at `ptr` */
|
||||
|
|
|
@ -13,14 +13,14 @@ namespace amuse
|
|||
|
||||
Engine::~Engine()
|
||||
{
|
||||
for (std::shared_ptr<Sequencer>& seq : m_activeSequencers)
|
||||
seq->_destroy();
|
||||
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)
|
||||
|
|
|
@ -143,6 +143,9 @@ std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velo
|
|||
if (!m_page)
|
||||
return {};
|
||||
|
||||
/* Ensure keyoff sent first */
|
||||
keyOff(note, 0);
|
||||
|
||||
std::shared_ptr<Voice> ret = m_parent.m_engine._allocateVoice(m_parent.m_audioGroup,
|
||||
m_parent.m_groupId, 32000.0,
|
||||
true, false, m_submix);
|
||||
|
|
|
@ -124,6 +124,9 @@ SongState::Channel::Channel(SongState& parent, uint8_t midiChan, uint32_t startT
|
|||
m_modWheelData = song + header.m_modOff;
|
||||
|
||||
m_waitCountdown = startTick;
|
||||
m_lastPitchTick = startTick;
|
||||
m_lastModTick = startTick;
|
||||
m_waitCountdown += int32_t(DecodeTimeRLE(m_data));
|
||||
}
|
||||
|
||||
void SongState::initialize(const unsigned char* ptr)
|
||||
|
@ -246,10 +249,6 @@ bool SongState::Channel::advance(Sequencer& seq, int32_t ticks)
|
|||
}
|
||||
}
|
||||
|
||||
/* Bootstrap first delta-time */
|
||||
if (m_data == m_dataBase)
|
||||
m_waitCountdown = DecodeTimeRLE(m_data);
|
||||
|
||||
/* Loop through as many commands as we can for this time period */
|
||||
while (true)
|
||||
{
|
||||
|
@ -257,9 +256,8 @@ bool SongState::Channel::advance(Sequencer& seq, int32_t ticks)
|
|||
if (m_waitCountdown)
|
||||
{
|
||||
m_waitCountdown -= ticks;
|
||||
if (m_waitCountdown <= 0)
|
||||
m_waitCountdown = 0;
|
||||
else
|
||||
ticks = 0;
|
||||
if (m_waitCountdown > 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -290,7 +288,7 @@ bool SongState::Channel::advance(Sequencer& seq, int32_t ticks)
|
|||
}
|
||||
|
||||
/* Set next delta-time */
|
||||
m_waitCountdown = DecodeTimeRLE(m_data);
|
||||
m_waitCountdown += int32_t(DecodeTimeRLE(m_data));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -302,12 +300,17 @@ bool SongState::advance(Sequencer& seq, double dt)
|
|||
if (m_songState == SongPlayState::Stopped)
|
||||
return true;
|
||||
|
||||
bool done = true;
|
||||
while (dt > 0.0)
|
||||
bool done = false;
|
||||
m_curDt += dt;
|
||||
while (m_curDt > 0.0)
|
||||
{
|
||||
done = true;
|
||||
|
||||
/* Compute ticks to compute based on current tempo */
|
||||
int32_t remTicks = dt * m_tempo * 384 / 60;
|
||||
if (!remTicks) remTicks = 1;
|
||||
double ticksPerSecond = m_tempo * 384 / 60;
|
||||
int32_t remTicks = std::ceil(m_curDt * ticksPerSecond);
|
||||
if (!remTicks)
|
||||
break;
|
||||
|
||||
/* See if there's an upcoming tempo change in this interval */
|
||||
if (m_tempoPtr && m_tempoPtr->m_tick != 0xffffffff)
|
||||
|
@ -335,9 +338,9 @@ bool SongState::advance(Sequencer& seq, double dt)
|
|||
m_curTick += remTicks;
|
||||
|
||||
if (m_tempo == 0)
|
||||
dt = 0.0;
|
||||
m_curDt = 0.0;
|
||||
else
|
||||
dt -= remTicks / double(m_tempo * 384 / 60);
|
||||
m_curDt -= remTicks / ticksPerSecond;
|
||||
}
|
||||
|
||||
if (done)
|
||||
|
|
|
@ -6,7 +6,6 @@ namespace amuse
|
|||
void Submix::_destroy()
|
||||
{
|
||||
m_destroyed = true;
|
||||
m_backendSubmix.reset();
|
||||
}
|
||||
|
||||
Submix::Submix(Engine& engine, Submix* smx)
|
||||
|
|
|
@ -18,8 +18,6 @@ void Voice::_destroy()
|
|||
|
||||
for (std::shared_ptr<Voice>& vox : m_childVoices)
|
||||
vox->_destroy();
|
||||
|
||||
m_backendVoice.reset();
|
||||
}
|
||||
|
||||
Voice::~Voice()
|
||||
|
@ -557,9 +555,6 @@ void Voice::_macroKeyOff()
|
|||
_doKeyOff();
|
||||
m_voxState = VoiceState::KeyOff;
|
||||
}
|
||||
|
||||
for (const std::shared_ptr<Voice>& vox : m_childVoices)
|
||||
vox->keyOff();
|
||||
}
|
||||
|
||||
void Voice::keyOff()
|
||||
|
@ -575,10 +570,12 @@ void Voice::keyOff()
|
|||
loadSoundObject(m_keyoffTrap.macroId, m_keyoffTrap.macroStep,
|
||||
m_state.m_ticksPerSec, m_state.m_initKey,
|
||||
m_state.m_initVel, m_state.m_initMod);
|
||||
return;
|
||||
}
|
||||
else
|
||||
_macroKeyOff();
|
||||
|
||||
for (const std::shared_ptr<Voice>& vox : m_childVoices)
|
||||
vox->keyOff();
|
||||
}
|
||||
|
||||
void Voice::message(int32_t val)
|
||||
|
@ -780,13 +777,21 @@ void Voice::setAdsr(ObjectId adsrId, bool dls)
|
|||
{
|
||||
const ADSRDLS* adsr = m_audioGroup.getPool().tableAsAdsrDLS(adsrId);
|
||||
if (adsr)
|
||||
{
|
||||
m_volAdsr.reset(adsr, m_state.m_initKey, m_state.m_initVel);
|
||||
if (m_voxState == VoiceState::KeyOff)
|
||||
m_volAdsr.keyOff();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const ADSR* adsr = m_audioGroup.getPool().tableAsAdsr(adsrId);
|
||||
if (adsr)
|
||||
{
|
||||
m_volAdsr.reset(adsr);
|
||||
if (m_voxState == VoiceState::KeyOff)
|
||||
m_volAdsr.keyOff();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue