From 02e9edbad93bd02d233bb8601b6de5b5382da4b9 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 15 Mar 2022 23:30:15 -0500 Subject: [PATCH] unlock the power of DECIMAL HZ! --- src/engine/engine.cpp | 15 ++++++++------- src/engine/engine.h | 13 ++++++++----- src/engine/fileOps.cpp | 4 ++-- src/engine/playback.cpp | 4 ++-- src/engine/song.h | 6 +++--- src/gui/gui.cpp | 28 ++++++++++++++++------------ src/gui/gui.h | 2 ++ 7 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 0bbf4cb4..cd7eb3ea 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1095,18 +1095,18 @@ unsigned char DivEngine::getSpeed2() { return speed2; } -int DivEngine::getHz() { +float DivEngine::getHz() { if (song.customTempo) { return song.hz; } else if (song.pal) { - return 60; + return 60.0; } else { - return 50; + return 50.0; } - return 60; + return 60.0; } -int DivEngine::getCurHz() { +float DivEngine::getCurHz() { return divider; } @@ -2216,11 +2216,12 @@ void DivEngine::setSysFlags(int system, unsigned int flags, bool restart) { isBusy.unlock(); } -void DivEngine::setSongRate(int hz, bool pal) { +void DivEngine::setSongRate(float hz, bool pal) { isBusy.lock(); song.pal=!pal; song.hz=hz; - song.customTempo=(song.hz!=50 && song.hz!=60); + // what? + song.customTempo=true; divider=60; if (song.customTempo) { divider=song.hz; diff --git a/src/engine/engine.h b/src/engine/engine.h index b4d5f7b6..9e31e563 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -182,8 +182,11 @@ class DivEngine { bool halted; bool forceMono; bool cmdStreamEnabled; - int ticks, curRow, curOrder, remainingLoops, nextSpeed, divider; - int cycles, clockDrift, stepPlay; + int ticks, curRow, curOrder, remainingLoops, nextSpeed; + double divider; + int cycles; + double clockDrift; + int stepPlay; int changeOrd, changePos, totalSeconds, totalTicks, totalTicksR, totalCmds, lastCmds, cmdsPerSecond, globalPitch; unsigned char extValue; unsigned char speed1, speed2; @@ -431,10 +434,10 @@ class DivEngine { unsigned char getSpeed2(); // get Hz - int getHz(); + float getHz(); // get current Hz - int getCurHz(); + float getCurHz(); // get time int getTotalTicks(); // 1/1000000th of a second @@ -526,7 +529,7 @@ class DivEngine { void setSysFlags(int system, unsigned int flags, bool restart); // set Hz - void setSongRate(int hz, bool pal); + void setSongRate(float hz, bool pal); // set remaining loops. -1 means loop forever. void setLoops(int loops); diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index dd1e8ad1..a47be934 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -841,7 +841,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { ds.arpLen=reader.readC(); ds.hz=reader.readF(); ds.pal=(ds.hz>=53); - if (ds.hz!=50 && ds.hz!=60) ds.customTempo=true; + ds.customTempo=true; ds.patLen=reader.readS(); ds.ordersLen=reader.readS(); @@ -2064,7 +2064,7 @@ SafeWriter* DivEngine::saveDMF(unsigned char version) { w->writeC(song.customTempo); char customHz[4]; memset(customHz,0,4); - snprintf(customHz,4,"%d",song.hz); + snprintf(customHz,4,"%d",(int)song.hz); w->write(customHz,3); w->writeI(song.patLen); w->writeC(song.ordersLen); diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index b92339d7..65480a58 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -946,7 +946,7 @@ void DivEngine::processRow(int i, bool afterDelay) { globalPitch+=(signed char)(effectVal-0x80); break; case 0xf0: // set Hz by tempo - divider=(effectVal*2+2)/5; + divider=(double)effectVal*2.0/5.0; if (divider<10) divider=10; cycles=((int)(got.rate)<=divider) { clockDrift-=divider; cycles++; diff --git a/src/engine/song.h b/src/engine/song.h index 5cedb184..6799909d 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -271,8 +271,8 @@ struct DivSong { unsigned char timeBase, speed1, speed2, arpLen; bool pal; bool customTempo; - // TODO: change Hz to float? - int hz, patLen, ordersLen, insLen, waveLen, sampleLen; + float hz; + int patLen, ordersLen, insLen, waveLen, sampleLen; float masterVol; float tuning; @@ -345,7 +345,7 @@ struct DivSong { arpLen(1), pal(true), customTempo(false), - hz(60), + hz(60.0), patLen(64), ordersLen(1), insLen(0), diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 809c61fe..352c7330 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -666,6 +666,16 @@ void FurnaceGUI::prepareLayout() { fclose(check); } +float FurnaceGUI::calcBPM(int s1, int s2, float hz) { + float hl=e->song.hilightA; + if (hl<=0.0f) hl=4.0f; + float timeBase=e->song.timeBase+1; + float speedSum=s1+s2; + if (timeBase<1.0f) timeBase=1.0f; + if (speedSum<1.0f) speedSum=1.0f; + return 120.0f*hz/(timeBase*hl*speedSum); +} + void FurnaceGUI::drawEditControls() { if (nextWindow==GUI_WINDOW_EDIT_CONTROLS) { editControlsOpen=true; @@ -1020,13 +1030,7 @@ void FurnaceGUI::drawSongInfo() { e->song.timeBase=realTB-1; } ImGui::TableNextColumn(); - float hl=e->song.hilightA; - if (hl<=0.0f) hl=4.0f; - float timeBase=e->song.timeBase+1; - float speedSum=e->song.speed1+e->song.speed2; - if (timeBase<1.0f) timeBase=1.0f; - if (speedSum<1.0f) speedSum=1.0f; - ImGui::Text("%.2f BPM",120.0f*(float)e->song.hz/(timeBase*hl*speedSum)); + ImGui::Text("%.2f BPM",calcBPM(e->song.speed1,e->song.speed2,e->song.hz)); ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -1083,17 +1087,17 @@ void FurnaceGUI::drawSongInfo() { ImGui::Text("Tick Rate"); ImGui::TableNextColumn(); ImGui::SetNextItemWidth(avail); - int setHz=e->song.hz; - if (ImGui::InputInt("##Rate",&setHz)) { + float setHz=e->song.hz; + if (ImGui::InputFloat("##Rate",&setHz,1.0f,1.0f,"%g")) { if (setHz<10) setHz=10; if (setHz>999) setHz=999; e->setSongRate(setHz,setHz<52); } - if (e->song.hz==50) { + if (e->song.hz>=49.98 && e->song.hz<=50.02) { ImGui::TableNextColumn(); ImGui::Text("PAL"); } - if (e->song.hz==60) { + if (e->song.hz>=59.9 && e->song.hz<=60.11) { ImGui::TableNextColumn(); ImGui::Text("NTSC"); } @@ -6078,7 +6082,7 @@ bool FurnaceGUI::loop() { if (e->isPlaying()) { int totalTicks=e->getTotalTicks(); int totalSeconds=e->getTotalSeconds(); - ImGui::Text("| Speed %d:%d @ %dHz | Order %d/%d | Row %d/%d | %d:%.2d:%.2d.%.2d",e->getSpeed1(),e->getSpeed2(),e->getCurHz(),e->getOrder(),e->song.ordersLen,e->getRow(),e->song.patLen,totalSeconds/3600,(totalSeconds/60)%60,totalSeconds%60,totalTicks/10000); + ImGui::Text("| Speed %d:%d @ %gHz (%g BPM) | Order %d/%d | Row %d/%d | %d:%.2d:%.2d.%.2d",e->getSpeed1(),e->getSpeed2(),e->getCurHz(),calcBPM(e->getSpeed1(),e->getSpeed2(),e->getCurHz()),e->getOrder(),e->song.ordersLen,e->getRow(),e->song.patLen,totalSeconds/3600,(totalSeconds/60)%60,totalSeconds%60,totalTicks/10000); } else { bool hasInfo=false; String info; diff --git a/src/gui/gui.h b/src/gui/gui.h index b0812b38..72255440 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -719,6 +719,8 @@ class FurnaceGUI { void updateWindowTitle(); void prepareLayout(); + float calcBPM(int s1, int s2, float hz); + void patternRow(int i, bool isPlaying, float lineHeight, int chans, int ord); void actualWaveList();