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

View File

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

View File

@ -116,10 +116,11 @@ public:
};
/** Backend voice allocator implementation for boo mixer */
class BooBackendVoiceAllocator : public IBackendVoiceAllocator
class BooBackendVoiceAllocator : public IBackendVoiceAllocator, public boo::IAudioVoiceEngineCallback
{
friend class BooBackendMIDIReader;
boo::IAudioVoiceEngine& m_booEngine;
Engine* m_cbInterface = nullptr;
public:
BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine);
@ -127,11 +128,11 @@ public:
std::unique_ptr<IBackendSubmix> allocateSubmix(Submix& clientSmx, bool mainOut, int busId);
std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices();
std::unique_ptr<IMIDIReader> allocateMIDIReader(Engine& engine, const char* name = nullptr);
void register5MsCallback(std::function<void(double)>&& callback);
void unregister5MsCallback();
void setCallbackInterface(Engine* engine);
AudioChannelSet getAvailableSet();
void pumpAndMixVoices();
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
_destroySequencer(std::list<std::shared_ptr<Sequencer>>::iterator it);
void _bringOutYourDead();
void _5MsCallback(double dt);
public:
~Engine();
@ -74,9 +73,6 @@ public:
/** Access voice backend of engine */
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! */
const AudioGroup* addAudioGroup(const AudioGroupData& data);
@ -130,6 +126,14 @@ public:
/** Obtain list of active sequencers */
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 */
virtual AudioChannelSet getAvailableSet() = 0;
/** Amuse flushes voice samples to the backend this way */
virtual void pumpAndMixVoices() = 0;
/** Set volume of main mix out */
virtual void setVolume(float vol) = 0;
/** Amuse may request callbacks 200-updates-per-second virtually */
virtual void register5MsCallback(std::function<void(double dt)>&& callback) = 0;
/** This is important to ensure orderly cleanup */
virtual void unregister5MsCallback() = 0;
/** Amuse registers for key callback events from the mixing engine this way */
virtual void setCallbackInterface(Engine* engine) = 0;
};
}

View File

@ -254,7 +254,11 @@ void BooBackendMIDIReader::stopSeq() {}
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,
bool dynamicPitch)
@ -280,19 +284,24 @@ std::unique_ptr<IMIDIReader> BooBackendVoiceAllocator::allocateMIDIReader(Engine
return ret;
}
void BooBackendVoiceAllocator::register5MsCallback(std::function<void(double)>&& callback)
void BooBackendVoiceAllocator::setCallbackInterface(Engine* engine)
{
m_booEngine.register5MsCallback(std::move(callback));
}
void BooBackendVoiceAllocator::unregister5MsCallback()
{
m_booEngine.unregister5MsCallback();
m_cbInterface = engine;
}
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::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()
{
m_backend.unregister5MsCallback();
m_backend.setCallbackInterface(nullptr);
for (std::shared_ptr<Sequencer>& seq : m_activeSequencers)
if (!seq->m_destroyed)
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->getAuxB().makeChorus(15, 0, 500);
m_defaultStudioReady = true;
backend.register5MsCallback(std::bind(&Engine::_5MsCallback, this, std::placeholders::_1));
m_backend.setCallbackInterface(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)
m_midiReader->pumpReader(dt);
@ -180,10 +180,8 @@ void Engine::_5MsCallback(double dt)
seq->advance(dt);
}
/** Update all active audio entities and fill OS audio buffers as needed */
void Engine::pumpEngine()
void Engine::_onPumpCycleComplete(IBackendVoiceAllocator& engine)
{
m_backend.pumpAndMixVoices();
_bringOutYourDead();
/* Determine lowest available free vid */