New engine event interface

This commit is contained in:
Jack Andersen 2017-02-14 20:01:39 -10:00
parent aff8880595
commit 5c8fa2e8ab
7 changed files with 45 additions and 43 deletions

View File

@ -125,7 +125,7 @@ struct AppCallback : boo::IApplicationCallback
UpdateSongDisplay(); UpdateSongDisplay();
} }
void SongLoop(const amuse::SongGroupIndex& index) void SongLoop(const amuse::SongGroupIndex& index, boo::IAudioVoiceEngine& booEngine)
{ {
printf( printf(
"░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n" "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n"
@ -202,7 +202,7 @@ struct AppCallback : boo::IApplicationCallback
UpdateSongDisplay(); UpdateSongDisplay();
} }
m_engine->pumpEngine(); m_win->waitForRetrace(&booEngine);
size_t voxCount; size_t voxCount;
int8_t progId; int8_t progId;
@ -231,8 +231,6 @@ struct AppCallback : boo::IApplicationCallback
m_seq.reset(); m_seq.reset();
break; break;
} }
m_win->waitForRetrace();
} }
} }
@ -260,7 +258,7 @@ struct AppCallback : boo::IApplicationCallback
UpdateSFXDisplay(); UpdateSFXDisplay();
} }
void SFXLoop(const amuse::SFXGroupIndex& index) void SFXLoop(const amuse::SFXGroupIndex& index, boo::IAudioVoiceEngine& booEngine)
{ {
printf("<space>: keyon/keyoff, <left/right>: cycle SFX, <up/down>: volume, <Q>: quit\n"); printf("<space>: keyon/keyoff, <left/right>: cycle SFX, <up/down>: volume, <Q>: quit\n");
@ -306,7 +304,7 @@ struct AppCallback : boo::IApplicationCallback
UpdateSFXDisplay(); UpdateSFXDisplay();
} }
m_engine->pumpEngine(); m_win->waitForRetrace(&booEngine);
if (m_vox && m_vox->state() == amuse::VoiceState::Dead) if (m_vox && m_vox->state() == amuse::VoiceState::Dead)
{ {
@ -322,8 +320,6 @@ struct AppCallback : boo::IApplicationCallback
m_seq.reset(); m_seq.reset();
break; break;
} }
m_win->waitForRetrace();
} }
} }
@ -876,9 +872,9 @@ struct AppCallback : boo::IApplicationCallback
/* Enter playback loop */ /* Enter playback loop */
if (m_sfxGroup) if (m_sfxGroup)
SFXLoop(*sfxIndex); SFXLoop(*sfxIndex, *voxEngine);
else else
SongLoop(*songIndex); SongLoop(*songIndex, *voxEngine);
printf("\n\n"); printf("\n\n");
} }

View File

@ -470,7 +470,7 @@ int main(int argc, const boo::SystemChar** argv)
signal(SIGINT, SIGINTHandler); signal(SIGINT, SIGINTHandler);
do do
{ {
engine.pumpEngine(); voxEngine->pumpAndMixVoices();
wroteFrames += voxEngine->get5MsFrames(); wroteFrames += voxEngine->get5MsFrames();
printf("\rFrame %" PRISize, wroteFrames); printf("\rFrame %" PRISize, wroteFrames);
fflush(stdout); fflush(stdout);

View File

@ -116,10 +116,11 @@ public:
}; };
/** Backend voice allocator implementation for boo mixer */ /** Backend voice allocator implementation for boo mixer */
class BooBackendVoiceAllocator : public IBackendVoiceAllocator class BooBackendVoiceAllocator : public IBackendVoiceAllocator, public boo::IAudioVoiceEngineCallback
{ {
friend class BooBackendMIDIReader; friend class BooBackendMIDIReader;
boo::IAudioVoiceEngine& m_booEngine; boo::IAudioVoiceEngine& m_booEngine;
Engine* m_cbInterface = nullptr;
public: public:
BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine); BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine);
@ -127,11 +128,11 @@ public:
std::unique_ptr<IBackendSubmix> allocateSubmix(Submix& clientSmx, bool mainOut, int busId); std::unique_ptr<IBackendSubmix> allocateSubmix(Submix& clientSmx, bool mainOut, int busId);
std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices(); std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices();
std::unique_ptr<IMIDIReader> allocateMIDIReader(Engine& engine, const char* name = nullptr); std::unique_ptr<IMIDIReader> allocateMIDIReader(Engine& engine, const char* name = nullptr);
void register5MsCallback(std::function<void(double)>&& callback); void setCallbackInterface(Engine* engine);
void unregister5MsCallback();
AudioChannelSet getAvailableSet(); AudioChannelSet getAvailableSet();
void pumpAndMixVoices();
void setVolume(float vol); void setVolume(float vol);
void on5MsInterval(boo::IAudioVoiceEngine& engine, double dt);
void onPumpCycleComplete(boo::IAudioVoiceEngine& engine);
}; };
} }

