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

View File

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

View File

@ -50,6 +50,7 @@ class Engine
std::list<Submix>::iterator _destroySubmix(Submix* smx); std::list<Submix>::iterator _destroySubmix(Submix* smx);
std::list<Submix>::iterator _removeSubmix(Submix* smx); std::list<Submix>::iterator _removeSubmix(Submix* smx);
void _bringOutYourDead(); void _bringOutYourDead();
void _5MsCallback(double dt);
public: public:
~Engine(); ~Engine();
Engine(IBackendVoiceAllocator& backend); Engine(IBackendVoiceAllocator& backend);
@ -58,7 +59,7 @@ public:
IBackendVoiceAllocator& getBackend() {return m_backend;} IBackendVoiceAllocator& getBackend() {return m_backend;}
/** Update all active audio entities and fill OS audio buffers as needed */ /** 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! */ /** Add audio group data pointers to engine; must remain resident! */
const AudioGroup* addAudioGroup(const AudioGroupData& data); 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_decayTime = 0.0; /**< Time of decay in seconds */
double m_sustainFactor = 1.0; /**< Evaluated sustain percentage */ double m_sustainFactor = 1.0; /**< Evaluated sustain percentage */
double m_releaseTime = 0.0; /**< Time of release in seconds */ double m_releaseTime = 0.0; /**< Time of release in seconds */
double m_releaseStartFactor; /**< Level at whenever release event occurs */ double m_releaseStartFactor = 0.0; /**< Level at whenever release event occurs */
double m_curTime; /**< Current time of envelope stage in seconds */ double m_curTime = 0.0; /**< Current time of envelope stage in seconds */
public: public:
void reset(const ADSR* adsr); void reset(const ADSR* adsr);
void reset(const ADSRDLS* adsr, int8_t note, int8_t vel); void reset(const ADSRDLS* adsr, int8_t note, int8_t vel);

View File

@ -2,6 +2,7 @@
#define __AMUSE_IBACKENDVOICEALLOCATOR_HPP__ #define __AMUSE_IBACKENDVOICEALLOCATOR_HPP__
#include <memory> #include <memory>
#include <functional>
namespace amuse namespace amuse
{ {
@ -39,6 +40,9 @@ public:
/** Amuse flushes voice samples to the backend this way */ /** Amuse flushes voice samples to the backend this way */
virtual void pumpAndMixVoices()=0; 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 */ /** Play MIDI arrangement */
void playSong(const unsigned char* arrData, bool dieOnEnd=true); void playSong(const unsigned char* arrData, bool dieOnEnd=true);
/** Stop current MIDI arrangement */
void stopSong(bool now=false);
/** Set total volume of sequencer */ /** Set total volume of sequencer */
void setVolume(float vol); 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); 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() AudioChannelSet BooBackendVoiceAllocator::getAvailableSet()
{ {
return AudioChannelSet(m_booEngine.getAvailableSet()); return AudioChannelSet(m_booEngine.getAvailableSet());

View File

@ -25,7 +25,9 @@ Engine::~Engine()
Engine::Engine(IBackendVoiceAllocator& backend) Engine::Engine(IBackendVoiceAllocator& backend)
: m_backend(backend) : m_backend(backend)
{} {
backend.register5MsCallback(std::bind(&Engine::_5MsCallback, this, std::placeholders::_1));
}
std::pair<AudioGroup*, const SongGroupIndex*> Engine::_findSongGroup(int groupId) const 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::_5MsCallback(double dt)
void Engine::pumpEngine(double dt)
{ {
for (std::shared_ptr<Sequencer>& seq : m_activeSequencers) for (std::shared_ptr<Sequencer>& seq : m_activeSequencers)
seq->advance(dt); seq->advance(dt);
}
/** Update all active audio entities and fill OS audio buffers as needed */
void Engine::pumpEngine()
{
m_backend.pumpAndMixVoices(); m_backend.pumpAndMixVoices();
_bringOutYourDead(); _bringOutYourDead();
@ -321,7 +326,8 @@ std::shared_ptr<Voice> Engine::fxStart(int sfxId, float vol, float pan, Submix*
if (!grp) if (!grp)
return nullptr; 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)) if (!ret->loadSoundObject(SBig(entry->objId), 0, 1000.f, entry->defKey, entry->defVel, 0))
{ {
_destroyVoice(ret.get()); _destroyVoice(ret.get());
@ -345,7 +351,8 @@ std::shared_ptr<Emitter> Engine::addEmitter(const Vector3f& pos, const Vector3f&
if (!grp) if (!grp)
return nullptr; 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))); m_activeEmitters.emplace(m_activeEmitters.end(), new Emitter(*this, *grp, std::move(vox)));
Emitter& ret = *m_activeEmitters.back(); Emitter& ret = *m_activeEmitters.back();
if (!ret.getVoice()->loadSoundObject(entry->objId, 0, 1000.f, entry->defKey, entry->defVel, 0)) 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; m_state = SequencerState::Playing;
} }
void Sequencer::stopSong(bool now)
{
allOff(now);
m_arrData = nullptr;
m_state = SequencerState::Interactive;
}
void Sequencer::ChannelState::setVolume(float vol) void Sequencer::ChannelState::setVolume(float vol)
{ {
m_curVol = vol; m_curVol = vol;

View File

@ -190,7 +190,7 @@ bool SongState::Channel::advance(Sequencer& seq, int32_t ticks)
m_lastPitchTick = nextTick; m_lastPitchTick = nextTick;
remPitchTicks -= (nextTick - pitchTick); remPitchTicks -= (nextTick - pitchTick);
pitchTick = nextTick; 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; continue;
} }
remPitchTicks -= (nextTick - pitchTick); remPitchTicks -= (nextTick - pitchTick);

View File

@ -224,7 +224,8 @@ bool Voice::_advanceSample(int16_t& samp, int32_t& newPitch)
} }
/* Factor in ADSR envelope state */ /* 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 */ /* Apply tremolo */
if (m_state.m_tremoloSel && (m_tremoloScale || m_tremoloModScale)) if (m_state.m_tremoloSel && (m_tremoloScale || m_tremoloModScale))