introduce a benchmark mode

This commit is contained in:
tildearrow 2022-07-19 17:01:19 -05:00
parent a4741861ce
commit cd7b333b2d
4 changed files with 119 additions and 2 deletions

32
src/asm/6502/macroInt.s Normal file
View File

@ -0,0 +1,32 @@
macroState=$50 ; pointer to state
macroAddr=$52 ; pointer to address
; macro state takes 4 bytes
; macroPos bits:
; 7: had
; 6: will
; x: macro
macroIntRun:
lda macroAddr,x
ora macroAddr+1,x
beq :+
; do macro
: rts
; set the macro address, then call
; x: macro
macroIntInit:
lda #0
sta macroState,x
sta macroPos,x
txa
rol
tax
lda macroAddr,x
ora macroAddr+1,x
beq :+
lda #$40
sta macroState,x
: rts

View File

@ -36,6 +36,7 @@
#include "../audio/jack.h"
#endif
#include <math.h>
#include <float.h>
#ifdef HAVE_SNDFILE
#include "sfWrapper.h"
#endif
@ -181,6 +182,63 @@ void DivEngine::walkSong(int& loopOrder, int& loopRow, int& loopEnd) {
}
}
#define EXPORT_BUFSIZE 2048
double DivEngine::benchmarkPlayback() {
float* outBuf[2];
outBuf[0]=new float[EXPORT_BUFSIZE];
outBuf[1]=new float[EXPORT_BUFSIZE];
curOrder=0;
prevOrder=0;
remainingLoops=1;
playSub(false);
std::chrono::high_resolution_clock::time_point timeStart=std::chrono::high_resolution_clock::now();
// benchmark
while (playing) {
nextBuf(NULL,outBuf,0,2,EXPORT_BUFSIZE);
}
std::chrono::high_resolution_clock::time_point timeEnd=std::chrono::high_resolution_clock::now();
delete[] outBuf[0];
delete[] outBuf[1];
double t=(double)(std::chrono::duration_cast<std::chrono::microseconds>(timeEnd-timeStart).count())/1000000.0;
printf("[RESULT] %fs\n",t);
return t;
}
double DivEngine::benchmarkSeek() {
double t[20];
curOrder=curSubSong->ordersLen-1;
prevOrder=curSubSong->ordersLen-1;
// benchmark
for (int i=0; i<20; i++) {
std::chrono::high_resolution_clock::time_point timeStart=std::chrono::high_resolution_clock::now();
playSub(false);
std::chrono::high_resolution_clock::time_point timeEnd=std::chrono::high_resolution_clock::now();
t[i]=(double)(std::chrono::duration_cast<std::chrono::microseconds>(timeEnd-timeStart).count())/1000000.0;
printf("[#%d] %fs\n",i+1,t[i]);
}
double tMin=DBL_MAX;
double tMax=0.0;
double tAvg=0.0;
for (int i=0; i<20; i++) {
if (t[i]<tMin) tMin=t[i];
if (t[i]>tMax) tMax=t[i];
tAvg+=t[i];
}
tAvg/=20.0;
printf("[RESULT] min %fs max %fs average %fs\n",tMin,tMax,tAvg);
return tAvg;
}
void _runExportThread(DivEngine* caller) {
caller->runExportThread();
}
@ -189,8 +247,6 @@ bool DivEngine::isExporting() {
return exporting;
}
#define EXPORT_BUFSIZE 2048
#ifdef HAVE_SNDFILE
void DivEngine::runExportThread() {
size_t fadeOutSamples=got.rate*exportFadeOut;

View File

@ -477,6 +477,10 @@ class DivEngine {
// notify wavetable change
void notifyWaveChange(int wave);
// benchmark (returns time in seconds)
double benchmarkPlayback();
double benchmarkSeek();
// returns the minimum VGM version which may carry the specified system, or 0 if none.
int minVGMVersion(DivSystem which);

View File

@ -49,6 +49,7 @@ FurnaceGUI g;
String outName;
String vgmOutName;
int loops=1;
int benchMode=0;
DivAudioExportModes outMode=DIV_EXPORT_MODE_ONE;
#ifdef HAVE_GUI
@ -220,6 +221,19 @@ TAParamResult pOutMode(String val) {
return TA_PARAM_SUCCESS;
}
TAParamResult pBenchmark(String val) {
if (val=="render") {
benchMode=1;
} else if (val=="seek") {
benchMode=2;
} else {
logE("invalid value for benchmark! valid values are: render and seek.");
return TA_PARAM_ERROR;
}
e.setAudio(DIV_AUDIO_DUMMY);
return TA_PARAM_SUCCESS;
}
TAParamResult pOutput(String val) {
outName=val;
e.setAudio(DIV_AUDIO_DUMMY);
@ -254,6 +268,8 @@ void initParams() {
params.push_back(TAParam("l","loops",true,pLoops,"<count>","set number of loops (-1 means loop forever)"));
params.push_back(TAParam("o","outmode",true,pOutMode,"one|persys|perchan","set file output mode"));
params.push_back(TAParam("B","benchmark",true,pBenchmark,"render|seek","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."));
}
@ -414,6 +430,15 @@ int main(int argc, char** argv) {
displayEngineFailError=true;
}
}
if (benchMode) {
logI("starting benchmark!");
if (benchMode==2) {
e.benchmarkSeek();
} else {
e.benchmarkPlayback();
}
return 0;
}
if (outName!="" || vgmOutName!="") {
if (vgmOutName!="") {
SafeWriter* w=e.saveVGM();