View File

@ -65,7 +65,6 @@ class Engine
std::list<std::shared_ptr<Sequencer>>::iterator std::list<std::shared_ptr<Sequencer>>::iterator
_destroySequencer(std::list<std::shared_ptr<Sequencer>>::iterator it); _destroySequencer(std::list<std::shared_ptr<Sequencer>>::iterator it);
void _bringOutYourDead(); void _bringOutYourDead();
void _5MsCallback(double dt);
public: public:
~Engine(); ~Engine();
@ -74,9 +73,6 @@ public:
/** Access voice backend of engine */ /** Access voice backend of engine */
IBackendVoiceAllocator& getBackend() { return m_backend; } IBackendVoiceAllocator& getBackend() { return m_backend; }
/** Update all active audio entities and fill OS audio buffers as needed */
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);
@ -130,6 +126,14 @@ public:
/** Obtain list of active sequencers */ /** Obtain list of active sequencers */
std::list<std::shared_ptr<Sequencer>>& getActiveSequencers() { return m_activeSequencers; } std::list<std::shared_ptr<Sequencer>>& getActiveSequencers() { return m_activeSequencers; }
/** All mixing occurs in virtual 5ms intervals;
* this is called at the start of each interval for all mixable entities */
void _on5MsInterval(IBackendVoiceAllocator& engine, double dt);
/** When a pumping cycle is complete this is called to allow the client to
* perform periodic cleanup tasks */
void _onPumpCycleComplete(IBackendVoiceAllocator& engine);
}; };
} }

View File

@ -53,17 +53,11 @@ public:
/** Amuse obtains speaker-configuration from the platform this way */ /** Amuse obtains speaker-configuration from the platform this way */
virtual AudioChannelSet getAvailableSet() = 0; virtual AudioChannelSet getAvailableSet() = 0;
/** Amuse flushes voice samples to the backend this way */
virtual void pumpAndMixVoices() = 0;
/** Set volume of main mix out */ /** Set volume of main mix out */
virtual void setVolume(float vol) = 0; virtual void setVolume(float vol) = 0;
/** Amuse may request callbacks 200-updates-per-second virtually */ /** Amuse registers for key callback events from the mixing engine this way */
virtual void register5MsCallback(std::function<void(double dt)>&& callback) = 0; virtual void setCallbackInterface(Engine* engine) = 0;
/** This is important to ensure orderly cleanup */
virtual void unregister5MsCallback() = 0;
}; };
} }

View File

@ -254,7 +254,11 @@ void BooBackendMIDIReader::stopSeq() {}
void BooBackendMIDIReader::reset() {} void BooBackendMIDIReader::reset() {}
BooBackendVoiceAllocator::BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) : m_booEngine(booEngine) {} BooBackendVoiceAllocator::BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine)
: m_booEngine(booEngine)
{
booEngine.setCallbackInterface(this);
}
std::unique_ptr<IBackendVoice> BooBackendVoiceAllocator::allocateVoice(Voice& clientVox, double sampleRate, std::unique_ptr<IBackendVoice> BooBackendVoiceAllocator::allocateVoice(Voice& clientVox, double sampleRate,
bool dynamicPitch) bool dynamicPitch)
@ -280,19 +284,24 @@ std::unique_ptr<IMIDIReader> BooBackendVoiceAllocator::allocateMIDIReader(Engine
return ret; return ret;
} }
void BooBackendVoiceAllocator::register5MsCallback(std::function<void(double)>&& callback) void BooBackendVoiceAllocator::setCallbackInterface(Engine* engine)
{ {
m_booEngine.register5MsCallback(std::move(callback)); m_cbInterface = engine;
}
void BooBackendVoiceAllocator::unregister5MsCallback()
{
m_booEngine.unregister5MsCallback();
} }
AudioChannelSet BooBackendVoiceAllocator::getAvailableSet() { return AudioChannelSet(m_booEngine.getAvailableSet()); } AudioChannelSet BooBackendVoiceAllocator::getAvailableSet() { return AudioChannelSet(m_booEngine.getAvailableSet()); }
void BooBackendVoiceAllocator::pumpAndMixVoices() { m_booEngine.pumpAndMixVoices(); }
void BooBackendVoiceAllocator::setVolume(float vol) { m_booEngine.setVolume(vol); } void BooBackendVoiceAllocator::setVolume(float vol) { m_booEngine.setVolume(vol); }
void BooBackendVoiceAllocator::on5MsInterval(boo::IAudioVoiceEngine& engine, double dt)
{
if (m_cbInterface)
m_cbInterface->_on5MsInterval(*this, dt);
}
void BooBackendVoiceAllocator::onPumpCycleComplete(boo::IAudioVoiceEngine& engine)
{
if (m_cbInterface)
m_cbInterface->_onPumpCycleComplete(*this);
}
} }

View File

@ -15,7 +15,7 @@ static const float FullLevels[8] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f};
Engine::~Engine() Engine::~Engine()
{ {
m_backend.unregister5MsCallback(); m_backend.setCallbackInterface(nullptr);
for (std::shared_ptr<Sequencer>& seq : m_activeSequencers) for (std::shared_ptr<Sequencer>& seq : m_activeSequencers)
if (!seq->m_destroyed) if (!seq->m_destroyed)
seq->_destroy(); seq->_destroy();
@ -31,7 +31,7 @@ Engine::Engine(IBackendVoiceAllocator& backend, AmplitudeMode ampMode)
m_defaultStudio->getAuxA().makeReverbStd(0.5f, 0.8f, 3.0f, 0.5f, 0.1f); m_defaultStudio->getAuxA().makeReverbStd(0.5f, 0.8f, 3.0f, 0.5f, 0.1f);
m_defaultStudio->getAuxB().makeChorus(15, 0, 500); m_defaultStudio->getAuxB().makeChorus(15, 0, 500);
m_defaultStudioReady = true; m_defaultStudioReady = true;
backend.register5MsCallback(std::bind(&Engine::_5MsCallback, this, std::placeholders::_1)); m_backend.setCallbackInterface(this);
m_midiReader = backend.allocateMIDIReader(*this); m_midiReader = backend.allocateMIDIReader(*this);
} }
@ -172,7 +172,7 @@ void Engine::_bringOutYourDead()
} }
} }
void Engine::_5MsCallback(double dt) void Engine::_on5MsInterval(IBackendVoiceAllocator& engine, double dt)
{ {
if (m_midiReader) if (m_midiReader)
m_midiReader->pumpReader(dt); m_midiReader->pumpReader(dt);
@ -180,10 +180,8 @@ void Engine::_5MsCallback(double dt)
seq->advance(dt); seq->advance(dt);
} }
/** Update all active audio entities and fill OS audio buffers as needed */ void Engine::_onPumpCycleComplete(IBackendVoiceAllocator& engine)
void Engine::pumpEngine()
{ {
m_backend.pumpAndMixVoices();
_bringOutYourDead(); _bringOutYourDead();
/* Determine lowest available free vid */ /* Determine lowest available free vid */