add Cxxx effect for mid-song Hz change

also add hang detection as I ran into one of them while test multi-chip
This commit is contained in:
tildearrow 2022-01-12 02:45:26 -05:00
parent d19d37c561
commit 6245b3af31
4 changed files with 78 additions and 29 deletions

View File

@ -2236,6 +2236,8 @@ void DivEngine::playSub(bool preserveDrift) {
} else { } else {
ticks=1; ticks=1;
totalTicks=0; totalTicks=0;
totalSeconds=0;
totalTicksR=0;
} }
speedAB=false; speedAB=false;
playing=true; playing=true;
@ -2308,6 +2310,16 @@ void DivEngine::reset() {
speed1=song.speed1; speed1=song.speed1;
speed2=song.speed2; speed2=song.speed2;
nextSpeed=speed1; nextSpeed=speed1;
divider=60;
if (song.customTempo) {
divider=song.hz;
} else {
if (song.pal) {
divider=60;
} else {
divider=50;
}
}
globalPitch=0; globalPitch=0;
for (int i=0; i<song.systemLen; i++) { for (int i=0; i<song.systemLen; i++) {
disCont[i].clear(); disCont[i].clear();
@ -2418,6 +2430,14 @@ int DivEngine::getHz() {
return 60; return 60;
} }
int DivEngine::getCurHz() {
return divider;
}
int DivEngine::getTotalSeconds() {
return totalSeconds;
}
int DivEngine::getTotalTicks() { int DivEngine::getTotalTicks() {
return totalTicks; return totalTicks;
} }
@ -2826,6 +2846,17 @@ void DivEngine::setSongRate(int hz, bool pal) {
for (int i=0; i<song.systemLen; i++) { for (int i=0; i<song.systemLen; i++) {
disCont[i].dispatch->setPAL((!song.pal) || (song.customTempo!=0 && song.hz<53)); disCont[i].dispatch->setPAL((!song.pal) || (song.customTempo!=0 && song.hz<53));
disCont[i].setRates(got.rate); disCont[i].setRates(got.rate);
disCont[i].clockDrift=0;
}
divider=60;
if (song.customTempo) {
divider=song.hz;
} else {
if (song.pal) {
divider=60;
} else {
divider=50;
}
} }
isBusy.unlock(); isBusy.unlock();
} }
@ -2879,6 +2910,8 @@ void DivEngine::quitDispatch() {
changeOrd=-1; changeOrd=-1;
changePos=0; changePos=0;
totalTicks=0; totalTicks=0;
totalSeconds=0;
totalTicksR=0;
totalCmds=0; totalCmds=0;
lastCmds=0; lastCmds=0;
cmdsPerSecond=0; cmdsPerSecond=0;

View File

@ -121,8 +121,8 @@ class DivEngine {
bool extValuePresent; bool extValuePresent;
bool repeatPattern; bool repeatPattern;
bool metronome; bool metronome;
int ticks, curRow, curOrder, remainingLoops, nextSpeed; int ticks, curRow, curOrder, remainingLoops, nextSpeed, divider;
int changeOrd, changePos, totalTicks, totalCmds, lastCmds, cmdsPerSecond, globalPitch; int changeOrd, changePos, totalSeconds, totalTicks, totalTicksR, totalCmds, lastCmds, cmdsPerSecond, globalPitch;
unsigned char extValue; unsigned char extValue;
unsigned char speed1, speed2; unsigned char speed1, speed2;
DivStatusView view; DivStatusView view;
@ -298,8 +298,12 @@ class DivEngine {
// get Hz // get Hz
int getHz(); int getHz();
// get current Hz
int getCurHz();
// get time // get time
int getTotalTicks(); int getTotalTicks(); // 1/1000000th of a second
int getTotalSeconds();
// get repeat pattern // get repeat pattern
bool getRepeatPattern(); bool getRepeatPattern();
@ -437,9 +441,12 @@ class DivEngine {
curOrder(0), curOrder(0),
remainingLoops(-1), remainingLoops(-1),
nextSpeed(3), nextSpeed(3),
divider(60),
changeOrd(-1), changeOrd(-1),
changePos(0), changePos(0),
totalSeconds(0),
totalTicks(0), totalTicks(0),
totalTicksR(0),
totalCmds(0), totalCmds(0),
lastCmds(0), lastCmds(0),
cmdsPerSecond(0), cmdsPerSecond(0),

View File

@ -90,7 +90,7 @@ const char* formatNote(unsigned char note, unsigned char octave) {
int DivEngine::dispatchCmd(DivCommand c) { int DivEngine::dispatchCmd(DivCommand c) {
if (view==DIV_STATUS_COMMANDS) { if (view==DIV_STATUS_COMMANDS) {
printf("%8d | %d: %s(%d, %d)\n",totalTicks,c.chan,cmdName[c.cmd],c.value,c.value2); printf("%8d | %d: %s(%d, %d)\n",totalTicksR,c.chan,cmdName[c.cmd],c.value,c.value2);
} }
totalCmds++; totalCmds++;
c.chan=dispatchChanOfChan[c.dis]; c.chan=dispatchChanOfChan[c.dis];
@ -506,6 +506,16 @@ void DivEngine::processRow(int i, bool afterDelay) {
chan[i].delayRow=whatRow; chan[i].delayRow=whatRow;
} }
break; break;
case 0xc0: case 0xc1: case 0xc2: case 0xc3: // set Hz
divider=((effect&0x3)<<8)|effectVal;
if (divider<10) divider=10;
for (int i=0; i<song.systemLen; i++) {
disCont[i].clockDrift=0;
}
break;
case 0xc4: // set Hz by tempo
// TODO
break;
case 0xe0: // arp speed case 0xe0: // arp speed
song.arpLen=effectVal; song.arpLen=effectVal;
break; break;
@ -688,16 +698,7 @@ void DivEngine::nextRow() {
bool DivEngine::nextTick(bool noAccum) { bool DivEngine::nextTick(bool noAccum) {
bool ret=false; bool ret=false;
int divider=60; if (divider<10) divider=10;
if (song.customTempo) {
divider=song.hz;
} else {
if (song.pal) {
divider=60;
} else {
divider=50;
}
}
for (int i=0; i<song.systemLen; i++) { for (int i=0; i<song.systemLen; i++) {
DivDispatchContainer& dc=disCont[i]; DivDispatchContainer& dc=disCont[i];
@ -810,22 +811,18 @@ bool DivEngine::nextTick(bool noAccum) {
for (int i=0; i<song.systemLen; i++) disCont[i].dispatch->tick(); for (int i=0; i<song.systemLen; i++) disCont[i].dispatch->tick();
if (!freelance) { if (!freelance) {
if (!noAccum) totalTicks++; if (!noAccum) {
totalTicksR++;
int hz; totalTicks+=1000000/divider;
if (song.customTempo) {
hz=song.hz;
} else if (song.pal) {
hz=60;
} else {
hz=50;
} }
if (consoleMode) fprintf(stderr,"\x1b[2K> %d:%.2d:%.2d.%.2d %.2x/%.2x:%.3d/%.3d %4dcmd/s\x1b[G",totalTicks/(hz*3600),(totalTicks/(hz*60))%60,(totalTicks/hz)%60,totalTicks%hz,curOrder,song.ordersLen,curRow,song.patLen,cmdsPerSecond); if (totalTicks>=1000000) {
totalTicks-=1000000;
if ((totalTicks%hz)==0) { totalSeconds++;
cmdsPerSecond=totalCmds-lastCmds; cmdsPerSecond=totalCmds-lastCmds;
lastCmds=totalCmds; lastCmds=totalCmds;
} }
if (consoleMode) 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,song.ordersLen,curRow,song.patLen,cmdsPerSecond);
} }
return ret; return ret;
@ -900,7 +897,8 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
memset(metroTick,0,size); memset(metroTick,0,size);
while (true) { int attempts=0;
while (++attempts<1000) {
bool allDone=true; bool allDone=true;
bool getOut=true; bool getOut=true;
// 1. check whether we are done with all buffers // 1. check whether we are done with all buffers
@ -948,6 +946,13 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
runPos[i]+=total; runPos[i]+=total;
} }
} }
logD("attempts: %d\n",attempts);
if (attempts>=1000) {
logE("hang detected! stopping!\n");
freelance=false;
playing=false;
extValuePresent=false;
}
totalProcessed=(1+runPos[0])*got.rate/disCont[0].dispatch->rate; totalProcessed=(1+runPos[0])*got.rate/disCont[0].dispatch->rate;
for (int i=0; i<song.systemLen; i++) { for (int i=0; i<song.systemLen; i++) {

View File

@ -1436,6 +1436,10 @@ void FurnaceGUI::drawPattern() {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY]); ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY]);
} else if (pat->data[i][index]<0x48) { } else if (pat->data[i][index]<0x48) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY]); ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY]);
} else if (pat->data[i][index]<0xc0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
} else if (pat->data[i][index]<0xd0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SPEED]);
} else if (pat->data[i][index]<0xe0) { } else if (pat->data[i][index]<0xe0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]); ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
} else if (pat->data[i][index]<0xf0) { } else if (pat->data[i][index]<0xf0) {
@ -2948,8 +2952,8 @@ bool FurnaceGUI::loop() {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PLAYBACK_STAT]); ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PLAYBACK_STAT]);
if (e->isPlaying()) { if (e->isPlaying()) {
int totalTicks=e->getTotalTicks(); int totalTicks=e->getTotalTicks();
int hz=e->getHz(); int totalSeconds=e->getTotalSeconds();
ImGui::Text("| Speed %d:%d | Order %d/%d | Row %d/%d | %d:%.2d:%.2d.%.2d",e->getSpeed1(),e->getSpeed2(),e->getOrder(),e->song.ordersLen,e->getRow(),e->song.patLen,totalTicks/(hz*3600),(totalTicks/(hz*60))%60,(totalTicks/hz)%60,(totalTicks%hz)*100/hz); 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);
} else { } else {
if (curFileName!="") ImGui::Text("| %s",curFileName.c_str()); if (curFileName!="") ImGui::Text("| %s",curFileName.c_str());
} }