heuristic for song length determination
song length calculation of lorge.fur now takes 18ms (from ~1 hour)
This commit is contained in:
parent
61ac87d505
commit
9e8c97cc6f
6 changed files with 53 additions and 14 deletions
|
|
@ -264,6 +264,19 @@ double DivEngine::benchmarkSeek() {
|
|||
return tAvg;
|
||||
}
|
||||
|
||||
double DivEngine::benchmarkWalk() {
|
||||
std::chrono::high_resolution_clock::time_point timeStart=std::chrono::high_resolution_clock::now();
|
||||
|
||||
// benchmark
|
||||
calcSongTimestamps();
|
||||
|
||||
std::chrono::high_resolution_clock::time_point timeEnd=std::chrono::high_resolution_clock::now();
|
||||
|
||||
double t=(double)(std::chrono::duration_cast<std::chrono::microseconds>(timeEnd-timeStart).count())/1000000.0;
|
||||
printf("[RESULT] %fs\n",t);
|
||||
return t;
|
||||
}
|
||||
|
||||
void DivEngine::notifyInsChange(int ins) {
|
||||
BUSY_BEGIN;
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
|
|
|
|||
|
|
@ -821,6 +821,7 @@ class DivEngine {
|
|||
// benchmark (returns time in seconds)
|
||||
double benchmarkPlayback();
|
||||
double benchmarkSeek();
|
||||
double benchmarkWalk();
|
||||
|
||||
// returns the minimum VGM version which may carry the specified system, or 0 if none.
|
||||
int minVGMVersion(DivSystem which);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "song.h"
|
||||
#include "../ta-log.h"
|
||||
#include <inttypes.h>
|
||||
#include <chrono>
|
||||
|
||||
TimeMicros DivSongTimestamps::getTimes(int order, int row) {
|
||||
|
|
@ -347,22 +348,40 @@ void DivSubSong::calcTimestamps(int chans, std::vector<DivGroovePattern>& groove
|
|||
|
||||
// MAKE IT WORK
|
||||
while (!endOfSong) {
|
||||
// heuristic
|
||||
int advance=(curVirtualTempoD*ticks)/curVirtualTempoN;
|
||||
for (int i=0; i<chans; i++) {
|
||||
if (rowDelay[i]>0) {
|
||||
if (rowDelay[i]<advance) advance=rowDelay[i];
|
||||
}
|
||||
}
|
||||
if (advance<1) advance=1;
|
||||
|
||||
//logV("tick %" PRIu64 " advance: %d",ts.totalTicks,advance);
|
||||
|
||||
// cycle channels to find a tick rate/tempo change effect after delay
|
||||
// (unfortunately Cxxx and F0xx are not pre-effects and obey EDxx)
|
||||
for (int i=0; i<chans; i++) {
|
||||
if (rowDelay[i]>0) {
|
||||
if (--rowDelay[i]==0) {
|
||||
rowDelay[i]-=advance;
|
||||
if (rowDelay[i]==0) {
|
||||
tinyProcessRow(i,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// run virtual tempo
|
||||
tempoAccum+=curVirtualTempoN;
|
||||
tempoAccum+=curVirtualTempoN*advance;
|
||||
while (tempoAccum>=curVirtualTempoD) {
|
||||
tempoAccum-=curVirtualTempoD;
|
||||
int ticksToRun=tempoAccum/curVirtualTempoD;
|
||||
tempoAccum%=curVirtualTempoD;
|
||||
// tick counter
|
||||
if (--ticks<=0) {
|
||||
ticks-=ticksToRun;
|
||||
if (ticks<0) {
|
||||
// if ticks is negative, we must call ticks back
|
||||
tempoAccum+=-ticks*curVirtualTempoD;
|
||||
}
|
||||
if (ticks<=0) {
|
||||
if (shallStopSched) {
|
||||
shallStop=true;
|
||||
break;
|
||||
|
|
@ -400,8 +419,8 @@ void DivSubSong::calcTimestamps(int chans, std::vector<DivGroovePattern>& groove
|
|||
|
||||
if (!endOfSong) {
|
||||
// update playback time
|
||||
double dt=divider;//*((double)virtualTempoN/(double)MAX(1,virtualTempoD));
|
||||
ts.totalTicks++;
|
||||
double dt=divider/(double)advance;//*((double)virtualTempoN/(double)MAX(1,virtualTempoD));
|
||||
ts.totalTicks+=advance;
|
||||
|
||||
ts.totalTime.micros+=1000000/dt;
|
||||
totalMicrosOff+=fmod(1000000.0,dt);
|
||||
|
|
@ -410,9 +429,10 @@ void DivSubSong::calcTimestamps(int chans, std::vector<DivGroovePattern>& groove
|
|||
ts.totalTime.micros++;
|
||||
}
|
||||
if (ts.totalTime.micros>=1000000) {
|
||||
ts.totalTime.micros-=1000000;
|
||||
// who's gonna play a song for 68 years?
|
||||
if (ts.totalTime.seconds<0x7fffffff) ts.totalTime.seconds++;
|
||||
ts.totalTime.seconds+=ts.totalTime.micros/1000000;
|
||||
if (ts.totalTime.seconds<0) ts.totalTime.seconds=INT_MAX;
|
||||
ts.totalTime.micros%=1000000;
|
||||
}
|
||||
}
|
||||
if (ts.maxRow[curOrder]<curRow) ts.maxRow[curOrder]=curRow;
|
||||
|
|
@ -425,6 +445,7 @@ void DivSubSong::calcTimestamps(int chans, std::vector<DivGroovePattern>& groove
|
|||
|
||||
std::chrono::high_resolution_clock::time_point timeEnd=std::chrono::high_resolution_clock::now();
|
||||
logV("calcTimestamps() took %dµs",std::chrono::duration_cast<std::chrono::microseconds>(timeEnd-timeStart).count());
|
||||
logV("song length: %s; %" PRIu64 " ticks",ts.totalTime.toString(6,TA_TIME_FORMAT_AUTO),ts.totalTicks);
|
||||
}
|
||||
|
||||
void DivSubSong::clearData() {
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ struct DivGroovePattern {
|
|||
struct DivSongTimestamps {
|
||||
// song duration (in seconds and microseconds)
|
||||
TimeMicros totalTime;
|
||||
int totalTicks;
|
||||
uint64_t totalTicks;
|
||||
int totalRows;
|
||||
|
||||
// loop region (order/row positions)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include "guiConst.h"
|
||||
#include "debug.h"
|
||||
#include "IconsFontAwesome4.h"
|
||||
#include <SDL_timer.h>
|
||||
#include <inttypes.h>
|
||||
#include <fmt/printf.h>
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
|
|
@ -208,7 +208,7 @@ void FurnaceGUI::drawDebug() {
|
|||
DivSongTimestamps& ts=e->curSubSong->ts;
|
||||
|
||||
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);
|
||||
ImGui::Text("song duration: %s (%" PRIu64 " ticks; %d rows)",timeFormatted.c_str(),ts.totalTicks,ts.totalRows);
|
||||
if (ts.isLoopDefined) {
|
||||
ImGui::Text("loop region is defined");
|
||||
} else {
|
||||
|
|
|
|||
10
src/main.cpp
10
src/main.cpp
|
|
@ -539,8 +539,10 @@ TAParamResult pBenchmark(String val) {
|
|||
benchMode=1;
|
||||
} else if (val=="seek") {
|
||||
benchMode=2;
|
||||
} else if (val=="walk") {
|
||||
benchMode=3;
|
||||
} else {
|
||||
logE("invalid value for benchmark! valid values are: render and seek.");
|
||||
logE("invalid value for benchmark! valid values are: render, seek and walk.");
|
||||
return TA_PARAM_ERROR;
|
||||
}
|
||||
e.setAudio(DIV_AUDIO_DUMMY);
|
||||
|
|
@ -653,7 +655,7 @@ void initParams() {
|
|||
params.push_back(TAParam("S","safemode",false,pSafeMode,"","enable safe mode (software rendering and no audio)"));
|
||||
params.push_back(TAParam("A","safeaudio",false,pSafeModeAudio,"","enable safe mode (with audio"));
|
||||
|
||||
params.push_back(TAParam("B","benchmark",true,pBenchmark,"render|seek","run performance test"));
|
||||
params.push_back(TAParam("B","benchmark",true,pBenchmark,"render|seek|walk","run performance test"));
|
||||
|
||||
params.push_back(TAParam("V","version",false,pVersion,"","view information about Furnace."));
|
||||
params.push_back(TAParam("W","warranty",false,pWarranty,"","view warranty disclaimer."));
|
||||
|
|
@ -1031,7 +1033,9 @@ int main(int argc, char** argv) {
|
|||
|
||||
if (benchMode) {
|
||||
logI("starting benchmark!");
|
||||
if (benchMode==2) {
|
||||
if (benchMode==3) {
|
||||
e.benchmarkWalk();
|
||||
} else if (benchMode==2) {
|
||||
e.benchmarkSeek();
|
||||
} else {
|
||||
e.benchmarkPlayback();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue