From b3b50bdb66c03fde51eca5fbc977e4dc5ed9fb9d Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 3 Mar 2025 01:45:42 -0500 Subject: [PATCH] ESFM: optimize osc buf --- src/engine/dispatch.h | 24 ++++++++++++------ src/engine/platform/esfm.cpp | 47 ++++++++++++++++++++++++++++++++++++ src/engine/platform/esfm.h | 3 +++ src/gui/debugWindow.cpp | 3 +-- 4 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 69f49c12b..e633ac822 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -427,18 +427,20 @@ struct DivSamplePos { constexpr size_t OSCBUF_PREC=(sizeof(size_t)>=8)?16:16; constexpr size_t OSCBUF_MASK=(UINTMAX_C(1)<data[_pos]=_val; + // the actual output of all DivDispatchOscBuffer instanced runs at 65536Hz. struct DivDispatchOscBuffer { size_t rate; size_t rateMul; unsigned int needle; unsigned short readNeedle; - unsigned short followNeedle; - unsigned short lastSample; + //unsigned short lastSample; bool follow; short data[65536]; - inline void putSample(size_t pos, short val) { + inline void putSample(const size_t pos, const short val) { unsigned short realPos=((needle+pos*rateMul)>>OSCBUF_PREC); if (val==-1) { data[realPos]=0xfffe; @@ -447,6 +449,16 @@ struct DivDispatchOscBuffer { //lastSample=val; data[realPos]=val; } + /* + inline void putSampleIKnowWhatIAmDoing(const unsigned short pos, const short val) { + //unsigned short realPos=((needle+pos*rateMul)>>OSCBUF_PREC); + if (val==-1) { + data[pos]=0xfffe; + return; + } + //lastSample=val; + data[pos]=val; + }*/ inline void begin(unsigned short len) { size_t calc=(len*rateMul); unsigned short start=needle>>16; @@ -473,8 +485,7 @@ struct DivDispatchOscBuffer { memset(data,-1,65536*sizeof(short)); needle=0; readNeedle=0; - followNeedle=0; - lastSample=0; + //lastSample=0; } void setRate(unsigned int r) { double rateMulD=65536.0/(double)r; @@ -487,8 +498,7 @@ struct DivDispatchOscBuffer { rateMul(UINTMAX_C(1)<needle; + for (int i=0; i<18; i++) { + oscBuf[i]->begin(len); + } + size_t pos=off; + for (size_t h=0; h>OSCBUF_PREC; + for (int c=0; c<18; c++) { + putSampleIKnowWhatIAmDoing(oscBuf[c],shiftedNeedlePos,ESFM_get_channel_output_native(&chip,c)); + } + sharedNeedlePos+=oscBuf[0]->rateMul; + + if (o[0]!=oldOut[0]) { + blip_add_delta(bb[0],pos,oldOut[0]-o[0]); + oldOut[0]=o[0]; + } + if (o[1]!=oldOut[1]) { + blip_add_delta(bb[1],pos,oldOut[1]-o[1]); + oldOut[1]=o[1]; + } + + pos++; + } + for (int i=0; i<18; i++) { + oscBuf[i]->end(len); + } +} + void DivPlatformESFM::tick(bool sysTick) { for (int i=0; i<18; i++) { chan[i].std.next(); @@ -1024,6 +1064,9 @@ void DivPlatformESFM::reset() { chan[i].vol=0x3f; chan[i].outVol=0x3f; } + + oldOut[0]=0; + oldOut[1]=0; } int DivPlatformESFM::getOutputCount() { @@ -1038,6 +1081,10 @@ bool DivPlatformESFM::keyOffAffectsPorta(int ch) { return false; } +bool DivPlatformESFM::hasAcquireDirect() { + return true; +} + bool DivPlatformESFM::getLegacyAlwaysSetVolume() { return false; } diff --git a/src/engine/platform/esfm.h b/src/engine/platform/esfm.h index e9d5863b5..df7fcc068 100644 --- a/src/engine/platform/esfm.h +++ b/src/engine/platform/esfm.h @@ -120,6 +120,7 @@ class DivPlatformESFM: public DivDispatch { }; FixedQueue writes; esfm_chip chip; + short oldOut[2]; bool isFast; unsigned char regPool[ESFM_REG_POOL_SIZE]; @@ -180,6 +181,7 @@ class DivPlatformESFM: public DivDispatch { public: void acquire(short** buf, size_t len); + void acquireDirect(blip_buffer_t** bb, size_t off, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -194,6 +196,7 @@ class DivPlatformESFM: public DivDispatch { void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); bool keyOffAffectsPorta(int ch); + bool hasAcquireDirect(); bool getLegacyAlwaysSetVolume(); void toggleRegisterDump(bool enable); void notifyInsChange(int ins); diff --git a/src/gui/debugWindow.cpp b/src/gui/debugWindow.cpp index 15f17f851..e6c8673a3 100644 --- a/src/gui/debugWindow.cpp +++ b/src/gui/debugWindow.cpp @@ -276,10 +276,9 @@ void FurnaceGUI::drawDebug() { ImGui::Checkbox(fmt::sprintf("##%d_OSCFollow_%d",i,c).c_str(),&oscBuf->follow); // address ImGui::TableNextColumn(); - int needle=oscBuf->follow?oscBuf->needle:oscBuf->followNeedle; + int needle=oscBuf->needle; ImGui::BeginDisabled(oscBuf->follow); if (ImGui::InputInt(fmt::sprintf("##%d_OSCFollowNeedle_%d",i,c).c_str(),&needle,1,100)) { - oscBuf->followNeedle=MIN(MAX(needle,0),65535); } ImGui::EndDisabled(); // data