diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index b6bb98de4..153923c0c 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -775,7 +775,7 @@ int DivEngine::duplicateSubSong(int index) { theCopy->notes=theOrig->notes; theCopy->hilightA=theOrig->hilightA; theCopy->hilightB=theOrig->hilightB; - theCopy->timeBase=theOrig->timeBase; + theCopy->effectDivider=theOrig->effectDivider; theCopy->arpLen=theOrig->arpLen; theCopy->speeds=theOrig->speeds; theCopy->virtualTempoN=theOrig->virtualTempoN; diff --git a/src/engine/fileOps/dmf.cpp b/src/engine/fileOps/dmf.cpp index a009848bc..98f2edecb 100644 --- a/src/engine/fileOps/dmf.cpp +++ b/src/engine/fileOps/dmf.cpp @@ -256,11 +256,11 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { bool customTempo=false; - ds.subsong[0]->timeBase=reader.readC(); + unsigned char oldTimeBase=reader.readC(); ds.subsong[0]->speeds.len=2; - ds.subsong[0]->speeds.val[0]=reader.readC(); + ds.subsong[0]->speeds.val[0]=(unsigned char)reader.readC(); if (ds.version>0x07) { - ds.subsong[0]->speeds.val[1]=reader.readC(); + ds.subsong[0]->speeds.val[1]=(unsigned char)reader.readC(); bool pal=reader.readC(); ds.subsong[0]->hz=pal?60:50; customTempo=reader.readC(); @@ -317,7 +317,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { } if (ds.system[0]==DIV_SYSTEM_YMU759) { - switch (ds.subsong[0]->timeBase) { + switch (oldTimeBase) { case 0: ds.subsong[0]->hz=248; break; @@ -340,8 +340,10 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { ds.subsong[0]->hz=248; break; } - ds.subsong[0]->timeBase=0; addWarning("Yamaha YMU759 emulation is incomplete! please migrate your song to the OPL3 system."); + } else { + ds.subsong[0]->speeds.val[0]*=(oldTimeBase+1); + ds.subsong[0]->speeds.val[1]*=(oldTimeBase+1); } logV("%x",reader.tell()); @@ -1346,7 +1348,7 @@ SafeWriter* DivEngine::saveDMF(unsigned char version) { int intHz=curSubSong->hz; - w->writeC(curSubSong->timeBase); + w->writeC(0); w->writeC(curSubSong->speeds.val[0]); w->writeC((curSubSong->speeds.len>=2)?curSubSong->speeds.val[1]:curSubSong->speeds.val[0]); w->writeC((intHz<=53)?0:1); diff --git a/src/engine/fileOps/fur.cpp b/src/engine/fileOps/fur.cpp index 34ca3c62e..12b5c6826 100644 --- a/src/engine/fileOps/fur.cpp +++ b/src/engine/fileOps/fur.cpp @@ -1077,7 +1077,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len, int variantID) { } reader.readI(); - subSong->timeBase=reader.readC(); + unsigned char oldTimeBase=reader.readC(); subSong->speeds.len=2; subSong->speeds.val[0]=(unsigned char)reader.readC(); subSong->speeds.val[1]=(unsigned char)reader.readC(); @@ -1641,6 +1641,10 @@ bool DivEngine::loadFur(unsigned char* file, size_t len, int variantID) { } } + for (int i=0; i<16; i++) { + subSong->speeds.val[i]*=(oldTimeBase+1); + } + if (ds.version>=156) { assetDirPtr.push_back(reader.readI()); assetDirPtr.push_back(reader.readI()); diff --git a/src/engine/fileOps/text.cpp b/src/engine/fileOps/text.cpp index bab5dc7ea..8b12c2482 100644 --- a/src/engine/fileOps/text.cpp +++ b/src/engine/fileOps/text.cpp @@ -296,7 +296,6 @@ SafeWriter* DivEngine::saveText(bool separatePatterns) { } w->writeText("\n"); w->writeText(fmt::sprintf("- virtual tempo: %d/%d\n",s->virtualTempoN,s->virtualTempoD)); - w->writeText(fmt::sprintf("- time base: %d\n",s->timeBase)); w->writeText(fmt::sprintf("- pattern length: %d\n",s->patLen)); w->writeText(fmt::sprintf("\norders:\n```\n")); diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index a59fb3c8d..687a0ef9d 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -705,12 +705,12 @@ void DivEngine::processRow(int i, bool afterDelay) { if (effectVal!=0) { // COMPAT FLAG: cut/delay effect policy (delayBehavior) // - 0: strict - // - delays equal or greater to the speed * timeBase are ignored + // - delays equal or greater to the speed are ignored (formerly time base was involved but that has been removed now) // - 1: strict old - // - delays equal or greater to the speed are ignored + // - delays greater to the speed are ignored // - 2: lax (default) // - no delay is ever ignored unless overridden by another - bool comparison=(song.compatFlags.delayBehavior==1)?(effectVal<=nextSpeed):(effectVal<(nextSpeed*(curSubSong->timeBase+1))); + bool comparison=(song.compatFlags.delayBehavior==1)?(effectVal<=nextSpeed):(effectVal<(nextSpeed)); if (song.compatFlags.delayBehavior==2) comparison=true; if (comparison) { // set the delay row, order and timer @@ -1868,16 +1868,16 @@ void DivEngine::nextRow() { // if the pattern length is odd and the current order is odd, use speed 2 for even rows and speed 1 for odd ones if ((curSubSong->patLen&1) && curOrder&1) { - ticks=((curRow&1)?speed2:speed1)*(curSubSong->timeBase+1); + ticks=((curRow&1)?speed2:speed1); nextSpeed=(curRow&1)?speed1:speed2; } else { - ticks=((curRow&1)?speed1:speed2)*(curSubSong->timeBase+1); + ticks=((curRow&1)?speed1:speed2); nextSpeed=(curRow&1)?speed2:speed1; } } else { // normal speed alternation // set the number of ticks and cycle to the next speed - ticks=speeds.val[curSpeed]*(curSubSong->timeBase+1); + ticks=speeds.val[curSpeed]; curSpeed++; if (curSpeed>=speeds.len) curSpeed=0; // cache the next speed for future operations @@ -2633,20 +2633,18 @@ void DivEngine::runMidiClock(int totalCycles) { output->midiOut->send(TAMidiMessage(TA_MIDI_CLOCK,0,0)); } - // calculate tempo using highlight, timeBase, tick rate, speeds and virtual tempo + // calculate tempo using highlight, tick rate, speeds and virtual tempo double hl=curSubSong->hilightA; if (hl<=0.0) hl=4.0; - double timeBase=curSubSong->timeBase+1; double speedSum=0; double vD=virtualTempoD; for (int i=0; i& groove if (effectVal!=0) { // COMPAT FLAG: cut/delay effect policy (delayBehavior) // - 0: strict - // - delays equal or greater to the speed * timeBase are ignored + // - delays equal or greater to the speed are ignored (formerly time base was involved but that has been removed now) // - 1: strict old - // - delays equal or greater to the speed are ignored + // - delays greater to the speed are ignored // - 2: lax (default) // - no delay is ever ignored unless overridden by another - bool comparison=(delayBehavior==1)?(effectVal<=nextSpeed):(effectVal<(nextSpeed*(timeBase+1))); + bool comparison=(delayBehavior==1)?(effectVal<=nextSpeed):(effectVal<(nextSpeed)); if (delayBehavior==2) comparison=true; if (comparison) { // set the delay row, order and timer @@ -327,16 +327,16 @@ void DivSubSong::calcTimestamps(int chans, std::vector& groove // we subtract firstPat from curOrder as firstPat is used by a function which finds sub-songs // (the beginning of a new sub-song will be in order 0) if ((patLen&1) && (curOrder-firstPat)&1) { - ticks=((curRow&1)?speed2:speed1)*(timeBase+1); + ticks=((curRow&1)?speed2:speed1); nextSpeed=(curRow&1)?speed1:speed2; } else { - ticks=((curRow&1)?speed1:speed2)*(timeBase+1); + ticks=((curRow&1)?speed1:speed2); nextSpeed=(curRow&1)?speed2:speed1; } } else { // normal speed alternation // set the number of ticks and cycle to the next speed - ticks=curSpeeds.val[curSpeed]*(timeBase+1); + ticks=curSpeeds.val[curSpeed]; curSpeed++; if (curSpeed>=curSpeeds.len) curSpeed=0; // cache the next speed for future operations @@ -465,7 +465,7 @@ bool DivSubSong::readData(SafeReader& reader, int version, int chans) { hz=reader.readF(); arpLen=reader.readC(); - timeBase=reader.readC(); + effectDivider=reader.readC(); patLen=reader.readS(); ordersLen=reader.readS(); @@ -519,7 +519,7 @@ bool DivSubSong::readData(SafeReader& reader, int version, int chans) { } reader.readI(); - timeBase=reader.readC(); + unsigned char oldTimeBase=reader.readC(); speeds.len=2; speeds.val[0]=(unsigned char)reader.readC(); speeds.val[1]=(unsigned char)reader.readC(); @@ -582,6 +582,10 @@ bool DivSubSong::readData(SafeReader& reader, int version, int chans) { speeds.val[i]=(unsigned char)reader.readC(); } } + + for (int i=0; i<16; i++) { + speeds.val[i]*=(oldTimeBase+1); + } } return true; @@ -595,7 +599,7 @@ void DivSubSong::putData(SafeWriter* w, int chans) { w->writeF(hz); w->writeC(arpLen); - w->writeC(timeBase); + w->writeC(effectDivider); w->writeS(patLen); w->writeS(ordersLen); w->writeC(hilightA); @@ -819,7 +823,7 @@ void DivSong::findSubSongs() { theCopy->notes=i->notes; theCopy->hilightA=i->hilightA; theCopy->hilightB=i->hilightB; - theCopy->timeBase=i->timeBase; + theCopy->effectDivider=i->effectDivider; theCopy->arpLen=i->arpLen; theCopy->speeds=i->speeds; theCopy->virtualTempoN=i->virtualTempoN; diff --git a/src/engine/song.h b/src/engine/song.h index e8499700b..7c2745d1d 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -226,7 +226,7 @@ struct DivSongTimestamps { struct DivSubSong { String name, notes; unsigned char hilightA, hilightB; - unsigned char timeBase, arpLen; + unsigned char effectDivider, arpLen; DivGroovePattern speeds; short virtualTempoN, virtualTempoD; float hz; @@ -269,7 +269,7 @@ struct DivSubSong { DivSubSong(): hilightA(4), hilightB(16), - timeBase(0), + effectDivider(0), arpLen(1), virtualTempoN(150), virtualTempoD(150), diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index e80930911..5573b94fe 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1295,16 +1295,14 @@ void FurnaceGUI::prepareLayout() { float FurnaceGUI::calcBPM(const DivGroovePattern& speeds, float hz, int vN, int vD) { float hl=e->curSubSong->hilightA; if (hl<=0.0f) hl=4.0f; - float timeBase=e->curSubSong->timeBase+1; float speedSum=0; for (int i=0; icurSubSong->timeBase+1; if (ImGui::InputScalar("##TimeBase",ImGuiDataType_U8,&realTB,&_ONE,&_THREE)) { MARK_MODIFIED @@ -210,6 +212,7 @@ void FurnaceGUI::drawSpeed(bool asChild) { recalcTimestamps=true; } ImGui::SameLine(); + */ ImGui::Text("%.2f BPM",calcBPM(e->curSubSong->speeds,e->curSubSong->hz,e->curSubSong->virtualTempoN,e->curSubSong->virtualTempoD)); ImGui::TableNextRow();