From 4723ed3972a54a4af81908196b3f883a38f31779 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 17 Oct 2022 14:25:30 -0500 Subject: [PATCH] VGM: experimental direct stream mode for YM2612 --- src/engine/dispatch.h | 3 +++ src/engine/platform/genesis.cpp | 32 +++++++++++++++++++++--------- src/engine/platform/genesis.h | 3 ++- src/engine/vgmOps.cpp | 35 +++++++++++++++++++++++++++++++++ src/main.cpp | 9 ++++++++- 5 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index ffd9e247..4c9fb2f2 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -264,6 +264,9 @@ struct DivRegWrite { struct DivDelayedWrite { int time; DivRegWrite write; + DivDelayedWrite(int t, unsigned int a, unsigned short v): + time(t), + write(a,v) {} }; struct DivDispatchOscBuffer { diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 480ecb44..0eb4aebb 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -27,11 +27,11 @@ #define IS_REALLY_MUTED(x) (isMuted[x] && (x<5 || !softPCM || (isMuted[5] && isMuted[6]))) -void DivPlatformGenesis::processDAC() { +void DivPlatformGenesis::processDAC(int iRate) { if (softPCM) { softPCMTimer+=chipClock/576; - if (softPCMTimer>rate) { - softPCMTimer-=rate; + if (softPCMTimer>iRate) { + softPCMTimer-=iRate; int sample=0; for (int i=5; i<7; i++) { @@ -75,14 +75,14 @@ void DivPlatformGenesis::processDAC() { } else { if (!chan[5].dacReady) { chan[5].dacDelay+=32000; - if (chan[5].dacDelay>=rate) { - chan[5].dacDelay-=rate; + if (chan[5].dacDelay>=iRate) { + chan[5].dacDelay-=iRate; chan[5].dacReady=true; } } if (chan[5].dacMode && chan[5].dacSample!=-1) { chan[5].dacPeriod+=chan[5].dacRate; - if (chan[5].dacPeriod>=rate) { + if (chan[5].dacPeriod>=iRate) { DivSample* s=parent->getSample(chan[5].dacSample); if (s->samples>0) { if (!isMuted[5]) { @@ -106,7 +106,7 @@ void DivPlatformGenesis::processDAC() { rWrite(0x2b,0); } } - while (chan[5].dacPeriod>=rate) chan[5].dacPeriod-=rate; + while (chan[5].dacPeriod>=iRate) chan[5].dacPeriod-=iRate; } else { chan[5].dacSample=-1; } @@ -120,7 +120,7 @@ void DivPlatformGenesis::acquire_nuked(short* bufL, short* bufR, size_t start, s static int os[2]; for (size_t h=start; hdebug_engine(); for (size_t h=start; h& stream, int sRate, size_t len) { + while (!writes.empty()) writes.pop_front(); + for (size_t i=0; i& stream, int sRate, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 582eafbd..01d01ac8 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -948,6 +948,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p bool sampleDir[DIV_MAX_CHANS]; std::vector chipVol; std::vector delayedWrites[32]; + std::vector> sortedWrites; for (int i=0; i>MASTER_CLOCK_PREC; if (directStream) { + // render stream of all chips for (int i=0; ifillStream(delayedWrites[i],44100,totalWait); + for (DivDelayedWrite& j: delayedWrites[i]) { + sortedWrites.push_back(std::pair(i,j)); + } + delayedWrites[i].clear(); + } + + if (!sortedWrites.empty()) { + // sort if more than one chip + if (song.systemLen>1) { + std::sort(sortedWrites.begin(),sortedWrites.end(),[](const std::pair& a, const std::pair& b) -> bool { + return a.second.time& i: sortedWrites) { + if (i.second.time>lastOne) { + // write delay + int delay=i.second.time-lastOne; + if (delay>16) { + w->writeC(0x61); + w->writeS(totalWait); + } else if (delay>0) { + w->writeC(0x70+delay-1); + } + lastOne=i.second.time; + } + // write write + performVGMWrite(w,song.system[i.first],i.second.write,streamIDs[i.first],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i.first],directStream); + } + sortedWrites.clear(); + totalWait-=lastOne; } } else { for (int i=0; i params; @@ -122,6 +123,11 @@ TAParamResult pBinary(String val) { return TA_PARAM_SUCCESS; } +TAParamResult pDirect(String val) { + vgmOutDirect=true; + return TA_PARAM_SUCCESS; +} + TAParamResult pLogLevel(String val) { if (val=="trace") { logLevel=LOGLEVEL_TRACE; @@ -289,6 +295,7 @@ void initParams() { params.push_back(TAParam("a","audio",true,pAudio,"jack|sdl","set audio engine (SDL by default)")); params.push_back(TAParam("o","output",true,pOutput,"","output audio to file")); params.push_back(TAParam("O","vgmout",true,pVGMOut,"","output .vgm data")); + params.push_back(TAParam("D","direct",false,pDirect,"","set VGM export direct stream mode")); params.push_back(TAParam("Z","zsmout",true,pZSMOut,"","output .zsm data for Commander X16 Zsound")); params.push_back(TAParam("C","cmdout",true,pCmdOut,"","output command stream")); params.push_back(TAParam("b","binary",false,pBinary,"","set command stream output format to binary")); @@ -490,7 +497,7 @@ int main(int argc, char** argv) { } } if (vgmOutName!="") { - SafeWriter* w=e.saveVGM(); + SafeWriter* w=e.saveVGM(NULL,true,0x171,false,vgmOutDirect); if (w!=NULL) { FILE* f=fopen(vgmOutName.c_str(),"wb"); if (f!=NULL) {