command stream preset instruments/volumes

This commit is contained in:
tildearrow 2025-11-10 18:27:45 -05:00
parent d3ce1a0b84
commit 92ad27f87e
5 changed files with 200 additions and 38 deletions

View file

@ -256,13 +256,14 @@ int DivCS::getInsLength(unsigned char ins, unsigned char ext, unsigned char* spe
case 0xc8: // vol slide
case 0xc9: // porta
return 3;
// speed dial commands
case 0xe0: case 0xe1: case 0xe2: case 0xe3:
case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0xe8: case 0xe9: case 0xea: case 0xeb:
return 1;
// speed dial commands
case 0xec: case 0xed: case 0xee: case 0xef:
if (speedDial==NULL) return 0;
return 1+getCmdLength(speedDial[ins&15]);
return 1+getCmdLength(speedDial[ins&3]);
case 0xd0: // opt
return 4;
case 0xd7: // cmd
@ -1257,12 +1258,18 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options
int loopRow=curSubSong->ts.loopStart.row;
logI("loop point: %d %d",loopOrder,loopRow);
int insPopularity[256];
int volPopularity[256];
int cmdPopularity[256];
int delayPopularity[256];
int sortedCmdPopularity[16];
int sortedInsPopularity[6];
int sortedVolPopularity[6];
int sortedCmdPopularity[4];
int sortedDelayPopularity[16];
unsigned char sortedCmd[16];
unsigned char sortedIns[6];
unsigned char sortedVol[6];
unsigned char sortedCmd[4];
unsigned char sortedDelay[16];
SafeWriter* globalStream;
@ -1272,14 +1279,20 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options
std::vector<size_t> tickPos[DIV_MAX_CHANS];
int loopTick=-1;
memset(insPopularity,0,256*sizeof(int));
memset(volPopularity,0,256*sizeof(int));
memset(cmdPopularity,0,256*sizeof(int));
memset(delayPopularity,0,256*sizeof(int));
memset(chanStream,0,DIV_MAX_CHANS*sizeof(void*));
memset(chanStreamOff,0,DIV_MAX_CHANS*sizeof(unsigned int));
memset(chanStackSize,0,DIV_MAX_CHANS*sizeof(unsigned int));
memset(sortedCmdPopularity,0,16*sizeof(int));
memset(sortedInsPopularity,0,6*sizeof(int));
memset(sortedVolPopularity,0,6*sizeof(int));
memset(sortedCmdPopularity,0,4*sizeof(int));
memset(sortedDelayPopularity,0,16*sizeof(int));
memset(sortedCmd,0,16);
memset(sortedIns,0,6);
memset(sortedVol,0,6);
memset(sortedCmd,0,4);
memset(sortedDelay,0,16);
SafeWriter* w=new SafeWriter;
@ -1386,6 +1399,11 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options
case DIV_CMD_PRE_NOTE:
break;
default:
if (i.cmd==DIV_CMD_HINT_VOLUME) {
volPopularity[i.value&0xff]++;
} else if (i.cmd==DIV_CMD_INSTRUMENT) {
insPopularity[i.value&0xff]++;
}
cmdPopularity[i.cmd]++;
writeCommandValues(chanStream[i.chan],i,options.bigEndian);
break;
@ -1450,12 +1468,97 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options
extValuePresent=false;
BUSY_END;
// PASS 1: optimize command calls
// PASS 1: optimize command calls and volume/instrument changes
if (!options.noCmdCallOpt) {
// calculate command usage
/// 1. instruments
// calculate instrument usage
int sortCand=-1;
int sortPos=0;
while (sortPos<16) {
while (sortPos<6) {
sortCand=-1;
for (int i=0; i<256; i++) {
if (insPopularity[i]) {
if (sortCand==-1) {
sortCand=i;
} else if (insPopularity[sortCand]<insPopularity[i]) {
sortCand=i;
}
}
}
if (sortCand==-1) break;
sortedInsPopularity[sortPos]=insPopularity[sortCand];
sortedIns[sortPos]=sortCand;
insPopularity[sortCand]=0;
sortPos++;
}
// set preset instruments
for (int h=0; h<chans; h++) {
unsigned char* buf=chanStream[h]->getFinalBuf();
for (size_t i=0; i<chanStream[h]->size(); i+=8) {
if (buf[i]==0xb8) {
// find whether this instrument is preset
for (int j=0; j<6; j++) {
if (buf[i+1]==sortedIns[j]) {
buf[i]=0xe0+j;
for (int k=i+1; k<(int)i+8; k++) {
buf[k]=0;
}
break;
}
}
}
}
}
/// 2. volumes
// calculate volume usage
sortCand=-1;
sortPos=0;
while (sortPos<6) {
sortCand=-1;
for (int i=0; i<256; i++) {
if (volPopularity[i]) {
if (sortCand==-1) {
sortCand=i;
} else if (volPopularity[sortCand]<volPopularity[i]) {
sortCand=i;
}
}
}
if (sortCand==-1) break;
sortedVolPopularity[sortPos]=volPopularity[sortCand];
sortedVol[sortPos]=sortCand;
volPopularity[sortCand]=0;
sortPos++;
}
// set preset volumes
for (int h=0; h<chans; h++) {
unsigned char* buf=chanStream[h]->getFinalBuf();
for (size_t i=0; i<chanStream[h]->size(); i+=8) {
if (buf[i]==0xc7) {
// find whether this volume is preset
for (int j=0; j<6; j++) {
if (buf[i+1]==sortedVol[j]) {
buf[i]=0xe6+j;
for (int k=i+1; k<(int)i+8; k++) {
buf[k]=0;
}
break;
}
}
}
}
}
/// 3. commands
// calculate command usage
sortCand=-1;
sortPos=0;
while (sortPos<4) {
sortCand=-1;
for (int i=DIV_CMD_SAMPLE_MODE; i<256; i++) {
if (cmdPopularity[i]) {
@ -1480,9 +1583,9 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options
for (size_t i=0; i<chanStream[h]->size(); i+=8) {
if (buf[i]==0xd7) {
// find whether this command is in speed dial
for (int j=0; j<16; j++) {
for (int j=0; j<4; j++) {
if (buf[i+1]==sortedCmd[j]) {
buf[i]=0xe0+j;
buf[i]=0xec+j;
// move everything to the left
for (int k=i+2; k<(int)i+8; k++) {
buf[k-1]=buf[k];
@ -1795,8 +1898,20 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options
if (sortedDelayPopularity[i]) logD("- %d: %d",sortedDelay[i],sortedDelayPopularity[i]);
}
logD("instrument popularity:");
for (int i=0; i<6; i++) {
w->writeC(sortedIns[i]);
logD("- $%.2x: %d",sortedIns[i],sortedInsPopularity[i]);
}
logD("volume popularity:");
for (int i=0; i<6; i++) {
w->writeC(sortedVol[i]);
logD("- $%.2x: %d",sortedVol[i],sortedVolPopularity[i]);
}
logD("command popularity:");
for (int i=0; i<16; i++) {
for (int i=0; i<4; i++) {
w->writeC(sortedCmd[i]);
if (sortedCmdPopularity[i]) logD("- %s ($%.2x): %d",cmdName[sortedCmd[i]],sortedCmd[i],sortedCmdPopularity[i]);
}