From bdcbab09213818118473130600d8b47b2880c452 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 9 May 2023 05:05:53 -0500 Subject: [PATCH] prepare to fix MIDI clock --- src/engine/engine.cpp | 27 ++++++++++++++++++++++--- src/engine/engine.h | 8 ++++++++ src/engine/platform/snes.cpp | 1 + src/engine/playback.cpp | 39 ++++++++++++++++++++++++++++++------ 4 files changed, 66 insertions(+), 9 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 2b5237b40..b83c68a6b 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -2034,6 +2034,10 @@ String DivEngine::getPlaybackDebugInfo() { "divider: %f\n" "cycles: %d\n" "clockDrift: %f\n" + "midiClockCycles: %d\n" + "midiClockDrift: %f\n" + "midiTimeCycles: %d\n" + "midiTimeDrift: %d\n" "changeOrd: %d\n" "changePos: %d\n" "totalSeconds: %d\n" @@ -2048,8 +2052,9 @@ String DivEngine::getPlaybackDebugInfo() { "totalProcessed: %d\n" "bufferPos: %d\n", curOrder,prevOrder,curRow,prevRow,ticks,subticks,totalLoops,lastLoopPos,nextSpeed,divider,cycles,clockDrift, - changeOrd,changePos,totalSeconds,totalTicks,totalTicksR,totalCmds,lastCmds,cmdsPerSecond,globalPitch, - (int)extValue,(int)tempoAccum,(int)totalProcessed,(int)bufferPos + midiClockCycles,midiClockDrift,midiTimeCycles,midiTimeDrift,changeOrd,changePos,totalSeconds,totalTicks, + totalTicksR,totalCmds,lastCmds,cmdsPerSecond,globalPitch,(int)extValue,(int)tempoAccum,(int)totalProcessed, + (int)bufferPos ); } @@ -2165,10 +2170,16 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) { prevOrder=0; prevRow=0; stepPlay=0; - int prevDrift; + int prevDrift, prevMidiClockDrift, prevMidiTimeDrift; prevDrift=clockDrift; + prevMidiClockDrift=midiClockDrift; + prevMidiTimeDrift=midiTimeDrift; clockDrift=0; cycles=0; + midiClockCycles=0; + midiClockDrift=0; + midiTimeCycles=0; + midiTimeDrift=0; if (!preserveDrift) { ticks=1; tempoAccum=0; @@ -2211,9 +2222,15 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) { repeatPattern=oldRepeatPattern; if (preserveDrift) { clockDrift=prevDrift; + midiClockDrift=prevMidiClockDrift; + midiTimeDrift=prevMidiTimeDrift; } else { clockDrift=0; cycles=0; + midiClockCycles=0; + midiClockDrift=0; + midiTimeCycles=0; + midiTimeDrift=0; } if (!preserveDrift) { ticks=1; @@ -4367,6 +4384,10 @@ void DivEngine::quitDispatch() { } cycles=0; clockDrift=0; + midiClockCycles=0; + midiClockDrift=0; + midiTimeCycles=0; + midiTimeDrift=0; chans=0; playing=false; curSpeed=0; diff --git a/src/engine/engine.h b/src/engine/engine.h index 96be99551..4e7d44de5 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -378,6 +378,10 @@ class DivEngine { double divider; int cycles; double clockDrift; + int midiClockCycles; + double midiClockDrift; + int midiTimeCycles; + double midiTimeDrift; int stepPlay; int changeOrd, changePos, totalSeconds, totalTicks, totalTicksR, totalCmds, lastCmds, cmdsPerSecond, globalPitch; unsigned char extValue, pendingMetroTick; @@ -1146,6 +1150,10 @@ class DivEngine { divider(60), cycles(0), clockDrift(0), + midiClockCycles(0), + midiClockDrift(0), + midiTimeCycles(0), + midiTimeDrift(0), stepPlay(0), changeOrd(-1), changePos(0), diff --git a/src/engine/platform/snes.cpp b/src/engine/platform/snes.cpp index a5684d0e8..21ae97b8d 100644 --- a/src/engine/platform/snes.cpp +++ b/src/engine/platform/snes.cpp @@ -202,6 +202,7 @@ void DivPlatformSNES::tick(bool sysTick) { } } for (int i=0; i<8; i++) { + // TODO: if wavetable length is higher than 32, we lose precision! if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { DivSample* s=parent->getSample(chan[i].sample); double off=(s->centerRate>=1)?((double)s->centerRate/8363.0):1.0; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index b53af4b70..93a9338a7 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -1317,11 +1317,6 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { if (--subticks<=0) { subticks=tickMult; - // MIDI clock - if (output) if (!skipping && output->midiOut!=NULL && midiOutClock) { - output->midiOut->send(TAMidiMessage(TA_MIDI_CLOCK,0,0)); - } - if (stepPlay!=1) { tempoAccum+=curSubSong->virtualTempoN; while (tempoAccum>=curSubSong->virtualTempoD) { @@ -1835,7 +1830,39 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi pendingMetroTick=0; } } else { - // 3. tick the clock and fill buffers as needed + // 3. run MIDI clock + for (int i=0; imidiOut!=NULL && midiOutClock) { + output->midiOut->send(TAMidiMessage(TA_MIDI_CLOCK,0,0)); + } + + double hl=curSubSong->hilightA; + if (hl<=0.0) hl=4.0; + double timeBase=curSubSong->timeBase+1; + double speedSum=0; + double vD=curSubSong->virtualTempoD; + for (int i=0; ivirtualTempoN/vD; + logV("bpm: %f %f",bpm,divider); + + midiClockCycles=got.rate*pow(2,MASTER_CLOCK_PREC)/(bpm); + midiClockDrift+=fmod(got.rate*pow(2,MASTER_CLOCK_PREC),(double)(bpm)); + if (midiClockDrift>=(bpm)) { + midiClockDrift-=(bpm); + midiClockCycles++; + } + } + } + + // 4. tick the clock and fill buffers as needed if (cycles