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_LEGATO,
DIV_CMD_PRE_PORTA,
DIV_CMD_PRE_NOTE, // used in C64
DIV_CMD_SAMPLE_MODE,

View File

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

View File

@ -10,31 +10,6 @@ void DivPlatformC64::acquire(int& l, int& r) {
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() {
for (int i=0; i<3; i++) {
chan[i].std.next();
@ -84,16 +59,10 @@ void DivPlatformC64::tick() {
//rWrite(16+i*5,chan[i].sweep);
}
}
if (chan[i].onTheKey) {
DivInstrument* ins=parent->getIns(chan[i].ins);
sid.write(i*7+4,
(ins->c64.noiseOn<<7)|
(ins->c64.pulseOn<<6)|
(ins->c64.sawOn<<5)|
(ins->c64.triOn<<4)|
1
);
chan[i].onTheKey=false;
if (chan[i].testWhen>0) {
if (--chan[i].testWhen<1) {
sid.write(i*7+4,8);
}
}
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
DivInstrument* ins=parent->getIns(chan[i].ins);
@ -106,9 +75,8 @@ void DivPlatformC64::tick() {
(ins->c64.pulseOn<<6)|
(ins->c64.sawOn<<5)|
(ins->c64.triOn<<4)|
8
1
);
chan[i].onTheKey=true;
}
if (chan[i].keyOff) {
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].inPorta=c.value;
break;
case DIV_CMD_PRE_NOTE:
chan[c.chan].testWhen=c.value;
break;
case DIV_CMD_GET_VOLMAX:
return 15;
break;

View File

@ -7,9 +7,9 @@
class DivPlatformC64: public DivDispatch {
struct Channel {
int freq, baseFreq, pitch, prevFreq;
int freq, baseFreq, pitch, prevFreq, testWhen;
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;
DivMacroInt std;
Channel():
@ -17,6 +17,7 @@ class DivPlatformC64: public DivDispatch {
baseFreq(0),
pitch(0),
prevFreq(65535),
testWhen(0),
ins(-1),
note(0),
duty(0),
@ -28,7 +29,6 @@ class DivPlatformC64: public DivDispatch {
keyOn(false),
keyOff(false),
inPorta(false),
onTheKey(false),
vol(15),
wave(-1) {}
};

View File

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