Timing and pitch fixes

This commit is contained in:
Jack Andersen 2016-05-19 00:12:32 -10:00
parent 93b9c93ea4
commit 5245a41567
11 changed files with 45 additions and 13 deletions

View File

@ -204,7 +204,10 @@ struct AppCallback : boo::IApplicationCallback
{
m_setupId = setupId;
if (m_seq)
m_seq->allOff();
{
m_seq->stopSong();
m_seq->kill();
}
m_seq = m_engine->seqPlay(m_groupId, setupId, nullptr);
m_seq->setVolume(m_volume * VOL_FACTOR);
@ -291,7 +294,7 @@ struct AppCallback : boo::IApplicationCallback
UpdateSongDisplay();
}
m_engine->pumpEngine(1.0 / 60.0);
m_engine->pumpEngine();
size_t voxCount;
if (m_seq)
@ -377,7 +380,7 @@ struct AppCallback : boo::IApplicationCallback
UpdateSFXDisplay();
}
m_engine->pumpEngine(1.0 / 60.0);
m_engine->pumpEngine();
if (m_vox && m_vox->state() == amuse::VoiceState::Dead)
{

View File

@ -69,6 +69,7 @@ public:
BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine);
std::unique_ptr<IBackendVoice> allocateVoice(Voice& clientVox, double sampleRate, bool dynamicPitch);
std::unique_ptr<IBackendSubmix> allocateSubmix(Submix& clientSmx);
void register5MsCallback(std::function<void(double)>&& callback);
AudioChannelSet getAvailableSet();
void pumpAndMixVoices();
};

View File

@ -50,6 +50,7 @@ class Engine
std::list<Submix>::iterator _destroySubmix(Submix* smx);
std::list<Submix>::iterator _removeSubmix(Submix* smx);
void _bringOutYourDead();
void _5MsCallback(double dt);
public:
~Engine();
Engine(IBackendVoiceAllocator& backend);
@ -58,7 +59,7 @@ public:
IBackendVoiceAllocator& getBackend() {return m_backend;}
/** Update all active audio entities and fill OS audio buffers as needed */
void pumpEngine(double dt);
void pumpEngine();
/** Add audio group data pointers to engine; must remain resident! */
const AudioGroup* addAudioGroup(const AudioGroupData& data);

View File

@ -24,8 +24,8 @@ private:
double m_decayTime = 0.0; /**< Time of decay in seconds */
double m_sustainFactor = 1.0; /**< Evaluated sustain percentage */
double m_releaseTime = 0.0; /**< Time of release in seconds */
double m_releaseStartFactor; /**< Level at whenever release event occurs */
double m_curTime; /**< Current time of envelope stage 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:
void reset(const ADSR* adsr);
void reset(const ADSRDLS* adsr, int8_t note, int8_t vel);

View File

@ -2,6 +2,7 @@
#define __AMUSE_IBACKENDVOICEALLOCATOR_HPP__
#include <memory>
#include <functional>
namespace amuse
{
@ -39,6 +40,9 @@ public:
/** Amuse flushes voice samples to the backend this way */
virtual void pumpAndMixVoices()=0;
/** Amuse may request callbacks 200-updates-per-second virtually */
virtual void register5MsCallback(std::function<void(double dt)>&& callback)=0;
};
}

View File

@ -127,6 +127,9 @@ public:
/** Play MIDI arrangement */
void playSong(const unsigned char* arrData, bool dieOnEnd=true);
/** Stop current MIDI arrangement */
void stopSong(bool now=false);
/** Set total volume of sequencer */
void setVolume(float vol);

View File

