diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 835bf055b..82ae4f710 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -103,6 +103,7 @@ class DivDispatch { int rate; virtual void acquire(short* bufL, short* bufR, size_t start, size_t len); virtual int dispatch(DivCommand c); + virtual void reset(); virtual void tick(); virtual bool isStereo(); diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 0c0ad1cfc..7704221a5 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -991,7 +991,43 @@ void DivEngine::setLoops(int loops) { } void DivEngine::play() { - + isBusy.lock(); + for (int i=0; i<17; i++) { + chan[i]=DivChannelState(); + } + dispatch->reset(); + playing=true; + curRow=0; + clockDrift=0; + cycles=0; + isBusy.unlock(); +} + +void DivEngine::stop() { + isBusy.lock(); + playing=false; + isBusy.unlock(); +} + +unsigned char DivEngine::getOrder() { + return curOrder; +} + +void DivEngine::setOrder(unsigned char order) { + isBusy.lock(); + curOrder=order; + if (order>=song.ordersLen) curOrder=0; + if (playing) { + for (int i=0; i<17; i++) { + chan[i]=DivChannelState(); + } + dispatch->reset(); + playing=true; + curRow=0; + clockDrift=0; + cycles=0; + } + isBusy.unlock(); } void DivEngine::setAudio(DivAudioEngines which) { diff --git a/src/engine/engine.h b/src/engine/engine.h index a1412283c..050f0449f 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -4,6 +4,7 @@ #include "dispatch.h" #include "../audio/taAudio.h" #include "blip_buf.h" +#include enum DivStatusView { DIV_STATUS_NOTHING=0, @@ -71,6 +72,7 @@ class DivEngine { DivStatusView view; DivChannelState chan[17]; DivAudioEngines audioEngine; + std::mutex isBusy; short vibTable[64]; @@ -107,6 +109,15 @@ class DivEngine { // play void play(); + // stop + void stop(); + + // get current order + unsigned char getOrder(); + + // go to order + void setOrder(unsigned char order); + // set remaining loops. -1 means loop forever. void setLoops(int loops); diff --git a/src/engine/platform/abstract.cpp b/src/engine/platform/abstract.cpp index ceef77b38..65582a9b5 100644 --- a/src/engine/platform/abstract.cpp +++ b/src/engine/platform/abstract.cpp @@ -10,6 +10,9 @@ int DivDispatch::dispatch(DivCommand c) { return 1; } +void DivDispatch::reset() { +} + bool DivDispatch::isStereo() { return false; } diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index 36dfc5b5a..9e2606b00 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -471,25 +471,11 @@ int DivPlatformYM2610::dispatch(DivCommand c) { return 1; } -bool DivPlatformYM2610::isStereo() { - return true; -} - -bool DivPlatformYM2610::keyOffAffectsArp(int ch) { - return (ch>3); -} - -int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, bool pal) { - parent=p; - if (pal) { - rate=500000; - } else { - rate=500000; - } - iface.parent=parent; - iface.sampleBank=0; - fm=new ymfm::ym2610(iface); +void DivPlatformYM2610::reset() { fm->reset(); + for (int i=0; i<13; i++) { + chan[i]=DivPlatformYM2610::Channel(); + } for (int i=0; i<4; i++) { chan[i].vol=0x7f; } @@ -523,5 +509,26 @@ int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, bool pal) { // PCM volume writes.emplace(0x101,0x3f); +} + +bool DivPlatformYM2610::isStereo() { + return true; +} + +bool DivPlatformYM2610::keyOffAffectsArp(int ch) { + return (ch>3); +} + +int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, bool pal) { + parent=p; + if (pal) { + rate=500000; + } else { + rate=500000; + } + iface.parent=parent; + iface.sampleBank=0; + fm=new ymfm::ym2610(iface); + reset(); return 10; } diff --git a/src/engine/platform/ym2610.h b/src/engine/platform/ym2610.h index 4df404bda..dfa86f216 100644 --- a/src/engine/platform/ym2610.h +++ b/src/engine/platform/ym2610.h @@ -61,6 +61,7 @@ class DivPlatformYM2610: public DivDispatch { public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void reset(); void tick(); bool isStereo(); bool keyOffAffectsArp(int ch); diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index be7078479..3e3791eee 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -774,6 +774,11 @@ bool DivEngine::nextTick() { } void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size) { + if (!playing) { + memset(out[0],0,size*sizeof(float)); + memset(out[1],0,size*sizeof(float)); + return; + } size_t runtotal=blip_clocks_needed(bb[0],size); if (runtotal>bbInLen) { @@ -787,6 +792,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi size_t runLeft=runtotal; size_t runPos=0; totalProcessed=0; + isBusy.lock(); while (runLeft) { if (!remainingLoops) { memset(bbIn[0]+runPos,0,runLeft*sizeof(short)); @@ -811,6 +817,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi } } } + isBusy.unlock(); totalProcessed=(1+runPos)*got.rate/dispatch->rate; for (size_t i=0; isong.speed1); ImGui::InputScalar("Speed 2",ImGuiDataType_U8,&e->song.speed2); + unsigned char ord=e->getOrder(); + if (ImGui::InputScalar("Order",ImGuiDataType_U8,&ord)) { + e->setOrder(ord); + } + if (ImGui::Button("Play")) { + e->play(); + } + if (ImGui::Button("Stop")) { + e->stop(); + } } ImGui::End();