Add vibrato waveform import support for S3M, XM, MOD and IT

Fine print:
- OpenMPT hacks are not implemented here for MOD and XM for random waveform
- Retrigger/Continuous setting is not handled for MOD, XM and S3M
-- For S3M, I can't confirm if the setting even existed:
   I'm pretty sure it got cut out of Impulse Tracker.
- Your waveform may sound different here than in the original player

If tremolo and panbrello waveforms are implemented in Furnace, then their
corresponding conversions can be implemented. For now, though, they can't make
the cut since there is no corresponding effect to change those waveforms from
the default setting.
This commit is contained in:
KungFuFurby 2025-09-09 20:31:22 -04:00 committed by tildearrow
parent 3df67fb1b3
commit 0660e25f06
4 changed files with 71 additions and 0 deletions

View file

@ -1516,6 +1516,26 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
break;
case 'S': // special...
switch (effectVal[chan]>>4) {
case 0x3: // vibrato waveform
switch (effectVal[chan]&3) {
case 0x0: // sine
p->data[readRow][effectCol[chan]++]=0xe3;
p->data[readRow][effectCol[chan]++]=0x00;
break;
case 0x1: // ramp down
p->data[readRow][effectCol[chan]++]=0xe3;
p->data[readRow][effectCol[chan]++]=0x05;
break;
case 0x2: // square
p->data[readRow][effectCol[chan]++]=0xe3;
p->data[readRow][effectCol[chan]++]=0x06;
break;
case 0x3: // random
p->data[readRow][effectCol[chan]++]=0xe3;
p->data[readRow][effectCol[chan]++]=0x07;
break;
}
break;
case 0x8: // panning
p->data[readRow][effectCol[chan]++]=0x80;
p->data[readRow][effectCol[chan]++]=(effectVal[chan]&15)<<4;

View file

@ -356,6 +356,20 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
case 2: // single note slide down
writeFxCol(fxTyp-1+0xf1,fxVal);
break;
case 0x3: // vibrato waveform
switch (fxVal&3) {
case 0x0: // sine
writeFxCol(0xe3,0x00);
break;
case 0x1: // ramp down
writeFxCol(0xe3,0x05);
break;
case 0x2: // square
case 0x3:
writeFxCol(0xe3,0x06);
break;
}
break;
case 9: // retrigger
writeFxCol(0x0c,fxVal);
break;

View file

@ -1101,6 +1101,26 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
break;
case 'S': // special...
switch (effectVal>>4) {
case 0x3: // vibrato waveform
switch (effectVal&3) {
case 0x0: // sine
p->data[readRow][effectCol[chan]++]=0xe3;
p->data[readRow][effectCol[chan]++]=0x00;
break;
case 0x1: // ramp down
p->data[readRow][effectCol[chan]++]=0xe3;
p->data[readRow][effectCol[chan]++]=0x05;
break;
case 0x2: // square
p->data[readRow][effectCol[chan]++]=0xe3;
p->data[readRow][effectCol[chan]++]=0x06;
break;
case 0x3: // random
p->data[readRow][effectCol[chan]++]=0xe3;
p->data[readRow][effectCol[chan]++]=0x07;
break;
}
break;
case 0x8: // panning
p->data[readRow][effectCol[chan]++]=0x80;
p->data[readRow][effectCol[chan]++]=(effectVal&15)<<4;

View file

@ -1147,6 +1147,23 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
case 0xe: // special...
// TODO: implement the rest
switch (effectVal>>4) {
case 0x3: // vibrato waveform
switch (effectVal&3) {
case 0x0: // sine
p->data[j][effectCol[k]++]=0xe3;
p->data[j][effectCol[k]++]=0x00;
break;
case 0x1: // ramp down
p->data[j][effectCol[k]++]=0xe3;
p->data[j][effectCol[k]++]=0x05;
break;
case 0x2: // square
case 0x3:
p->data[j][effectCol[k]++]=0xe3;
p->data[j][effectCol[k]++]=0x06;
break;
}
break;
case 0x5: // fine tune
p->data[j][effectCol[k]++]=0xe5;
p->data[j][effectCol[k]++]=(effectVal&15)<<4;