rework some of the playback logic

paving the way for C64
This commit is contained in:
tildearrow 2021-12-05 16:11:12 -05:00
parent ff07a19405
commit 0f3f173b6e
5 changed files with 65 additions and 74 deletions

View File

@ -15,6 +15,7 @@ enum DivDispatchCmds {
DIV_CMD_PANNING, DIV_CMD_PANNING,
DIV_CMD_LEGATO, DIV_CMD_LEGATO,
DIV_CMD_PRE_PORTA, DIV_CMD_PRE_PORTA,
DIV_CMD_PRE_NOTE, // used in C64
DIV_CMD_SAMPLE_MODE, DIV_CMD_SAMPLE_MODE,

View File

@ -20,6 +20,7 @@ struct DivChannelState {
std::vector<DivDelayedCommand> delayed; std::vector<DivDelayedCommand> delayed;
int note, pitch, portaSpeed, portaNote; int note, pitch, portaSpeed, portaNote;
int volume, volSpeed, cut, rowDelay, volMax; int volume, volSpeed, cut, rowDelay, volMax;
int delayOrder, delayRow;
int vibratoDepth, vibratoRate, vibratoPos, vibratoDir, vibratoFine; int vibratoDepth, vibratoRate, vibratoPos, vibratoDir, vibratoFine;
int tremoloDepth, tremoloRate, tremoloPos; int tremoloDepth, tremoloRate, tremoloPos;
unsigned char arp, arpStage, arpTicks; unsigned char arp, arpStage, arpTicks;
@ -34,6 +35,8 @@ struct DivChannelState {
volSpeed(0), volSpeed(0),
cut(-1), cut(-1),
rowDelay(0), rowDelay(0),
delayOrder(0),
delayRow(0),
vibratoDepth(0), vibratoDepth(0),
vibratoRate(0), vibratoRate(0),
vibratoPos(0), vibratoPos(0),
@ -104,7 +107,7 @@ class DivEngine {
speedAB(false), speedAB(false),
ticks(0), ticks(0),
cycles(0), cycles(0),
curRow(-1), curRow(0),
curOrder(0), curOrder(0),
changeOrd(-1), changeOrd(-1),
changePos(0), changePos(0),

View File

@ -10,31 +10,6 @@ void DivPlatformC64::acquire(int& l, int& r) {
r=l; r=l;
} }
static unsigned char noiseTable[256]={
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 4,
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4,
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4,
3, 2, 1, 0, 11, 10, 9, 8, 7, 6, 5, 4,
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4,
3, 2, 1, 0, 11, 10, 9, 8, 7, 6, 5, 4,
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4,
3, 2, 1, 0, 11, 10, 9, 8, 7, 6, 5, 4,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15
};
void DivPlatformC64::tick() { void DivPlatformC64::tick() {
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
chan[i].std.next(); chan[i].std.next();
@ -84,16 +59,10 @@ void DivPlatformC64::tick() {
//rWrite(16+i*5,chan[i].sweep); //rWrite(16+i*5,chan[i].sweep);
} }
} }
if (chan[i].onTheKey) { if (chan[i].testWhen>0) {
DivInstrument* ins=parent->getIns(chan[i].ins); if (--chan[i].testWhen<1) {
sid.write(i*7+4, sid.write(i*7+4,8);
(ins->c64.noiseOn<<7)| }
(ins->c64.pulseOn<<6)|
(ins->c64.sawOn<<5)|
(ins->c64.triOn<<4)|
1
);
chan[i].onTheKey=false;
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
DivInstrument* ins=parent->getIns(chan[i].ins); DivInstrument* ins=parent->getIns(chan[i].ins);
@ -106,9 +75,8 @@ void DivPlatformC64::tick() {
(ins->c64.pulseOn<<6)| (ins->c64.pulseOn<<6)|
(ins->c64.sawOn<<5)| (ins->c64.sawOn<<5)|
(ins->c64.triOn<<4)| (ins->c64.triOn<<4)|
8 1
); );
chan[i].onTheKey=true;
} }
if (chan[i].keyOff) { if (chan[i].keyOff) {
sid.write(i*7+5,(ins->c64.a<<4)|(ins->c64.d)); sid.write(i*7+5,(ins->c64.a<<4)|(ins->c64.d));
@ -207,6 +175,9 @@ int DivPlatformC64::dispatch(DivCommand c) {
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins)); chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;
case DIV_CMD_PRE_NOTE:
chan[c.chan].testWhen=c.value;
break;
case DIV_CMD_GET_VOLMAX: case DIV_CMD_GET_VOLMAX:
return 15; return 15;
break; break;

View File

@ -7,9 +7,9 @@
class DivPlatformC64: public DivDispatch { class DivPlatformC64: public DivDispatch {
struct Channel { struct Channel {
int freq, baseFreq, pitch, prevFreq; int freq, baseFreq, pitch, prevFreq, testWhen;
unsigned char ins, note, duty, sweep; unsigned char ins, note, duty, sweep;
bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, onTheKey; bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta;
signed char vol, outVol, wave; signed char vol, outVol, wave;
DivMacroInt std; DivMacroInt std;
Channel(): Channel():
@ -17,6 +17,7 @@ class DivPlatformC64: public DivDispatch {
baseFreq(0), baseFreq(0),
pitch(0), pitch(0),
prevFreq(65535), prevFreq(65535),
testWhen(0),
ins(-1), ins(-1),
note(0), note(0),
duty(0), duty(0),
@ -28,7 +29,6 @@ class DivPlatformC64: public DivDispatch {
keyOn(false), keyOn(false),
keyOff(false), keyOff(false),
inPorta(false), inPorta(false),
onTheKey(false),
vol(15), vol(15),
wave(-1) {} wave(-1) {}
}; };

View File

@ -23,6 +23,7 @@ const char* cmdName[DIV_CMD_MAX]={
"PANNING", "PANNING",
"LEGATO", "LEGATO",
"PRE_PORTA", "PRE_PORTA",
"PRE_NOTE",
"SAMPLE_MODE", "SAMPLE_MODE",
@ -205,25 +206,29 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char
} }
void DivEngine::processRow(int i, bool afterDelay) { void DivEngine::processRow(int i, bool afterDelay) {
DivPattern* pat=song.pat[i]->data[curOrder]; int whatOrder=afterDelay?chan[i].delayOrder:curOrder;
int whatRow=afterDelay?chan[i].delayRow:curRow;
DivPattern* pat=song.pat[i]->data[whatOrder];
// pre effects // pre effects
if (!afterDelay) for (int j=0; j<song.pat[i]->effectRows; j++) { if (!afterDelay) for (int j=0; j<song.pat[i]->effectRows; j++) {
short effect=pat->data[curRow][4+(j<<1)]; short effect=pat->data[whatRow][4+(j<<1)];
short effectVal=pat->data[curRow][5+(j<<1)]; short effectVal=pat->data[whatRow][5+(j<<1)];
if (effectVal==-1) effectVal=0; if (effectVal==-1) effectVal=0;
if (effect==0xed) { if (effect==0xed) {
chan[i].rowDelay=effectVal+1; chan[i].rowDelay=effectVal+1;
chan[i].delayOrder=whatOrder;
chan[i].delayRow=whatRow;
return; return;
} }
} }
// instrument // instrument
if (pat->data[curRow][2]!=-1) { if (pat->data[whatRow][2]!=-1) {
dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,i,pat->data[curRow][2])); dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,i,pat->data[whatRow][2]));
} }
// note // note
if (pat->data[curRow][0]==100) { if (pat->data[whatRow][0]==100) {
chan[i].note=-1; chan[i].note=-1;
chan[i].keyOn=false; chan[i].keyOn=false;
if (chan[i].stopOnOff) { if (chan[i].stopOnOff) {
@ -232,8 +237,8 @@ void DivEngine::processRow(int i, bool afterDelay) {
chan[i].stopOnOff=false; chan[i].stopOnOff=false;
} }
dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i)); dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i));
} else if (!(pat->data[curRow][0]==0 && pat->data[curRow][1]==0)) { } else if (!(pat->data[whatRow][0]==0 && pat->data[whatRow][1]==0)) {
chan[i].note=pat->data[curRow][0]+pat->data[curRow][1]*12; chan[i].note=pat->data[whatRow][0]+pat->data[whatRow][1]*12;
if (!chan[i].keyOn) { if (!chan[i].keyOn) {
chan[i].arp=0; chan[i].arp=0;
} }
@ -244,17 +249,17 @@ void DivEngine::processRow(int i, bool afterDelay) {
} }
// volume // volume
if (pat->data[curRow][3]!=-1) { if (pat->data[whatRow][3]!=-1) {
if (dispatchCmd(DivCommand(DIV_ALWAYS_SET_VOLUME,i)) || (MIN(chan[i].volMax,chan[i].volume)>>8)!=pat->data[curRow][3]) { if (dispatchCmd(DivCommand(DIV_ALWAYS_SET_VOLUME,i)) || (MIN(chan[i].volMax,chan[i].volume)>>8)!=pat->data[whatRow][3]) {
chan[i].volume=pat->data[curRow][3]<<8; chan[i].volume=pat->data[whatRow][3]<<8;
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8)); dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
} }
} }
// effects // effects
for (int j=0; j<song.pat[i]->effectRows; j++) { for (int j=0; j<song.pat[i]->effectRows; j++) {
short effect=pat->data[curRow][4+(j<<1)]; short effect=pat->data[whatRow][4+(j<<1)];
short effectVal=pat->data[curRow][5+(j<<1)]; short effectVal=pat->data[whatRow][5+(j<<1)];
if (effectVal==-1) effectVal=0; if (effectVal==-1) effectVal=0;
@ -336,6 +341,8 @@ void DivEngine::processRow(int i, bool afterDelay) {
break; break;
case 0x0c: // retrigger case 0x0c: // retrigger
chan[i].rowDelay=effectVal+1; chan[i].rowDelay=effectVal+1;
chan[i].delayOrder=whatOrder;
chan[i].delayRow=whatRow;
break; break;
case 0xe0: // arp speed case 0xe0: // arp speed
@ -399,8 +406,8 @@ void DivEngine::processRow(int i, bool afterDelay) {
// post effects // post effects
for (int j=0; j<song.pat[i]->effectRows; j++) { for (int j=0; j<song.pat[i]->effectRows; j++) {
short effect=pat->data[curRow][4+(j<<1)]; short effect=pat->data[whatRow][4+(j<<1)];
short effectVal=pat->data[curRow][5+(j<<1)]; short effectVal=pat->data[whatRow][5+(j<<1)];
if (effectVal==-1) effectVal=0; if (effectVal==-1) effectVal=0;
perSystemPostEffect(i,effect,effectVal); perSystemPostEffect(i,effect,effectVal);
@ -412,18 +419,6 @@ void DivEngine::nextRow() {
static char pb1[4096]; static char pb1[4096];
static char pb2[4096]; static char pb2[4096];
static char pb3[4096]; static char pb3[4096];
if (++curRow>=song.patLen) {
nextOrder();
}
if (changeOrd>=0) {
curRow=changePos;
curOrder=changeOrd;
if (curOrder>=song.ordersLen) {
curOrder=0;
}
changeOrd=-1;
}
if (view==DIV_STATUS_PATTERN) { if (view==DIV_STATUS_PATTERN) {
strcpy(pb1,""); strcpy(pb1,"");
strcpy(pb3,""); strcpy(pb3,"");
@ -469,6 +464,33 @@ void DivEngine::nextRow() {
chan[i].rowDelay=0; chan[i].rowDelay=0;
processRow(i,false); processRow(i,false);
} }
if (++curRow>=song.patLen) {
nextOrder();
}
if (changeOrd>=0) {
curRow=changePos;
curOrder=changeOrd;
if (curOrder>=song.ordersLen) {
curOrder=0;
}
changeOrd=-1;
}
if (speedAB) {
ticks=song.speed2*(song.timeBase+1);
} else {
ticks=song.speed1*(song.timeBase+1);
}
speedAB=!speedAB;
// post row details
for (int i=0; i<chans; i++) {
DivPattern* pat=song.pat[i]->data[curOrder];
if (!(pat->data[curRow][0]==0 && pat->data[curRow][1]==0)) {
dispatchCmd(DivCommand(DIV_CMD_PRE_NOTE,i,ticks));
}
}
} }
void DivEngine::nextTick() { void DivEngine::nextTick() {
@ -483,12 +505,6 @@ void DivEngine::nextTick() {
} }
if (--ticks<=0) { if (--ticks<=0) {
nextRow(); nextRow();
if (speedAB) {
ticks=song.speed2*(song.timeBase+1);
} else {
ticks=song.speed1*(song.timeBase+1);
}
speedAB=!speedAB;
} }
// process stuff // process stuff
for (int i=0; i<chans; i++) { for (int i=0; i<chans; i++) {