diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index c9474f494..ee9f599ff 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -203,13 +203,10 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul void DivEngine::walkSong(int& loopOrder, int& loopRow, int& loopEnd) { if (curSubSong!=NULL) { - curSubSong->walk(loopOrder,loopRow,loopEnd,chans,song.jumpTreatment,song.ignoreJumpAtEnd); - } -} - -void DivEngine::findSongLength(int loopOrder, int loopRow, double fadeoutLen, int& rowsForFadeout, bool& hasFFxx, std::vector& orders, int& length) { - if (curSubSong!=NULL) { - curSubSong->findLength(loopOrder,loopRow,fadeoutLen,rowsForFadeout,hasFFxx,orders,song.grooves,length,chans,song.jumpTreatment,song.ignoreJumpAtEnd); + curSubSong->calcTimestamps(chans,song.grooves,song.jumpTreatment,song.ignoreJumpAtEnd,song.brokenSpeedSel,song.delayBehavior); + loopOrder=curSubSong->ts.loopStart.order; + loopRow=curSubSong->ts.loopStart.row; + loopEnd=curSubSong->ts.loopEnd.order; } } diff --git a/src/engine/engine.h b/src/engine/engine.h index c62b2d13b..c44121166 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -870,12 +870,9 @@ class DivEngine { int convertPanSplitToLinearLR(unsigned char left, unsigned char right, int range); unsigned int convertPanLinearToSplit(int val, unsigned char bits, int range); - // find song loop position + // DEPRECATED - find song loop position void walkSong(int& loopOrder, int& loopRow, int& loopEnd); - // find song length in rows (up to specified loop point), and find length of every order - void findSongLength(int loopOrder, int loopRow, double fadeoutLen, int& rowsForFadeout, bool& hasFFxx, std::vector& orders, int& length); - // calculate all song timestamps void calcSongTimestamps(); diff --git a/src/engine/song.cpp b/src/engine/song.cpp index 0552d9164..c2bf52263 100644 --- a/src/engine/song.cpp +++ b/src/engine/song.cpp @@ -47,256 +47,10 @@ DivSongTimestamps::~DivSongTimestamps() { } } } -bool DivSubSong::walk(int& loopOrder, int& loopRow, int& loopEnd, int chans, int jumpTreatment, int ignoreJumpAtEnd, int firstPat) { - loopOrder=0; - loopRow=0; - loopEnd=-1; - int nextOrder=-1; - int nextRow=0; - int effectVal=0; - int lastSuspectedLoopEnd=-1; - DivPattern* subPat[DIV_MAX_CHANS]; - unsigned char wsWalked[8192]; - memset(wsWalked,0,8192); - if (firstPat>0) { - memset(wsWalked,255,32*firstPat); - } - for (int i=firstPat; ilastSuspectedLoopEnd) { - lastSuspectedLoopEnd=i; - } - for (int j=nextRow; j>3))&8191]&(1<<(j&7))) { - loopOrder=i; - loopRow=j; - loopEnd=lastSuspectedLoopEnd; - return true; - } - for (int k=0; knewData[j][DIV_PAT_FXVAL(l)]; - if (effectVal<0) effectVal=0; - if (subPat[k]->newData[j][DIV_PAT_FX(l)]==0x0d) { - if (jumpTreatment==2) { - if ((inewData[j][DIV_PAT_FX(l)]==0x0b) { - if (nextOrder==-1 || jumpTreatment==0) { - nextOrder=effectVal; - if (jumpTreatment==1 || jumpTreatment==2 || !jumpingOrder) { - nextRow=0; - } - changingOrder=true; - } - } - } - } - - wsWalked[((i<<5)+(j>>3))&8191]|=1<<(j&7); - - if (nextOrder!=-1) { - i=nextOrder-1; - nextOrder=-1; - break; - } - } - } - return false; -} - -double calcRowLenInSeconds(const DivGroovePattern& speeds, float hz, int vN, int vD, int timeBaseFromSong) { - double hl=1; //count for 1 row - if (hl<=0.0) hl=4.0; - double timeBase=timeBaseFromSong+1; - double speedSum=0; - for (int i=0; i& orders_vec, std::vector& grooves, int& length, int chans, int jumpTreatment, int ignoreJumpAtEnd, int firstPat) { - length=0; - hasFFxx=false; - rowsForFadeout=0; - - float secondsPerThisRow=0.0f; - - DivGroovePattern curSpeeds=speeds; //simulate that we are playing the song, track all speed/BPM/tempo/engine rate changes - short curVirtualTempoN=virtualTempoN; - short curVirtualTempoD=virtualTempoD; - float curHz=hz; - double curDivider=(double)timeBase; - - double curLen=0.0; //how many seconds passed since the start of song - - int nextOrder=-1; - int nextRow=0; - int effectVal=0; - int lastSuspectedLoopEnd=-1; - DivPattern* subPat[DIV_MAX_CHANS]; - unsigned char wsWalked[8192]; - memset(wsWalked,0,8192); - if (firstPat>0) { - memset(wsWalked,255,32*firstPat); - } - for (int i=firstPat; ilastSuspectedLoopEnd) { - lastSuspectedLoopEnd=i; - } - for (int j=nextRow; j>3))&8191]&(1<<(j&7))) { - return; - } - for (int k=0; knewData[j][DIV_PAT_FXVAL(l)]; - if (effectVal<0) effectVal=0; - - if (subPat[k]->newData[j][DIV_PAT_FX(l)]==0xff) { - hasFFxx=true; - - // FFxx makes YOU SHALL NOT PASS!!! move - orders_vec.push_back(j+1); // order len - length+=j+1; // add length of order to song length - - return; - } - - switch (subPat[k]->newData[j][DIV_PAT_FX(l)]) { - case 0x09: { // select groove pattern/speed 1 - if (grooves.empty()) { - if (effectVal>0) curSpeeds.val[0]=effectVal; - } else { - if (effectVal<(short)grooves.size()) { - curSpeeds=grooves[effectVal]; - //curSpeed=0; - } - } - break; - } - case 0x0f: { // speed 1/speed 2 - if (curSpeeds.len==2 && grooves.empty()) { - if (effectVal>0) curSpeeds.val[1]=effectVal; - } else { - if (effectVal>0) curSpeeds.val[0]=effectVal; - } - break; - } - case 0xfd: { // virtual tempo num - if (effectVal>0) curVirtualTempoN=effectVal; - break; - } - case 0xfe: { // virtual tempo den - if (effectVal>0) curVirtualTempoD=effectVal; - break; - } - case 0xf0: { // set Hz by tempo (set bpm) - curDivider=(double)effectVal*2.0/5.0; - if (curDivider<1) curDivider=1; - break; - } - } - - if (subPat[k]->newData[j][DIV_PAT_FX(l)]==0x0d) { - if (jumpTreatment==2) { - if ((inewData[j][DIV_PAT_FX(l)]==0x0b) { - if (nextOrder==-1 || jumpTreatment==0) { - nextOrder=effectVal; - if (jumpTreatment==1 || jumpTreatment==2 || !jumpingOrder) { - nextRow=0; - } - changingOrder=true; - } - } - } - } - - if (i>loopOrder || (i==loopOrder && j>loopRow)) { - // we count each row fadeout lasts. When our time is greater than fadeout length we successfully counted the number of fadeout rows - if (curLen<=fadeoutLen && fadeoutLen>0.0) { - secondsPerThisRow=calcRowLenInSeconds(speeds,curHz,curVirtualTempoN,curVirtualTempoD,curDivider); - curLen+=secondsPerThisRow; - rowsForFadeout++; - } - } - - wsWalked[((i<<5)+(j>>3))&8191]|=1<<(j&7); - - if (nextOrder!=-1) { - i=nextOrder-1; - orders_vec.push_back(j+1); // order len - length+=j+1; // add length of order to song length - jumped=true; - nextOrder=-1; - break; - } - } - if (!jumped) { // if no jump occured we add full pattern length - orders_vec.push_back(patLen); // order len - length+=patLen; // add length of order to song length - } - } -} void DivSubSong::calcTimestamps(int chans, std::vector& grooves, int jumpTreatment, int ignoreJumpAtEnd, int brokenSpeedSel, int delayBehavior, int firstPat) { // reduced version of the playback routine for calculation. + std::chrono::high_resolution_clock::time_point timeStart=std::chrono::high_resolution_clock::now(); // reset state ts.totalSeconds=0; @@ -647,7 +401,7 @@ void DivSubSong::calcTimestamps(int chans, std::vector& groove if (!endOfSong) { // update playback time - double dt=divider*((double)virtualTempoN/(double)MAX(1,virtualTempoD)); + double dt=divider;//*((double)virtualTempoN/(double)MAX(1,virtualTempoD)); ts.totalTicks++; ts.totalMicros+=1000000/dt; @@ -669,6 +423,9 @@ void DivSubSong::calcTimestamps(int chans, std::vector& groove ts.loopStart.order=prevOrder; ts.loopStart.row=prevRow; ts.loopStartTime=ts.getTimes(ts.loopStart.order,ts.loopStart.row); + + std::chrono::high_resolution_clock::time_point timeEnd=std::chrono::high_resolution_clock::now(); + logV("calcTimestamps() took %dµs",std::chrono::duration_cast(timeEnd-timeStart).count()); } void DivSubSong::clearData() { @@ -802,24 +559,22 @@ void DivSong::findSubSongs(int chans) { for (DivSubSong* i: subsong) { std::vector subSongStart; std::vector subSongEnd; - int loopOrder=0; - int loopRow=0; - int loopEnd=-1; int curStart=-1; // find possible subsongs logD("finding subsongs..."); while (++curStartordersLen) { - if (!i->walk(loopOrder,loopRow,loopEnd,chans,jumpTreatment,ignoreJumpAtEnd,curStart)) break; + i->calcTimestamps(chans,grooves,jumpTreatment,ignoreJumpAtEnd,brokenSpeedSel,delayBehavior,curStart); + if (!i->ts.isLoopable) break; // make sure we don't pick the same range twice if (!subSongEnd.empty()) { - if (subSongEnd.back()==loopEnd) continue; + if (subSongEnd.back()==i->ts.loopEnd.order) continue; } - logV("found a subsong: %d-%d",curStart,loopEnd); + logV("found a subsong: %d-%d",curStart,i->ts.loopEnd.order); subSongStart.push_back(curStart); - subSongEnd.push_back(loopEnd); + subSongEnd.push_back(i->ts.loopEnd.order); } // if this is the only song, quit diff --git a/src/engine/song.h b/src/engine/song.h index 302519615..d3fca3a64 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -230,16 +230,6 @@ struct DivSubSong { // song timestamps DivSongTimestamps ts; - /** - * walk through the song and determine loop position. - */ - bool walk(int& loopOrder, int& loopRow, int& loopEnd, int chans, int jumpTreatment, int ignoreJumpAtEnd, int firstPat=0); - - /** - * find song length in rows (up to specified loop point). - */ - void findLength(int loopOrder, int loopRow, double fadeoutLen, int& rowsForFadeout, bool& hasFFxx, std::vector& orders, std::vector& grooves, int& length, int chans, int jumpTreatment, int ignoreJumpAtEnd, int firstPat=0); - /** * calculate timestamps (loop position, song length and more). */ diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 1df5551ce..1e20e46ce 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2717,20 +2717,15 @@ int FurnaceGUI::loadStream(String path) { void FurnaceGUI::exportAudio(String path, DivAudioExportModes mode) { - songOrdersLengths.clear(); - int loopOrder=0; int loopRow=0; int loopEnd=0; e->walkSong(loopOrder,loopRow,loopEnd); - e->findSongLength(loopOrder,loopRow,audioExportOptions.fadeOut,songFadeoutSectionLength,songHasSongEndCommand,songOrdersLengths,songLength); // for progress estimation - - songLoopedSectionLength=songLength; - for (int i=0; icurSubSong->ts.isLoopable; + songLength=e->curSubSong->ts.totalRows; e->saveAudio(path.c_str(),audioExportOptions); @@ -6039,43 +6034,21 @@ bool FurnaceGUI::loop() { float* progressLambda=&curProgress; int curPosInRows=0; int* curPosInRowsLambda=&curPosInRows; - int loopsLeft=0; - int* loopsLeftLambda=&loopsLeft; - int totalLoops=0; - int* totalLoopsLambda=&totalLoops; int curFile=0; int* curFileLambda=&curFile; if (e->isExporting()) { e->lockEngine( - [this, progressLambda, curPosInRowsLambda, curFileLambda, loopsLeftLambda, totalLoopsLambda] () { - int curRow=0; int curOrder=0; - e->getCurSongPos(curRow, curOrder); + [this, progressLambda, curPosInRowsLambda, curFileLambda] () { *curFileLambda=0; e->getCurFileIndex(*curFileLambda); - *curPosInRowsLambda=curRow; - for (int i=0; igetLoopsLeft(*loopsLeftLambda); - e->getTotalLoops(*totalLoopsLambda); - if ((*totalLoopsLambda)!=(*loopsLeftLambda)) { // we are going 2nd, 3rd, etc. time through the song - *curPosInRowsLambda-=(songLength-songLoopedSectionLength); // a hack so progress bar does not jump? - } - if (e->getIsFadingOut()) { // we are in fadeout??? why it works like that bruh - // LIVE WITH IT damn it - *curPosInRowsLambda-=(songLength-songLoopedSectionLength); // a hack so progress bar does not jump? - } - } - if (totalLength<0.1) { - // DON'T - *progressLambda=0; - } else { - *progressLambda=(float)((*curPosInRowsLambda)+((*totalLoopsLambda)-(*loopsLeftLambda))*songLength+lengthOfOneFile*(*curFileLambda))/(float)totalLength; - } + *progressLambda=(double)e->getTotalSeconds()/(double)MAX(1,e->curSubSong->ts.totalSeconds); + // TODO: fix + *curPosInRowsLambda=0; } ); } - ImGui::Text(_("Row %d of %d"),curPosInRows+((totalLoops)-(loopsLeft))*songLength,lengthOfOneFile); + ImGui::Text(_("Row %d of %d"),songLength,lengthOfOneFile); if (audioExportOptions.mode==DIV_EXPORT_MODE_MANY_CHAN) ImGui::Text(_("Channel %d of %d"),curFile+1,totalFiles); ImGui::ProgressBar(curProgress,ImVec2(320.0f*dpiScale,0),fmt::sprintf("%.2f%%",curProgress*100.0f).c_str()); @@ -9274,8 +9247,6 @@ FurnaceGUI::FurnaceGUI(): memset(romExportAvail,0,sizeof(bool)*DIV_ROM_MAX); - songOrdersLengths.clear(); - strncpy(noteOffLabel,"OFF",32); strncpy(noteRelLabel,"===",32); strncpy(macroRelLabel,"REL",32); diff --git a/src/gui/gui.h b/src/gui/gui.h index 39bb08435..88232b8e2 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1821,7 +1821,6 @@ class FurnaceGUI { char emptyLabel[32]; char emptyLabel2[32]; - std::vector songOrdersLengths; // lengths of all orders (for drawing song export progress) int songLength; // length of all the song in rows int songLoopedSectionLength; // length of looped part of the song int songFadeoutSectionLength; // length of fading part of the song