implement 05xy/06xy

issue #1044
This commit is contained in:
tildearrow 2023-04-30 13:46:09 -05:00
parent 78b7049d81
commit 8bc0781f59
3 changed files with 79 additions and 1 deletions

View file

@ -55,6 +55,10 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul
return "03xx: Portamento"; return "03xx: Portamento";
case 0x04: case 0x04:
return "04xy: Vibrato (x: speed; y: depth)"; return "04xy: Vibrato (x: speed; y: depth)";
case 0x05:
return "05xy: Volume slide + vibrato (compatibility only!)";
case 0x06:
return "06xy: Volume slide + portamento (compatibility only!)";
case 0x07: case 0x07:
return "07xy: Tremolo (x: speed; y: depth)"; return "07xy: Tremolo (x: speed; y: depth)";
case 0x08: case 0x08:

View file

@ -105,7 +105,7 @@ struct DivChannelState {
int delayOrder, delayRow, retrigSpeed, retrigTick; int delayOrder, delayRow, retrigSpeed, retrigTick;
int vibratoDepth, vibratoRate, vibratoPos, vibratoPosGiant, vibratoDir, vibratoFine; int vibratoDepth, vibratoRate, vibratoPos, vibratoPosGiant, vibratoDir, vibratoFine;
int tremoloDepth, tremoloRate, tremoloPos; int tremoloDepth, tremoloRate, tremoloPos;
unsigned char arp, arpStage, arpTicks, panL, panR, panRL, panRR; unsigned char arp, arpStage, arpTicks, panL, panR, panRL, panRR, lastVibrato, lastPorta;
bool doNote, legato, portaStop, keyOn, keyOff, nowYouCanStop, stopOnOff; bool doNote, legato, portaStop, keyOn, keyOff, nowYouCanStop, stopOnOff;
bool arpYield, delayLocked, inPorta, scheduledSlideReset, shorthandPorta, wasShorthandPorta, noteOnInhibit, resetArp; bool arpYield, delayLocked, inPorta, scheduledSlideReset, shorthandPorta, wasShorthandPorta, noteOnInhibit, resetArp;
bool wentThroughNote, goneThroughNote; bool wentThroughNote, goneThroughNote;
@ -146,6 +146,8 @@ struct DivChannelState {
panR(255), panR(255),
panRL(0), panRL(0),
panRR(0), panRR(0),
lastVibrato(0),
lastPorta(0),
doNote(false), doNote(false),
legato(false), legato(false),
portaStop(false), portaStop(false),

View file

@ -680,6 +680,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
chan[i].inPorta=false; chan[i].inPorta=false;
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
} else { } else {
chan[i].lastPorta=effectVal;
calledPorta=true; calledPorta=true;
if (chan[i].note==chan[i].oldNote && !chan[i].inPorta && song.buggyPortaAfterSlide) { if (chan[i].note==chan[i].oldNote && !chan[i].inPorta && song.buggyPortaAfterSlide) {
chan[i].portaNote=chan[i].note; chan[i].portaNote=chan[i].note;
@ -700,11 +701,78 @@ void DivEngine::processRow(int i, bool afterDelay) {
} }
break; break;
case 0x04: // vibrato case 0x04: // vibrato
if (effectVal) chan[i].lastVibrato=effectVal;
chan[i].vibratoDepth=effectVal&15; chan[i].vibratoDepth=effectVal&15;
chan[i].vibratoRate=effectVal>>4; chan[i].vibratoRate=effectVal>>4;
dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,chan[i].vibratoDepth,chan[i].vibratoRate)); dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,chan[i].vibratoDepth,chan[i].vibratoRate));
dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15))); dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15)));
break; break;
case 0x05: // vol slide + vibrato
if (effectVal==0) {
chan[i].vibratoDepth=0;
chan[i].vibratoRate=0;
} else {
chan[i].vibratoDepth=chan[i].lastVibrato&15;
chan[i].vibratoRate=chan[i].lastVibrato>>4;
}
dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,chan[i].vibratoDepth,chan[i].vibratoRate));
dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15)));
// TODO: non-0x-or-x0 value should be treated as 00
if (effectVal!=0) {
if ((effectVal&15)!=0) {
chan[i].volSpeed=-(effectVal&15)*64;
} else {
chan[i].volSpeed=(effectVal>>4)*64;
}
// tremolo and vol slides are incompatible
chan[i].tremoloDepth=0;
chan[i].tremoloRate=0;
} else {
chan[i].volSpeed=0;
}
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,chan[i].volSpeed));
break;
case 0x06: // vol slide + porta
if (effectVal==0 || chan[i].lastPorta==0) {
chan[i].portaNote=-1;
chan[i].portaSpeed=-1;
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0)));
chan[i].inPorta=false;
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
} else {
calledPorta=true;
if (chan[i].note==chan[i].oldNote && !chan[i].inPorta && song.buggyPortaAfterSlide) {
chan[i].portaNote=chan[i].note;
chan[i].portaSpeed=-1;
} else {
chan[i].portaNote=chan[i].note;
chan[i].portaSpeed=chan[i].lastPorta;
chan[i].inPorta=true;
chan[i].wasShorthandPorta=false;
}
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0)));
chan[i].portaStop=true;
if (chan[i].keyOn) chan[i].doNote=false;
chan[i].stopOnOff=song.stopPortaOnNoteOff; // what?!
chan[i].scheduledSlideReset=false;
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,1));
lastSlide=0x1337; // i hate this so much
}
// TODO: non-0x-or-x0 value should be treated as 00
if (effectVal!=0) {
if ((effectVal&15)!=0) {
chan[i].volSpeed=-(effectVal&15)*64;
} else {
chan[i].volSpeed=(effectVal>>4)*64;
}
// tremolo and vol slides are incompatible
chan[i].tremoloDepth=0;
chan[i].tremoloRate=0;
} else {
chan[i].volSpeed=0;
}
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,chan[i].volSpeed));
break;
case 0x07: // tremolo case 0x07: // tremolo
// TODO // TODO
// this effect is really weird. i thought it would alter the tremolo depth but turns out it's completely different // this effect is really weird. i thought it would alter the tremolo depth but turns out it's completely different
@ -1148,6 +1216,10 @@ void DivEngine::nextRow() {
doPrepareCut=false; doPrepareCut=false;
break; break;
} }
if (pat->data[curRow][4+(j<<1)]==0x06) {
doPrepareCut=false;
break;
}
if (pat->data[curRow][4+(j<<1)]==0xea) { if (pat->data[curRow][4+(j<<1)]==0xea) {
if (pat->data[curRow][5+(j<<1)]>0) { if (pat->data[curRow][5+(j<<1)]>0) {
doPrepareCut=false; doPrepareCut=false;