@ -115,6 +115,11 @@ std::unique_ptr<IBackendSubmix> BooBackendVoiceAllocator::allocateSubmix(Submix&
return std::make_unique<BooBackendSubmix>(m_booEngine, clientSmx);
}
void BooBackendVoiceAllocator::register5MsCallback(std::function<void(double)>&& callback)
{
m_booEngine.register5MsCallback(std::move(callback));
}
AudioChannelSet BooBackendVoiceAllocator::getAvailableSet()
{
return AudioChannelSet(m_booEngine.getAvailableSet());

View File

@ -25,7 +25,9 @@ Engine::~Engine()
Engine::Engine(IBackendVoiceAllocator& backend)
: m_backend(backend)
{}
{
backend.register5MsCallback(std::bind(&Engine::_5MsCallback, this, std::placeholders::_1));
}
std::pair<AudioGroup*, const SongGroupIndex*> Engine::_findSongGroup(int groupId) const
{
@ -152,12 +154,15 @@ void Engine::_bringOutYourDead()
}
}
/** Update all active audio entities and fill OS audio buffers as needed */
void Engine::pumpEngine(double dt)
void Engine::_5MsCallback(double dt)
{
for (std::shared_ptr<Sequencer>& seq : m_activeSequencers)
seq->advance(dt);
}
/** Update all active audio entities and fill OS audio buffers as needed */
void Engine::pumpEngine()
{
m_backend.pumpAndMixVoices();
_bringOutYourDead();
@ -321,7 +326,8 @@ std::shared_ptr<Voice> Engine::fxStart(int sfxId, float vol, float pan, Submix*
if (!grp)
return nullptr;
std::shared_ptr<Voice> ret = _allocateVoice(*grp, std::get<1>(search->second), 32000.0, true, false, smx);
std::shared_ptr<Voice> ret = _allocateVoice(*grp, std::get<1>(search->second),
32000.0, true, false, smx);
if (!ret->loadSoundObject(SBig(entry->objId), 0, 1000.f, entry->defKey, entry->defVel, 0))
{
_destroyVoice(ret.get());
@ -345,7 +351,8 @@ std::shared_ptr<Emitter> Engine::addEmitter(const Vector3f& pos, const Vector3f&
if (!grp)
return nullptr;
std::shared_ptr<Voice> vox = _allocateVoice(*grp, std::get<1>(search->second), 32000.0, true, true, smx);
std::shared_ptr<Voice> vox = _allocateVoice(*grp, std::get<1>(search->second),
32000.0, true, true, smx);
m_activeEmitters.emplace(m_activeEmitters.end(), new Emitter(*this, *grp, std::move(vox)));
Emitter& ret = *m_activeEmitters.back();
if (!ret.getVoice()->loadSoundObject(entry->objId, 0, 1000.f, entry->defKey, entry->defVel, 0))

View File

@ -409,6 +409,13 @@ void Sequencer::playSong(const unsigned char* arrData, bool dieOnEnd)
m_state = SequencerState::Playing;
}
void Sequencer::stopSong(bool now)
{
allOff(now);
m_arrData = nullptr;
m_state = SequencerState::Interactive;
}
void Sequencer::ChannelState::setVolume(float vol)
{
m_curVol = vol;

View File

@ -190,7 +190,7 @@ bool SongState::Channel::advance(Sequencer& seq, int32_t ticks)
m_lastPitchTick = nextTick;
remPitchTicks -= (nextTick - pitchTick);
pitchTick = nextTick;
seq.setPitchWheel(m_midiChan, clamp(-1.f, m_lastPitchVal / 8192.f, 1.f));
seq.setPitchWheel(m_midiChan, clamp(-1.f, m_lastPitchVal / 32768.f, 1.f));
continue;
}
remPitchTicks -= (nextTick - pitchTick);

View File

@ -224,7 +224,8 @@ bool Voice::_advanceSample(int16_t& samp, int32_t& newPitch)
}
/* Factor in ADSR envelope state */
float totalVol = m_userVol * m_curVol * m_volAdsr.nextSample(m_sampleRate) * (m_state.m_curVel / 127.f);
float adsr = m_volAdsr.nextSample(m_sampleRate);
float totalVol = m_userVol * m_curVol * adsr * (m_state.m_curVel / 127.f);
/* Apply tremolo */
if (m_state.m_tremoloSel && (m_tremoloScale || m_tremoloModScale))