some time refactors
no more weird totalTicks name code looks better
This commit is contained in:
parent
a2b56b5b64
commit
5ff81aef33
16 changed files with 256 additions and 211 deletions
|
|
@ -1511,8 +1511,7 @@ String DivEngine::getPlaybackDebugInfo() {
|
|||
"midiTimeDrift: %f\n"
|
||||
"changeOrd: %d\n"
|
||||
"changePos: %d\n"
|
||||
"totalSeconds: %d\n"
|
||||
"totalTicks: %d\n"
|
||||
"totalTime: %s\n"
|
||||
"totalTicksR: %d\n"
|
||||
"curMidiClock: %d\n"
|
||||
"curMidiTime: %d\n"
|
||||
|
|
@ -1524,7 +1523,7 @@ String DivEngine::getPlaybackDebugInfo() {
|
|||
"totalProcessed: %d\n"
|
||||
"bufferPos: %d\n",
|
||||
curOrder,prevOrder,curRow,prevRow,ticks,subticks,totalLoops,lastLoopPos,nextSpeed,divider,cycles,clockDrift,
|
||||
midiClockCycles,midiClockDrift,midiTimeCycles,midiTimeDrift,changeOrd,changePos,totalSeconds,totalTicks,
|
||||
midiClockCycles,midiClockDrift,midiTimeCycles,midiTimeDrift,changeOrd,changePos,totalTime.toString(),
|
||||
totalTicksR,curMidiClock,curMidiTime,totalCmds,lastCmds,cmdsPerSecond,
|
||||
(int)extValue,(int)tempoAccum,(int)totalProcessed,(int)bufferPos
|
||||
);
|
||||
|
|
@ -1662,27 +1661,17 @@ void DivEngine::setFilePlayerSync(bool doSync) {
|
|||
filePlayerSync=doSync;
|
||||
}
|
||||
|
||||
void DivEngine::getFilePlayerCue(int& seconds, int& micros) {
|
||||
seconds=filePlayerCueSeconds;
|
||||
micros=filePlayerCueMicros;
|
||||
TimeMicros DivEngine::getFilePlayerCue() {
|
||||
return filePlayerCue;
|
||||
}
|
||||
|
||||
void DivEngine::setFilePlayerCue(int seconds, int micros) {
|
||||
filePlayerCueSeconds=seconds;
|
||||
filePlayerCueMicros=micros;
|
||||
void DivEngine::setFilePlayerCue(TimeMicros cue) {
|
||||
filePlayerCue=cue;
|
||||
}
|
||||
|
||||
void DivEngine::syncFilePlayer() {
|
||||
if (curFilePlayer==NULL) return;
|
||||
int finalSeconds=totalSeconds+filePlayerCueSeconds;
|
||||
int finalMicros=totalTicks+filePlayerCueMicros;
|
||||
|
||||
while (finalMicros>=1000000) {
|
||||
finalMicros-=1000000;
|
||||
finalSeconds++;
|
||||
}
|
||||
|
||||
curFilePlayer->setPosSeconds(finalSeconds,finalMicros);
|
||||
curFilePlayer->setPosSeconds(totalTime+filePlayerCue);
|
||||
}
|
||||
|
||||
void DivEngine::playSub(bool preserveDrift, int goalRow) {
|
||||
|
|
@ -1717,9 +1706,8 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) {
|
|||
ticks=1;
|
||||
subticks=0;
|
||||
tempoAccum=0;
|
||||
totalTicks=0;
|
||||
totalTime=TimeMicros(0,0);
|
||||
totalTicksOff=0;
|
||||
totalSeconds=0;
|
||||
totalTicksR=0;
|
||||
curMidiClock=0;
|
||||
curMidiTime=0;
|
||||
|
|
@ -1809,7 +1797,7 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) {
|
|||
cmdStream.clear();
|
||||
std::chrono::high_resolution_clock::time_point timeEnd=std::chrono::high_resolution_clock::now();
|
||||
logV("playSub() took %dµs",std::chrono::duration_cast<std::chrono::microseconds>(timeEnd-timeStart).count());
|
||||
logV("and landed us at %d.%06d (%d ticks, %d:%d.%d)",totalSeconds,totalTicks,totalTicksR,curOrder,curRow,ticks);
|
||||
logV("and landed us at %s (%d ticks, %d:%d.%d)",totalTime.toString(),totalTicksR,curOrder,curRow,ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2569,12 +2557,8 @@ void DivEngine::virtualTempoChanged() {
|
|||
BUSY_END;
|
||||
}
|
||||
|
||||
int DivEngine::getTotalSeconds() {
|
||||
return totalSeconds;
|
||||
}
|
||||
|
||||
int DivEngine::getTotalTicks() {
|
||||
return totalTicks;
|
||||
TimeMicros DivEngine::getCurTime() {
|
||||
return totalTime;
|
||||
}
|
||||
|
||||
bool DivEngine::getRepeatPattern() {
|
||||
|
|
@ -3995,9 +3979,8 @@ void DivEngine::quitDispatch() {
|
|||
nextSpeed=3;
|
||||
changeOrd=-1;
|
||||
changePos=0;
|
||||
totalTicks=0;
|
||||
totalTime=TimeMicros(0,0);
|
||||
totalTicksOff=0;
|
||||
totalSeconds=0;
|
||||
totalTicksR=0;
|
||||
curMidiClock=0;
|
||||
curMidiTime=0;
|
||||
|
|
|
|||
|
|
@ -510,7 +510,8 @@ class DivEngine {
|
|||
int midiTimeCycles;
|
||||
double midiTimeDrift;
|
||||
int stepPlay;
|
||||
int changeOrd, changePos, totalSeconds, totalTicks, totalTicksR, curMidiClock, curMidiTime, totalCmds, lastCmds, cmdsPerSecond;
|
||||
int changeOrd, changePos, totalTicksR, curMidiClock, curMidiTime, totalCmds, lastCmds, cmdsPerSecond;
|
||||
TimeMicros totalTime;
|
||||
double totalTicksOff;
|
||||
int curMidiTimePiece, curMidiTimeCode;
|
||||
unsigned char extValue, pendingMetroTick;
|
||||
|
|
@ -602,8 +603,7 @@ class DivEngine {
|
|||
size_t filePlayerBufLen;
|
||||
DivFilePlayer* curFilePlayer;
|
||||
bool filePlayerSync;
|
||||
ssize_t filePlayerCueSeconds;
|
||||
unsigned int filePlayerCueMicros;
|
||||
TimeMicros filePlayerCue;
|
||||
int filePlayerLoopTrail;
|
||||
int curFilePlayerTrail;
|
||||
|
||||
|
|
@ -763,8 +763,8 @@ class DivEngine {
|
|||
bool getFilePlayerSync();
|
||||
void setFilePlayerSync(bool doSync);
|
||||
// get/set file player cue position.
|
||||
void getFilePlayerCue(int& seconds, int& micros);
|
||||
void setFilePlayerCue(int seconds, int micros);
|
||||
TimeMicros getFilePlayerCue();
|
||||
void setFilePlayerCue(TimeMicros cue);
|
||||
// UNSAFE - sync file player to current playback position.
|
||||
void syncFilePlayer();
|
||||
|
||||
|
|
@ -1049,8 +1049,7 @@ class DivEngine {
|
|||
void virtualTempoChanged();
|
||||
|
||||
// get time
|
||||
int getTotalTicks(); // 1/1000000th of a second
|
||||
int getTotalSeconds();
|
||||
TimeMicros getCurTime();
|
||||
|
||||
// get repeat pattern
|
||||
bool getRepeatPattern();
|
||||
|
|
@ -1525,8 +1524,6 @@ class DivEngine {
|
|||
stepPlay(0),
|
||||
changeOrd(-1),
|
||||
changePos(0),
|
||||
totalSeconds(0),
|
||||
totalTicks(0),
|
||||
totalTicksR(0),
|
||||
curMidiClock(0),
|
||||
curMidiTime(0),
|
||||
|
|
@ -1576,8 +1573,7 @@ class DivEngine {
|
|||
filePlayerBufLen(0),
|
||||
curFilePlayer(NULL),
|
||||
filePlayerSync(false),
|
||||
filePlayerCueSeconds(0),
|
||||
filePlayerCueMicros(0),
|
||||
filePlayerCue(0,0),
|
||||
filePlayerLoopTrail(0),
|
||||
curFilePlayerTrail(0),
|
||||
totalProcessed(0),
|
||||
|
|
|
|||
|
|
@ -298,15 +298,15 @@ ssize_t DivFilePlayer::getPos() {
|
|||
return playPos;
|
||||
}
|
||||
|
||||
void DivFilePlayer::getPosSeconds(ssize_t& seconds, unsigned int& micros) {
|
||||
TimeMicros DivFilePlayer::getPosSeconds() {
|
||||
if (sf==NULL) {
|
||||
seconds=0;
|
||||
micros=0;
|
||||
return;
|
||||
return TimeMicros(0,0);
|
||||
}
|
||||
double microsD=playPos%si.samplerate;
|
||||
seconds=playPos/si.samplerate;
|
||||
micros=(int)((1000000.0*microsD)/(double)si.samplerate);
|
||||
return TimeMicros(
|
||||
playPos/si.samplerate, // seconds
|
||||
(int)((1000000.0*microsD)/(double)si.samplerate) // microseconds
|
||||
);
|
||||
}
|
||||
|
||||
ssize_t DivFilePlayer::setPos(ssize_t newPos, unsigned int offset) {
|
||||
|
|
@ -325,20 +325,20 @@ ssize_t DivFilePlayer::setPos(ssize_t newPos, unsigned int offset) {
|
|||
}
|
||||
}
|
||||
|
||||
ssize_t DivFilePlayer::setPosSeconds(ssize_t seconds, unsigned int micros, unsigned int offset) {
|
||||
ssize_t DivFilePlayer::setPosSeconds(TimeMicros newTime, unsigned int offset) {
|
||||
if (sf==NULL) return 0;
|
||||
double microsD=(double)si.samplerate*((double)micros/1000000.0);
|
||||
double microsD=(double)si.samplerate*((double)newTime.micros/1000000.0);
|
||||
if (offset==UINT_MAX) {
|
||||
playPos=seconds*si.samplerate+(int)microsD;
|
||||
playPos=(ssize_t)newTime.seconds*(ssize_t)si.samplerate+(int)microsD;
|
||||
rateAccum=0;
|
||||
wantBlock=playPos;
|
||||
logD("DivFilePlayer: setPosSeconds(%" PRIi64 ".%06d)",seconds,micros);
|
||||
logD("DivFilePlayer: setPosSeconds(%s)",newTime.toString());
|
||||
return playPos;
|
||||
} else {
|
||||
pendingPosOffset=offset;
|
||||
pendingPos=seconds*si.samplerate+(int)microsD;
|
||||
pendingPos=(ssize_t)newTime.seconds*(ssize_t)si.samplerate+(int)microsD;
|
||||
wantBlock=pendingPos;
|
||||
logD("DivFilePlayer: offset %u setPosSeconds(%" PRIi64 ".%06d)",offset,seconds,micros);
|
||||
logD("DivFilePlayer: offset %u setPosSeconds(%s)",offset,newTime.toString());
|
||||
return pendingPos;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#define _FILEPLAYER_H
|
||||
|
||||
#include "../ta-utils.h"
|
||||
#include "../timeutils.h"
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
|
@ -78,9 +79,9 @@ class DivFilePlayer {
|
|||
|
||||
void mix(float** buf, int chans, unsigned int size);
|
||||
ssize_t getPos();
|
||||
void getPosSeconds(ssize_t& seconds, unsigned int& micros);
|
||||
TimeMicros getPosSeconds();
|
||||
ssize_t setPos(ssize_t newPos, unsigned int offset=UINT_MAX);
|
||||
ssize_t setPosSeconds(ssize_t seconds, unsigned int micros, unsigned int offset=UINT_MAX);
|
||||
ssize_t setPosSeconds(TimeMicros newTime, unsigned int offset=UINT_MAX);
|
||||
|
||||
bool isBlockPresent(ssize_t pos);
|
||||
bool setBlockPriority(ssize_t pos, bool priority);
|
||||
|
|
|
|||
|
|
@ -2172,8 +2172,9 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
|
||||
// also set the playback position and sync file player if necessary
|
||||
TimeMicros rowTS=curSubSong->ts.getTimes(curOrder,curRow);
|
||||
totalSeconds=rowTS.seconds;
|
||||
totalTicks=rowTS.micros;
|
||||
if (rowTS.seconds!=-1) {
|
||||
totalTime=rowTS;
|
||||
}
|
||||
if (curFilePlayer && filePlayerSync) {
|
||||
syncFilePlayer();
|
||||
}
|
||||
|
|
@ -2581,25 +2582,27 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
if (!noAccum) {
|
||||
double dt=divider*tickMult;
|
||||
totalTicksR++;
|
||||
// despite the name, totalTicks is in microseconds...
|
||||
totalTicks+=1000000/dt;
|
||||
totalTime.micros+=1000000/dt;
|
||||
totalTicksOff+=fmod(1000000.0,dt);
|
||||
while (totalTicksOff>=dt) {
|
||||
totalTicksOff-=dt;
|
||||
totalTicks++;
|
||||
totalTime.micros++;
|
||||
}
|
||||
}
|
||||
if (totalTicks>=1000000) {
|
||||
totalTicks-=1000000;
|
||||
if (totalTime.micros>=1000000) {
|
||||
totalTime.micros-=1000000;
|
||||
// who's gonna play a song for 68 years?
|
||||
if (totalSeconds<0x7fffffff) totalSeconds++;
|
||||
if (totalTime.seconds<0x7fffffff) totalTime.seconds++;
|
||||
cmdsPerSecond=totalCmds-lastCmds;
|
||||
lastCmds=totalCmds;
|
||||
}
|
||||
}
|
||||
|
||||
// print status in console mode
|
||||
if (consoleMode && !disableStatusOut && subticks<=1 && !skipping) fprintf(stderr,"\x1b[2K> %d:%.2d:%.2d.%.2d %.2x/%.2x:%.3d/%.3d %4dcmd/s\x1b[G",totalSeconds/3600,(totalSeconds/60)%60,totalSeconds%60,totalTicks/10000,curOrder,curSubSong->ordersLen,curRow,curSubSong->patLen,cmdsPerSecond);
|
||||
if (consoleMode && !disableStatusOut && subticks<=1 && !skipping) {
|
||||
String timeFormatted=totalTime.toString(2,TA_TIME_FORMAT_HMS);
|
||||
fprintf(stderr,"\x1b[2K> %s %.2x/%.2x:%.3d/%.3d %4dcmd/s\x1b[G",timeFormatted.c_str(),curOrder,curSubSong->ordersLen,curRow,curSubSong->patLen,cmdsPerSecond);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -3110,15 +3113,12 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
if (curFilePlayer && filePlayerSync) {
|
||||
if (curFilePlayer->isPlaying()) {
|
||||
TimeMicros rowTS=curSubSong->ts.loopStartTime;
|
||||
int finalSeconds=rowTS.seconds+filePlayerCueSeconds;
|
||||
int finalMicros=rowTS.micros+filePlayerCueMicros;
|
||||
|
||||
while (finalMicros>=1000000) {
|
||||
finalMicros-=1000000;
|
||||
finalSeconds++;
|
||||
if (rowTS.seconds==-1) {
|
||||
logW("that row isn't supposed to play. report this now!");
|
||||
}
|
||||
|
||||
curFilePlayer->setPosSeconds(finalSeconds,finalMicros,lastLoopPos);
|
||||
curFilePlayer->setPosSeconds(rowTS+filePlayerCue,lastLoopPos);
|
||||
}
|
||||
}
|
||||
// increase total loop count
|
||||
|
|
@ -3232,7 +3232,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
// complain and stop playback if we believe the engine has stalled
|
||||
//logD("attempts: %d",attempts);
|
||||
if (attempts>=(int)(size+10)) {
|
||||
logE("hang detected! stopping! at %d seconds %d micro (%d>=%d)",totalSeconds,totalTicks,attempts,(int)size);
|
||||
logE("hang detected! stopping! at %s (%d>=%d)",totalTime.toString(),attempts,(int)size);
|
||||
freelance=false;
|
||||
playing=false;
|
||||
extValuePresent=false;
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@ TimeMicros DivSongTimestamps::getTimes(int order, int row) {
|
|||
}
|
||||
|
||||
DivSongTimestamps::DivSongTimestamps():
|
||||
totalSeconds(0),
|
||||
totalMicros(0),
|
||||
totalTime(0,0),
|
||||
totalTicks(0),
|
||||
totalRows(0),
|
||||
isLoopDefined(false),
|
||||
|
|
@ -54,8 +53,7 @@ void DivSubSong::calcTimestamps(int chans, std::vector<DivGroovePattern>& groove
|
|||
std::chrono::high_resolution_clock::time_point timeStart=std::chrono::high_resolution_clock::now();
|
||||
|
||||
// reset state
|
||||
ts.totalSeconds=0;
|
||||
ts.totalMicros=0;
|
||||
ts.totalTime=TimeMicros(0,0);
|
||||
ts.totalTicks=0;
|
||||
ts.totalRows=0;
|
||||
ts.isLoopDefined=true;
|
||||
|
|
@ -396,7 +394,7 @@ void DivSubSong::calcTimestamps(int chans, std::vector<DivGroovePattern>& groove
|
|||
ts.orders[prevOrder][i].seconds=-1;
|
||||
}
|
||||
}
|
||||
ts.orders[prevOrder][prevRow]=TimeMicros(ts.totalSeconds,ts.totalMicros);
|
||||
ts.orders[prevOrder][prevRow]=ts.totalTime;
|
||||
rowChanged=false;
|
||||
}
|
||||
|
||||
|
|
@ -405,16 +403,16 @@ void DivSubSong::calcTimestamps(int chans, std::vector<DivGroovePattern>& groove
|
|||
double dt=divider;//*((double)virtualTempoN/(double)MAX(1,virtualTempoD));
|
||||
ts.totalTicks++;
|
||||
|
||||
ts.totalMicros+=1000000/dt;
|
||||
ts.totalTime.micros+=1000000/dt;
|
||||
totalMicrosOff+=fmod(1000000.0,dt);
|
||||
while (totalMicrosOff>=dt) {
|
||||
totalMicrosOff-=dt;
|
||||
ts.totalMicros++;
|
||||
ts.totalTime.micros++;
|
||||
}
|
||||
if (ts.totalMicros>=1000000) {
|
||||
ts.totalMicros-=1000000;
|
||||
if (ts.totalTime.micros>=1000000) {
|
||||
ts.totalTime.micros-=1000000;
|
||||
// who's gonna play a song for 68 years?
|
||||
if (ts.totalSeconds<0x7fffffff) ts.totalSeconds++;
|
||||
if (ts.totalTime.seconds<0x7fffffff) ts.totalTime.seconds++;
|
||||
}
|
||||
}
|
||||
if (ts.maxRow[curOrder]<curRow) ts.maxRow[curOrder]=curRow;
|
||||
|
|
|
|||
|
|
@ -170,8 +170,7 @@ struct DivGroovePattern {
|
|||
|
||||
struct DivSongTimestamps {
|
||||
// song duration (in seconds and microseconds)
|
||||
int totalSeconds;
|
||||
int totalMicros;
|
||||
TimeMicros totalTime;
|
||||
int totalTicks;
|
||||
int totalRows;
|
||||
|
||||
|
|
|
|||
|
|
@ -104,10 +104,9 @@ void FurnaceGUI::drawClock() {
|
|||
}
|
||||
}
|
||||
if (clockShowTime) {
|
||||
int totalTicks=e->getTotalTicks();
|
||||
int totalSeconds=e->getTotalSeconds();
|
||||
String timeFormatted=e->getCurTime().toString(2,TA_TIME_FORMAT_MS_ZERO);
|
||||
ImGui::PushFont(bigFont);
|
||||
ImGui::Text("%.2d:%.2d.%.2d",(totalSeconds/60),totalSeconds%60,totalTicks/10000);
|
||||
ImGui::TextUnformatted(timeFormatted.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,7 +206,8 @@ void FurnaceGUI::drawDebug() {
|
|||
|
||||
DivSongTimestamps& ts=e->curSubSong->ts;
|
||||
|
||||
ImGui::Text("song duration: %d.%06d (%d ticks; %d rows)",ts.totalSeconds,ts.totalMicros,ts.totalTicks,ts.totalRows);
|
||||
String timeFormatted=ts.totalTime.toString(-1,TA_TIME_FORMAT_AUTO);
|
||||
ImGui::Text("song duration: %s (%d ticks; %d rows)",timeFormatted.c_str(),ts.totalTicks,ts.totalRows);
|
||||
if (ts.isLoopDefined) {
|
||||
ImGui::Text("loop region is defined");
|
||||
} else {
|
||||
|
|
@ -219,7 +220,8 @@ void FurnaceGUI::drawDebug() {
|
|||
}
|
||||
|
||||
ImGui::Text("loop region: %d:%d - %d:%d",ts.loopStart.order,ts.loopStart.row,ts.loopEnd.order,ts.loopEnd.row);
|
||||
ImGui::Text("loop start time: %d.%06d",ts.loopStartTime.seconds,ts.loopStartTime.micros);
|
||||
timeFormatted=ts.loopStartTime.toString(-1,TA_TIME_FORMAT_AUTO);
|
||||
ImGui::Text("loop start time: %s",timeFormatted.c_str());
|
||||
|
||||
if (ImGui::TreeNode("Maximum rows")) {
|
||||
for (int i=0; i<e->curSubSong->ordersLen; i++) {
|
||||
|
|
|
|||
|
|
@ -2719,7 +2719,7 @@ void FurnaceGUI::exportAudio(String path, DivAudioExportModes mode) {
|
|||
e->calcSongTimestamps();
|
||||
DivSongTimestamps& ts=e->curSubSong->ts;
|
||||
|
||||
songLength=ts.totalSeconds+(double)ts.totalMicros/1000000.0;
|
||||
songLength=ts.totalTime.toDouble();
|
||||
double loopLength=songLength-(ts.loopStartTime.seconds+(double)ts.loopStartTime.micros/1000000.0);
|
||||
|
||||
e->saveAudio(path.c_str(),audioExportOptions);
|
||||
|
|
@ -4843,8 +4843,7 @@ bool FurnaceGUI::loop() {
|
|||
}
|
||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PLAYBACK_STAT]);
|
||||
if (e->isPlaying() && settings.playbackTime) {
|
||||
int totalTicks=e->getTotalTicks();
|
||||
int totalSeconds=e->getTotalSeconds();
|
||||
TimeMicros totalTime=e->getCurTime();
|
||||
|
||||
String info;
|
||||
|
||||
|
|
@ -4873,32 +4872,10 @@ bool FurnaceGUI::loop() {
|
|||
|
||||
info+=_("| ");
|
||||
|
||||
if (totalSeconds==0x7fffffff) {
|
||||
if (totalTime.seconds==0x7fffffff) {
|
||||
info+=_("Don't you have anything better to do?");
|
||||
} else {
|
||||
if (totalSeconds>=86400) {
|
||||
int totalDays=totalSeconds/86400;
|
||||
int totalYears=totalDays/365;
|
||||
totalDays%=365;
|
||||
int totalMonths=totalDays/30;
|
||||
totalDays%=30;
|
||||
|
||||
#ifdef HAVE_LOCALE
|
||||
info+=fmt::sprintf(ngettext("%d year ","%d years ",totalYears),totalYears);
|
||||
info+=fmt::sprintf(ngettext("%d month ","%d months ",totalMonths),totalMonths);
|
||||
info+=fmt::sprintf(ngettext("%d day ","%d days ",totalDays),totalDays);
|
||||
#else
|
||||
info+=fmt::sprintf(_GN("%d year ","%d years ",totalYears),totalYears);
|
||||
info+=fmt::sprintf(_GN("%d month ","%d months ",totalMonths),totalMonths);
|
||||
info+=fmt::sprintf(_GN("%d day ","%d days ",totalDays),totalDays);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (totalSeconds>=3600) {
|
||||
info+=fmt::sprintf("%.2d:",(totalSeconds/3600)%24);
|
||||
}
|
||||
|
||||
info+=fmt::sprintf("%.2d:%.2d.%.2d",(totalSeconds/60)%60,totalSeconds%60,totalTicks/10000);
|
||||
info+=totalTime.toString(2,TA_TIME_FORMAT_AUTO_MS_ZERO);
|
||||
}
|
||||
|
||||
ImGui::TextUnformatted(info.c_str());
|
||||
|
|
@ -6039,7 +6016,7 @@ bool FurnaceGUI::loop() {
|
|||
[this, curFileLambda] () {
|
||||
*curFileLambda=0;
|
||||
e->getCurFileIndex(*curFileLambda);
|
||||
curProgress=(((double)e->getTotalSeconds()+(double)e->getTotalTicks()/1000000.0)+(songLength*(*curFileLambda)))/totalLength;
|
||||
curProgress=(e->getCurTime().toDouble()+(songLength*(*curFileLambda)))/totalLength;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -7390,17 +7367,8 @@ bool FurnaceGUI::loop() {
|
|||
if (!fp->isPlaying()) {
|
||||
TimeMicros rowTS=e->curSubSong->ts.getTimes(cursor.order,cursor.y);
|
||||
if (rowTS.seconds!=-1) {
|
||||
int cueSeconds=0;
|
||||
int cueMicros=0;
|
||||
e->getFilePlayerCue(cueSeconds,cueMicros);
|
||||
rowTS.seconds+=cueSeconds;
|
||||
rowTS.micros+=cueMicros;
|
||||
while (rowTS.micros>=1000000) {
|
||||
rowTS.micros-=1000000;
|
||||
rowTS.seconds++;
|
||||
}
|
||||
|
||||
fp->setPosSeconds(rowTS.seconds,rowTS.micros);
|
||||
TimeMicros cueTime=e->getFilePlayerCue();
|
||||
fp->setPosSeconds(cueTime+rowTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,30 +90,11 @@ void FurnaceGUI::drawMobileOrderSel() {
|
|||
|
||||
// time
|
||||
if (e->isPlaying() && settings.playbackTime) {
|
||||
int totalTicks=e->getTotalTicks();
|
||||
int totalSeconds=e->getTotalSeconds();
|
||||
String info="";
|
||||
TimeMicros totalTime=e->getCurTime();
|
||||
String info=totalTime.toString(2,TA_TIME_FORMAT_AUTO_MS_ZERO);
|
||||
|
||||
if (totalSeconds==0x7fffffff) {
|
||||
if (totalTime.seconds==0x7fffffff) {
|
||||
info="∞";
|
||||
} else {
|
||||
if (totalSeconds>=86400) {
|
||||
int totalDays=totalSeconds/86400;
|
||||
int totalYears=totalDays/365;
|
||||
totalDays%=365;
|
||||
int totalMonths=totalDays/30;
|
||||
totalDays%=30;
|
||||
|
||||
info+=fmt::sprintf("%dy",totalYears);
|
||||
info+=fmt::sprintf("%dm",totalMonths);
|
||||
info+=fmt::sprintf("%dd",totalDays);
|
||||
}
|
||||
|
||||
if (totalSeconds>=3600) {
|
||||
info+=fmt::sprintf("%.2d:",(totalSeconds/3600)%24);
|
||||
}
|
||||
|
||||
info+=fmt::sprintf("%.2d:%.2d.%.2d",(totalSeconds/60)%60,totalSeconds%60,totalTicks/10000);
|
||||
}
|
||||
|
||||
ImVec2 textSize=ImGui::CalcTextSize(info.c_str());
|
||||
|
|
|
|||
|
|
@ -412,7 +412,8 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
|
|||
if (rowTS.seconds==-1) {
|
||||
ImGui::Text("---");
|
||||
} else {
|
||||
ImGui::Text("%d.%06d",rowTS.seconds,rowTS.micros);
|
||||
String timeFormatted=rowTS.toString(2,TA_TIME_FORMAT_AUTO_MS_ZERO);
|
||||
ImGui::TextUnformatted(timeFormatted.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,21 +79,15 @@ void FurnaceGUI::drawRefPlayer() {
|
|||
}
|
||||
if (fp->isPlaying()) {
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
|
||||
int cueSeconds=0;
|
||||
int cueMicros=0;
|
||||
fp->stop();
|
||||
e->getFilePlayerCue(cueSeconds,cueMicros);
|
||||
fp->setPosSeconds(cueSeconds,cueMicros);
|
||||
fp->setPosSeconds(e->getFilePlayerCue());
|
||||
}
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Middle)) {
|
||||
fp->stop();
|
||||
fp->setPos(0);
|
||||
}
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
|
||||
int cueSeconds=0;
|
||||
int cueMicros=0;
|
||||
e->getFilePlayerCue(cueSeconds,cueMicros);
|
||||
fp->setPosSeconds(cueSeconds,cueMicros);
|
||||
fp->setPosSeconds(e->getFilePlayerCue());
|
||||
}
|
||||
ImGui::SetItemTooltip(
|
||||
_("left click: go to cue position\n"
|
||||
|
|
@ -103,21 +97,12 @@ void FurnaceGUI::drawRefPlayer() {
|
|||
} else {
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
|
||||
// try setting cue pos
|
||||
ssize_t curSeconds=0;
|
||||
unsigned int curMicros=0;
|
||||
fp->getPosSeconds(curSeconds,curMicros);
|
||||
TimeMicros curPos=fp->getPosSeconds();
|
||||
TimeMicros rowTS=e->curSubSong->ts.getTimes(curOrder,0);
|
||||
if (rowTS.seconds==-1) {
|
||||
showError(_("the first row of this order isn't going to play."));
|
||||
} else {
|
||||
// calculate difference and set cue pos
|
||||
curSeconds-=rowTS.seconds;
|
||||
int curMicrosI=curMicros-rowTS.micros;
|
||||
while (curMicrosI<0) {
|
||||
curMicrosI+=1000000;
|
||||
curSeconds--;
|
||||
}
|
||||
e->setFilePlayerCue(curSeconds,curMicrosI);
|
||||
e->setFilePlayerCue(curPos-rowTS);
|
||||
}
|
||||
}
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Middle)) {
|
||||
|
|
@ -125,25 +110,23 @@ void FurnaceGUI::drawRefPlayer() {
|
|||
}
|
||||
if (ImGui::BeginPopupContextItem("Edit Cue Position",ImGuiPopupFlags_MouseButtonRight)) {
|
||||
ImGui::TextUnformatted(_("Set cue position at first order:"));
|
||||
int cueSeconds=0;
|
||||
int cueMicros=0;
|
||||
TimeMicros cueTime=e->getFilePlayerCue();
|
||||
bool altered=false;
|
||||
e->getFilePlayerCue(cueSeconds,cueMicros);
|
||||
// TODO: improve this...
|
||||
ImGui::SetNextItemWidth(240.0f*dpiScale);
|
||||
if (ImGui::InputInt(_("Seconds##CuePosS"),&cueSeconds)) {
|
||||
if (cueSeconds<-3600) cueSeconds=-3600;
|
||||
if (cueSeconds>3600) cueSeconds=3600;
|
||||
if (ImGui::InputInt(_("Seconds##CuePosS"),&cueTime.seconds)) {
|
||||
if (cueTime.seconds<-3600) cueTime.seconds=-3600;
|
||||
if (cueTime.seconds>3600) cueTime.seconds=3600;
|
||||
altered=true;
|
||||
}
|
||||
ImGui::SetNextItemWidth(240.0f*dpiScale);
|
||||
if (ImGui::InputInt(_("Microseconds##CuePosM"),&cueMicros,1000,10000)) {
|
||||
if (cueMicros<0) cueMicros=0;
|
||||
if (cueMicros>999999) cueMicros=999999;
|
||||
if (ImGui::InputInt(_("Microseconds##CuePosM"),&cueTime.micros,1000,10000)) {
|
||||
if (cueTime.micros<0) cueTime.micros=0;
|
||||
if (cueTime.micros>999999) cueTime.micros=999999;
|
||||
altered=true;
|
||||
}
|
||||
if (altered) {
|
||||
e->setFilePlayerCue(cueSeconds,cueMicros);
|
||||
e->setFilePlayerCue(cueTime);
|
||||
}
|
||||
if (ImGui::Button(_("OK"))) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
|
@ -165,21 +148,12 @@ void FurnaceGUI::drawRefPlayer() {
|
|||
}
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
|
||||
// try setting cue pos
|
||||
ssize_t curSeconds=0;
|
||||
unsigned int curMicros=0;
|
||||
fp->getPosSeconds(curSeconds,curMicros);
|
||||
TimeMicros curPos=fp->getPosSeconds();
|
||||
TimeMicros rowTS=e->curSubSong->ts.getTimes(curOrder,0);
|
||||
if (rowTS.seconds==-1) {
|
||||
showError(_("the first row of this order isn't going to play."));
|
||||
} else {
|
||||
// calculate difference and set cue pos
|
||||
curSeconds-=rowTS.seconds;
|
||||
int curMicrosI=curMicros-rowTS.micros;
|
||||
while (curMicrosI<0) {
|
||||
curMicrosI+=1000000;
|
||||
curSeconds--;
|
||||
}
|
||||
e->setFilePlayerCue(curSeconds,curMicrosI);
|
||||
e->setFilePlayerCue(curPos-rowTS);
|
||||
fp->stop();
|
||||
}
|
||||
}
|
||||
|
|
@ -203,9 +177,7 @@ void FurnaceGUI::drawRefPlayer() {
|
|||
} else {
|
||||
rowTS=e->curSubSong->ts.getTimes(curOrder,0);
|
||||
}
|
||||
int cueSeconds=0;
|
||||
int cueMicros=0;
|
||||
e->getFilePlayerCue(cueSeconds,cueMicros);
|
||||
TimeMicros cueTime=e->getFilePlayerCue();
|
||||
if (rowTS.seconds==-1) {
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
|
||||
showError(_("the row that the pattern cursor is at isn't going to play. try moving the cursor."));
|
||||
|
|
@ -213,15 +185,7 @@ void FurnaceGUI::drawRefPlayer() {
|
|||
showError(_("the first row of this order isn't going to play. try another order."));
|
||||
}
|
||||
} else {
|
||||
int finalSeconds=rowTS.seconds+cueSeconds;
|
||||
int finalMicros=rowTS.micros+cueMicros;
|
||||
|
||||
while (finalMicros>=1000000) {
|
||||
finalMicros-=1000000;
|
||||
finalSeconds++;
|
||||
}
|
||||
|
||||
fp->setPosSeconds(finalSeconds,finalMicros);
|
||||
fp->setPosSeconds(rowTS+cueTime);
|
||||
fp->play();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1082,7 +1082,7 @@ void FurnaceGUI::drawTutorial() {
|
|||
oneQuarter=(oneQuarter*e->curSubSong->virtualTempoN)/e->curSubSong->virtualTempoD;
|
||||
oneQuarter/=e->curSubSong->hz;
|
||||
oneQuarter/=4;
|
||||
if (cv->playSongs && e->getTotalSeconds()>=oneQuarter) {
|
||||
if (cv->playSongs && e->getCurTime().seconds>=oneQuarter) {
|
||||
if (loadRandomDemoSong()) {
|
||||
cv->loadInstruments();
|
||||
e->changeSongP(0);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include "timeutils.h"
|
||||
#include <fmt/printf.h>
|
||||
|
||||
String TimeMicros::toString(signed char prec, unsigned char hms) {
|
||||
String TimeMicros::toString(signed char prec, TATimeFormats hms) {
|
||||
String ret;
|
||||
int actualSeconds=seconds;
|
||||
int actualMicros=micros;
|
||||
|
|
@ -31,8 +31,55 @@ String TimeMicros::toString(signed char prec, unsigned char hms) {
|
|||
}
|
||||
if (negative) actualSeconds=-actualSeconds;
|
||||
|
||||
// handle auto formats
|
||||
switch (hms) {
|
||||
case 2: { // h:mm:ss
|
||||
case TA_TIME_FORMAT_AUTO:
|
||||
hms=TA_TIME_FORMAT_SECONDS;
|
||||
if (actualSeconds>60) hms=TA_TIME_FORMAT_MS;
|
||||
if (actualSeconds>3600) hms=TA_TIME_FORMAT_HMS;
|
||||
if (actualSeconds>86400) hms=TA_TIME_FORMAT_DAYS_HMS;
|
||||
break;
|
||||
case TA_TIME_FORMAT_AUTO_ZERO:
|
||||
hms=TA_TIME_FORMAT_SECONDS;
|
||||
if (actualSeconds>60) hms=TA_TIME_FORMAT_MS_ZERO;
|
||||
if (actualSeconds>3600) hms=TA_TIME_FORMAT_HMS_ZERO;
|
||||
if (actualSeconds>86400) hms=TA_TIME_FORMAT_DAYS_HMS_ZERO;
|
||||
break;
|
||||
case TA_TIME_FORMAT_AUTO_MS:
|
||||
hms=TA_TIME_FORMAT_MS;
|
||||
if (actualSeconds>3600) hms=TA_TIME_FORMAT_HMS;
|
||||
if (actualSeconds>86400) hms=TA_TIME_FORMAT_DAYS_HMS;
|
||||
break;
|
||||
case TA_TIME_FORMAT_AUTO_MS_ZERO:
|
||||
hms=TA_TIME_FORMAT_MS_ZERO;
|
||||
if (actualSeconds>3600) hms=TA_TIME_FORMAT_HMS_ZERO;
|
||||
if (actualSeconds>86400) hms=TA_TIME_FORMAT_DAYS_HMS_ZERO;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (hms) {
|
||||
case TA_TIME_FORMAT_SECONDS: { // seconds
|
||||
if (negative) {
|
||||
ret=fmt::sprintf("-%d",actualSeconds);
|
||||
} else {
|
||||
ret=fmt::sprintf("%d",actualSeconds);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TA_TIME_FORMAT_MS: { // m:ss
|
||||
int m=actualSeconds/60;
|
||||
int s=actualSeconds%60;
|
||||
|
||||
if (negative) {
|
||||
ret=fmt::sprintf("-%d:%02d",m,s);
|
||||
} else {
|
||||
ret=fmt::sprintf("%d:%02d",m,s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TA_TIME_FORMAT_HMS: { // h:mm:ss
|
||||
int h=actualSeconds/3600;
|
||||
int m=(actualSeconds/60)%60;
|
||||
int s=actualSeconds%60;
|
||||
|
|
@ -44,25 +91,65 @@ String TimeMicros::toString(signed char prec, unsigned char hms) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 1: { // m:ss
|
||||
case TA_TIME_FORMAT_MS_ZERO: { // mm:ss
|
||||
int m=actualSeconds/60;
|
||||
int s=actualSeconds%60;
|
||||
|
||||
if (negative) {
|
||||
ret=fmt::sprintf("-%d:%02d",m,s);
|
||||
ret=fmt::sprintf("-%02d:%02d",m,s);
|
||||
} else {
|
||||
ret=fmt::sprintf("%d:%02d",m,s);
|
||||
ret=fmt::sprintf("%02d:%02d",m,s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: { // seconds
|
||||
case TA_TIME_FORMAT_HMS_ZERO: { // hh:mm:ss
|
||||
int h=actualSeconds/3600;
|
||||
int m=(actualSeconds/60)%60;
|
||||
int s=actualSeconds%60;
|
||||
|
||||
if (negative) {
|
||||
ret=fmt::sprintf("-%d",actualSeconds);
|
||||
ret=fmt::sprintf("-%02d:%02d:%02d",h,m,s);
|
||||
} else {
|
||||
ret=fmt::sprintf("%d",actualSeconds);
|
||||
ret=fmt::sprintf("%02d:%02d:%02d",h,m,s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TA_TIME_FORMAT_DAYS_HMS: { // ?y?m?d h:mm:ss
|
||||
int days=actualSeconds/86400;
|
||||
int years=days/365;
|
||||
days%=365;
|
||||
int months=days/30;
|
||||
days%=30;
|
||||
int h=(actualSeconds/3600)%24;
|
||||
int m=(actualSeconds/60)%60;
|
||||
int s=actualSeconds%60;
|
||||
|
||||
if (negative) {
|
||||
ret=fmt::sprintf("-%dy%dm%dd %d:%02d:%02d",years,months,days,h,m,s);
|
||||
} else {
|
||||
ret=fmt::sprintf("%dy%dm%dd %d:%02d:%02d",years,months,days,h,m,s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TA_TIME_FORMAT_DAYS_HMS_ZERO: { // ?y?m?d hh:mm:ss
|
||||
int days=actualSeconds/86400;
|
||||
int years=days/365;
|
||||
days%=365;
|
||||
int months=days/30;
|
||||
days%=30;
|
||||
int h=(actualSeconds/3600)%24;
|
||||
int m=(actualSeconds/60)%60;
|
||||
int s=actualSeconds%60;
|
||||
|
||||
if (negative) {
|
||||
ret=fmt::sprintf("-%dy%dm%dd %02d:%02d:%02d",years,months,days,h,m,s);
|
||||
} else {
|
||||
ret=fmt::sprintf("%dy%dm%dd %02d:%02d:%02d",years,months,days,h,m,s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return "ERROR!";
|
||||
}
|
||||
|
||||
if (prec<0) {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,23 @@
|
|||
|
||||
#include "ta-utils.h"
|
||||
|
||||
enum TATimeFormats: unsigned char {
|
||||
TA_TIME_FORMAT_SECONDS=0, // seconds only
|
||||
TA_TIME_FORMAT_MS, // m:ss
|
||||
TA_TIME_FORMAT_HMS, // h:mm:ss
|
||||
|
||||
TA_TIME_FORMAT_MS_ZERO, // mm:ss
|
||||
TA_TIME_FORMAT_HMS_ZERO, // hh:mm:ss
|
||||
|
||||
TA_TIME_FORMAT_DAYS_HMS, // years, months, days, h:mm:ss
|
||||
TA_TIME_FORMAT_DAYS_HMS_ZERO, // years, months, days, hh:mm:ss
|
||||
|
||||
TA_TIME_FORMAT_AUTO, // automatic
|
||||
TA_TIME_FORMAT_AUTO_ZERO, // automatic (zero)
|
||||
TA_TIME_FORMAT_AUTO_MS, // automatic (from minutes)
|
||||
TA_TIME_FORMAT_AUTO_MS_ZERO, // automatic (from minutes; zero)
|
||||
};
|
||||
|
||||
struct TimeMicros {
|
||||
int seconds, micros;
|
||||
|
||||
|
|
@ -37,13 +54,62 @@ struct TimeMicros {
|
|||
return seconds+(double)micros/1000000.0;
|
||||
}
|
||||
|
||||
// operators
|
||||
inline TimeMicros& operator+(TimeMicros& other) {
|
||||
seconds+=other.seconds;
|
||||
micros+=other.micros;
|
||||
while (micros>=1000000) {
|
||||
micros-=1000000;
|
||||
seconds++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline TimeMicros& operator+(int other) {
|
||||
seconds+=other;
|
||||
return *this;
|
||||
}
|
||||
inline TimeMicros& operator-(TimeMicros& other) {
|
||||
seconds-=other.seconds;
|
||||
micros-=other.micros;
|
||||
while (micros<0) {
|
||||
micros+=1000000;
|
||||
seconds--;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline TimeMicros& operator-(int other) {
|
||||
seconds-=other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// comparison operators
|
||||
inline bool operator==(TimeMicros& other) {
|
||||
return (seconds==other.seconds && micros==other.micros);
|
||||
}
|
||||
inline bool operator>(TimeMicros& other) {
|
||||
return (seconds>other.seconds || (seconds==other.seconds && micros>other.micros));
|
||||
}
|
||||
inline bool operator>=(TimeMicros& other) {
|
||||
return (seconds>other.seconds || (seconds==other.seconds && micros>=other.micros));
|
||||
}
|
||||
|
||||
inline bool operator!=(TimeMicros& other) {
|
||||
return !(*this==other);
|
||||
}
|
||||
inline bool operator<(TimeMicros& other) {
|
||||
return !(*this>=other);
|
||||
}
|
||||
inline bool operator<=(TimeMicros& other) {
|
||||
return !(*this>other);
|
||||
}
|
||||
|
||||
/**
|
||||
* convert this TimeMicros to a String.
|
||||
* @param prec maximum digit precision (0-6). use -1 for automatic precision.
|
||||
* @param hms how many denominations to include (0: seconds, 1: minutes, 2: hours).
|
||||
* @return formatted TimeMicros.
|
||||
*/
|
||||
String toString(signed char prec=-1, unsigned char hms=0);
|
||||
String toString(signed char prec=6, TATimeFormats hms=TA_TIME_FORMAT_SECONDS);
|
||||
static TimeMicros fromString(String s);
|
||||
|
||||
TimeMicros(int s, int u):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue