implement relative pitch macro mode

This commit is contained in:
tildearrow 2022-04-28 01:31:16 -05:00
parent 77b4e57c58
commit d211170e86
70 changed files with 469 additions and 158 deletions

View File

@ -2,9 +2,6 @@
- panning macro - panning macro
- QSound? - QSound?
- pitch macro
- relative mode
- test
- piano/input pad - piano/input pad
- note input via piano - note input via piano
- input pad - input pad

View File

@ -457,4 +457,8 @@ class DivDispatch {
#define COLOR_NTSC (315000000.0/88.0) #define COLOR_NTSC (315000000.0/88.0)
#define COLOR_PAL (283.75*15625.0+25.0) #define COLOR_PAL (283.75*15625.0+25.0)
#define CLAMP_VAR(x,xMin,xMax) \
if (x<xMin) x=xMin; \
if (x>xMax) x=xMax;
#endif #endif

View File

@ -198,6 +198,12 @@ void DivPlatformAmiga::tick(bool sysTick) {
chan[i].ws.tick(); chan[i].ws.tick();
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].std.phaseReset.had) { if (chan[i].std.phaseReset.had) {
@ -207,7 +213,7 @@ void DivPlatformAmiga::tick(bool sysTick) {
} }
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,DIV_INS_AMIGA); //DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA);
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2);
if (chan[i].freq>4095) chan[i].freq=4095; if (chan[i].freq>4095) chan[i].freq=4095;
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].keyOn) { if (chan[i].keyOn) {
@ -266,7 +272,7 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (chan[c.chan].useWave) { if (chan[c.chan].useWave) {
chan[c.chan].ws.init(ins,chan[c.chan].audLen<<1,255,chan[c.chan].insChanged); chan[c.chan].ws.init(ins,chan[c.chan].audLen<<1,255,chan[c.chan].insChanged);
} }
@ -277,7 +283,7 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
chan[c.chan].sample=-1; chan[c.chan].sample=-1;
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -364,7 +370,7 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
} }
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -41,6 +41,10 @@ class DivPlatformAmiga: public DivDispatch {
signed char vol, outVol; signed char vol, outVol;
DivMacroInt std; DivMacroInt std;
DivWaveSynth ws; DivWaveSynth ws;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -275,6 +275,12 @@ void DivPlatformArcade::tick(bool sysTick) {
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
@ -420,7 +426,7 @@ void DivPlatformArcade::tick(bool sysTick) {
for (int i=0; i<8; i++) { for (int i=0; i<8; i++) {
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
chan[i].freq=chan[i].baseFreq+(chan[i].pitch>>1)-64+chan[i].std.pitch.val; chan[i].freq=chan[i].baseFreq+(chan[i].pitch>>1)-64+chan[i].pitch2;
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].freq>=(95<<6)) chan[i].freq=(95<<6)-1; if (chan[i].freq>=(95<<6)) chan[i].freq=(95<<6)-1;
immWrite(i+0x28,hScale(chan[i].freq>>6)); immWrite(i+0x28,hScale(chan[i].freq>>6));
@ -452,7 +458,7 @@ int DivPlatformArcade::dispatch(DivCommand c) {
chan[c.chan].state=ins->fm; chan[c.chan].state=ins->fm;
} }
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) { if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
} }

View File

@ -42,6 +42,10 @@ class DivPlatformArcade: public DivDispatch {
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, portaPause, furnacePCM, hardReset; bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, portaPause, furnacePCM, hardReset;
int vol, outVol; int vol, outVol;
unsigned char chVolL, chVolR; unsigned char chVolL, chVolR;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freqH(0), freqH(0),
freqL(0), freqL(0),

View File

@ -216,6 +216,12 @@ void DivPlatformAY8910::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].std.phaseReset.had) { if (chan[i].std.phaseReset.had) {
@ -239,7 +245,7 @@ void DivPlatformAY8910::tick(bool sysTick) {
if (!chan[i].std.ex3.will) chan[i].autoEnvNum=1; if (!chan[i].std.ex3.will) chan[i].autoEnvNum=1;
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2);
if (chan[i].freq>4095) chan[i].freq=4095; if (chan[i].freq>4095) chan[i].freq=4095;
if (chan[i].keyOn) { if (chan[i].keyOn) {
//rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(ins->gb.soundLen&63))); //rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(ins->gb.soundLen&63)));
@ -302,7 +308,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (isMuted[c.chan]) { if (isMuted[c.chan]) {
rWrite(0x08+c.chan,0); rWrite(0x08+c.chan,0);
} else if (intellivision && (chan[c.chan].psgMode&4)) { } else if (intellivision && (chan[c.chan].psgMode&4)) {
@ -315,7 +321,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -457,7 +463,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_AY)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AY));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -40,6 +40,10 @@ class DivPlatformAY8910: public DivDispatch {
int vol, outVol; int vol, outVol;
unsigned char pan; unsigned char pan;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), note(0), pitch(0), pitch2(0), ins(-1), psgMode(1), autoEnvNum(0), autoEnvDen(0), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), inPorta(false), vol(0), outVol(15), pan(3) {} Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), note(0), pitch(0), pitch2(0), ins(-1), psgMode(1), autoEnvNum(0), autoEnvDen(0), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), inPorta(false), vol(0), outVol(15), pan(3) {}
}; };
Channel chan[3]; Channel chan[3];

View File

@ -227,6 +227,12 @@ void DivPlatformAY8930::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].std.phaseReset.had) { if (chan[i].std.phaseReset.had) {
@ -261,7 +267,7 @@ void DivPlatformAY8930::tick(bool sysTick) {
immWrite(0x1a,ayNoiseOr); immWrite(0x1a,ayNoiseOr);
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2);
if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].freq>65535) chan[i].freq=65535;
if (chan[i].keyOn) { if (chan[i].keyOn) {
if (chan[i].insChanged) { if (chan[i].insChanged) {
@ -326,7 +332,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (isMuted[c.chan]) { if (isMuted[c.chan]) {
rWrite(0x08+c.chan,0); rWrite(0x08+c.chan,0);
} else { } else {
@ -337,7 +343,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -482,7 +488,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_AY8930)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AY8930));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -36,6 +36,10 @@ class DivPlatformAY8930: public DivDispatch {
int vol, outVol; int vol, outVol;
unsigned char pan; unsigned char pan;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), note(0), pitch(0), pitch2(0), ins(-1), psgMode(1), autoEnvNum(0), autoEnvDen(0), duty(4), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), inPorta(false), vol(0), outVol(31), pan(3) {} Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), note(0), pitch(0), pitch2(0), ins(-1), psgMode(1), autoEnvNum(0), autoEnvDen(0), duty(4), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), inPorta(false), vol(0), outVol(31), pan(3) {}
}; };
Channel chan[3]; Channel chan[3];

View File

@ -111,6 +111,12 @@ void DivPlatformBubSysWSG::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].active) { if (chan[i].active) {
@ -120,7 +126,7 @@ void DivPlatformBubSysWSG::tick(bool sysTick) {
} }
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,DIV_INS_SCC); //DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SCC);
chan[i].freq=0x1000-parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val; chan[i].freq=0x1000-parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].pitch2;
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].freq>4095) chan[i].freq=4095; if (chan[i].freq>4095) chan[i].freq=4095;
k005289->load(i,chan[i].freq); k005289->load(i,chan[i].freq);
@ -151,7 +157,7 @@ int DivPlatformBubSysWSG::dispatch(DivCommand c) {
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
rWrite(2+c.chan,(chan[c.chan].wave<<5)|chan[c.chan].vol); rWrite(2+c.chan,(chan[c.chan].wave<<5)|chan[c.chan].vol);
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (chan[c.chan].wave<0) { if (chan[c.chan].wave<0) {
chan[c.chan].wave=0; chan[c.chan].wave=0;
chan[c.chan].ws.changeWave1(chan[c.chan].wave); chan[c.chan].ws.changeWave1(chan[c.chan].wave);
@ -163,7 +169,7 @@ int DivPlatformBubSysWSG::dispatch(DivCommand c) {
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -228,7 +234,7 @@ int DivPlatformBubSysWSG::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_SCC)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SCC));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -34,6 +34,10 @@ class DivPlatformBubSysWSG: public DivDispatch {
signed char waveROM[32] = {0}; // 4 bit PROM per channel on bubble system signed char waveROM[32] = {0}; // 4 bit PROM per channel on bubble system
DivMacroInt std; DivMacroInt std;
DivWaveSynth ws; DivWaveSynth ws;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -183,6 +183,12 @@ void DivPlatformC64::tick(bool sysTick) {
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active)); rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active));
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].std.ex1.had) { if (chan[i].std.ex1.had) {
@ -205,7 +211,7 @@ void DivPlatformC64::tick(bool sysTick) {
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8,chan[i].pitch2);
if (chan[i].freq>0xffff) chan[i].freq=0xffff; if (chan[i].freq>0xffff) chan[i].freq=0xffff;
if (chan[i].keyOn) { if (chan[i].keyOn) {
rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay)); rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
@ -264,14 +270,14 @@ int DivPlatformC64::dispatch(DivCommand c) {
if (chan[c.chan].insChanged) { if (chan[c.chan].insChanged) {
chan[c.chan].insChanged=false; chan[c.chan].insChanged=false;
} }
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
break; break;
} }
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].keyOn=false; chan[c.chan].keyOn=false;
//chan[c.chan].std.init(NULL); //chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
chan[c.chan].active=false; chan[c.chan].active=false;
@ -352,7 +358,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta || !chan[c.chan].inPorta) { if (parent->song.resetMacroOnPorta || !chan[c.chan].inPorta) {
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_C64)); chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_C64));
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
} }
} }

View File

@ -33,6 +33,10 @@ class DivPlatformC64: public DivDispatch {
bool resetMask, resetFilter, resetDuty, ring, sync, test; bool resetMask, resetFilter, resetDuty, ring, sync, test;
signed char vol, outVol; signed char vol, outVol;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -146,6 +146,12 @@ void DivPlatformFDS::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].active) { if (chan[i].active) {
@ -177,7 +183,7 @@ void DivPlatformFDS::tick(bool sysTick) {
} }
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2);
if (chan[i].freq>4095) chan[i].freq=4095; if (chan[i].freq>4095) chan[i].freq=4095;
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].keyOn) { if (chan[i].keyOn) {
@ -241,7 +247,7 @@ int DivPlatformFDS::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (chan[c.chan].wave<0) { if (chan[c.chan].wave<0) {
chan[c.chan].wave=0; chan[c.chan].wave=0;
ws.changeWave1(chan[c.chan].wave); ws.changeWave1(chan[c.chan].wave);
@ -254,7 +260,7 @@ int DivPlatformFDS::dispatch(DivCommand c) {
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -358,7 +364,7 @@ int DivPlatformFDS::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_FDS)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FDS));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -32,6 +32,10 @@ class DivPlatformFDS: public DivDispatch {
signed char vol, outVol, wave; signed char vol, outVol, wave;
signed char modTable[32]; signed char modTable[32];
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -198,6 +198,12 @@ void DivPlatformGB::tick(bool sysTick) {
rWrite(0x25,procMute()); rWrite(0x25,procMute());
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].std.phaseReset.had) { if (chan[i].std.phaseReset.had) {
@ -227,7 +233,7 @@ void DivPlatformGB::tick(bool sysTick) {
if (ntPos>255) ntPos=255; if (ntPos>255) ntPos=255;
chan[i].freq=noiseTable[ntPos]; chan[i].freq=noiseTable[ntPos];
} else { } else {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2);
if (chan[i].freq>2047) chan[i].freq=2047; if (chan[i].freq>2047) chan[i].freq=2047;
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
} }
@ -281,7 +287,7 @@ int DivPlatformGB::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (c.chan==2) { if (c.chan==2) {
if (chan[c.chan].wave<0) { if (chan[c.chan].wave<0) {
chan[c.chan].wave=0; chan[c.chan].wave=0;
@ -295,7 +301,7 @@ int DivPlatformGB::dispatch(DivCommand c) {
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -379,7 +385,7 @@ int DivPlatformGB::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_GB)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_GB));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -32,6 +32,10 @@ class DivPlatformGB: public DivDispatch {
bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta; bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta;
signed char vol, outVol, wave; signed char vol, outVol, wave;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -280,6 +280,12 @@ void DivPlatformGenesis::tick(bool sysTick) {
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
@ -410,7 +416,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
for (int i=0; i<6; i++) { for (int i=0; i<6; i++) {
if (i==2 && extMode) continue; if (i==2 && extMode) continue;
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false,4,chan[i].std.pitch.val); int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false,4,chan[i].pitch2);
int block=(chan[i].baseFreq&0xf800)>>11; int block=(chan[i].baseFreq&0xf800)>>11;
if (fNum<0) fNum=0; if (fNum<0) fNum=0;
if (fNum>2047) { if (fNum>2047) {
@ -434,7 +440,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
off=(double)s->centerRate/8363.0; off=(double)s->centerRate/8363.0;
} }
} }
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,4)+chan[i].std.pitch.val; chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,4)+chan[i].pitch2;
dacRate=chan[i].freq*off; dacRate=chan[i].freq*off;
if (dacRate<1) dacRate=1; if (dacRate<1) dacRate=1;
if (dumpWrites) addWrite(0xffff0001,dacRate); if (dumpWrites) addWrite(0xffff0001,dacRate);
@ -524,7 +530,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
chan[c.chan].state=ins->fm; chan[c.chan].state=ins->fm;
} }
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) { if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
} }

View File

@ -41,6 +41,10 @@ class DivPlatformGenesis: public DivDispatch {
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta, hardReset; bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta, hardReset;
int vol, outVol; int vol, outVol;
unsigned char pan; unsigned char pan;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freqH(0), freqH(0),
freqL(0), freqL(0),

View File

@ -307,7 +307,7 @@ void DivPlatformGenesisExt::tick(bool sysTick) {
unsigned char writeMask=2; unsigned char writeMask=2;
if (extMode) for (int i=0; i<4; i++) { if (extMode) for (int i=0; i<4; i++) {
if (opChan[i].freqChanged) { if (opChan[i].freqChanged) {
int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4,opChan[i].std.pitch.val); int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4,opChan[i].pitch2);
int block=(opChan[i].baseFreq&0xf800)>>11; int block=(opChan[i].baseFreq&0xf800)>>11;
if (fNum<0) fNum=0; if (fNum<0) fNum=0;
if (fNum>2047) { if (fNum>2047) {

View File

@ -186,6 +186,12 @@ void DivPlatformLynx::tick(bool sysTick) {
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
@ -195,7 +201,7 @@ void DivPlatformLynx::tick(bool sysTick) {
WRITE_OTHER(i, ((chan[i].lfsr&0xf00)>>4)); WRITE_OTHER(i, ((chan[i].lfsr&0xf00)>>4));
chan[i].lfsr=-1; chan[i].lfsr=-1;
} }
chan[i].fd=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); chan[i].fd=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2);
if (chan[i].std.duty.had) { if (chan[i].std.duty.had) {
chan[i].duty=chan[i].std.duty.val; chan[i].duty=chan[i].std.duty.val;
WRITE_FEEDBACK(i, chan[i].duty.feedback); WRITE_FEEDBACK(i, chan[i].duty.feedback);
@ -224,12 +230,12 @@ int DivPlatformLynx::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
WRITE_VOLUME(c.chan,(isMuted[c.chan]?0:(chan[c.chan].vol&127))); WRITE_VOLUME(c.chan,(isMuted[c.chan]?0:(chan[c.chan].vol&127)));
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY)); chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY));
break; break;
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].active=false; chan[c.chan].active=false;
WRITE_VOLUME(c.chan, 0); WRITE_VOLUME(c.chan, 0);
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_LYNX_LFSR_LOAD: case DIV_CMD_LYNX_LFSR_LOAD:
chan[c.chan].freqChanged=true; chan[c.chan].freqChanged=true;
@ -241,7 +247,7 @@ int DivPlatformLynx::dispatch(DivCommand c) {
break; break;
case DIV_CMD_INSTRUMENT: case DIV_CMD_INSTRUMENT:
chan[c.chan].ins=c.value; chan[c.chan].ins=c.value;
//chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY)); //chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY));
break; break;
case DIV_CMD_VOLUME: case DIV_CMD_VOLUME:
if (chan[c.chan].vol!=c.value) { if (chan[c.chan].vol!=c.value) {
@ -297,7 +303,7 @@ int DivPlatformLynx::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -48,6 +48,10 @@ class DivPlatformLynx: public DivDispatch {
unsigned char pan; unsigned char pan;
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta; bool active, insChanged, freqChanged, keyOn, keyOff, inPorta;
signed char vol, outVol; signed char vol, outVol;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
std(), std(),
fd(0), fd(0),

View File

@ -124,6 +124,12 @@ void DivPlatformMMC5::tick(bool sysTick) {
rWrite(0x5000+i*4,0x30|chan[i].outVol|((chan[i].duty&3)<<6)); rWrite(0x5000+i*4,0x30|chan[i].outVol|((chan[i].duty&3)<<6));
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].std.phaseReset.had) { if (chan[i].std.phaseReset.had) {
@ -133,7 +139,7 @@ void DivPlatformMMC5::tick(bool sysTick) {
} }
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1; chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2)-1;
if (chan[i].freq>2047) chan[i].freq=2047; if (chan[i].freq>2047) chan[i].freq=2047;
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].keyOn) { if (chan[i].keyOn) {
@ -227,7 +233,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
rWrite(0x5000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6)); rWrite(0x5000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6));
break; break;
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
@ -237,7 +243,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
} }
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -305,7 +311,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -30,6 +30,10 @@ class DivPlatformMMC5: public DivDispatch {
bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, furnaceDac; bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, furnaceDac;
signed char vol, outVol, wave; signed char vol, outVol, wave;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -262,6 +262,12 @@ void DivPlatformN163::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].std.ex1.had) { if (chan[i].std.ex1.had) {
@ -347,7 +353,7 @@ void DivPlatformN163::tick(bool sysTick) {
chan[i].waveUpdated=false; chan[i].waveUpdated=false;
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq((((chan[i].baseFreq*chan[i].waveLen)*(chanMax+1))/16),chan[i].pitch,false,0,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq((((chan[i].baseFreq*chan[i].waveLen)*(chanMax+1))/16),chan[i].pitch,false,0,chan[i].pitch2);
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].freq>0x3ffff) chan[i].freq=0x3ffff; if (chan[i].freq>0x3ffff) chan[i].freq=0x3ffff;
if (chan[i].keyOn) { if (chan[i].keyOn) {
@ -398,7 +404,7 @@ int DivPlatformN163::dispatch(DivCommand c) {
if (!isMuted[c.chan]) { if (!isMuted[c.chan]) {
chan[c.chan].volumeChanged=true; chan[c.chan].volumeChanged=true;
} }
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
chan[c.chan].ws.init(ins,chan[c.chan].waveLen,15,chan[c.chan].insChanged); chan[c.chan].ws.init(ins,chan[c.chan].waveLen,15,chan[c.chan].insChanged);
break; break;
} }
@ -406,7 +412,7 @@ int DivPlatformN163::dispatch(DivCommand c) {
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].keyOn=false; chan[c.chan].keyOn=false;
//chan[c.chan].std.init(NULL); //chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
chan[c.chan].active=false; chan[c.chan].active=false;
@ -546,7 +552,7 @@ int DivPlatformN163::dispatch(DivCommand c) {
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) { if (parent->song.resetMacroOnPorta) {
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_N163)); chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_N163));
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
} }
} }

View File

@ -37,6 +37,10 @@ class DivPlatformN163: public DivDispatch {
signed char vol, outVol, resVol; signed char vol, outVol, resVol;
DivMacroInt std; DivMacroInt std;
DivWaveSynth ws; DivWaveSynth ws;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -196,6 +196,12 @@ void DivPlatformNES::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].sweepChanged) { if (chan[i].sweepChanged) {
@ -217,7 +223,7 @@ void DivPlatformNES::tick(bool sysTick) {
if (ntPos>252) ntPos=252; if (ntPos>252) ntPos=252;
chan[i].freq=(parent->song.properNoiseLayout)?(15-(chan[i].baseFreq&15)):(noiseTable[ntPos]); chan[i].freq=(parent->song.properNoiseLayout)?(15-(chan[i].baseFreq&15)):(noiseTable[ntPos]);
} else { } else {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1; chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2)-1;
if (chan[i].freq>2047) chan[i].freq=2047; if (chan[i].freq>2047) chan[i].freq=2047;
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
} }
@ -325,7 +331,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
if (c.chan==2) { if (c.chan==2) {
rWrite(0x4000+c.chan*4,0xff); rWrite(0x4000+c.chan*4,0xff);
} else { } else {
@ -339,7 +345,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
} }
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -428,7 +434,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -30,6 +30,10 @@ class DivPlatformNES: public DivDispatch {
bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, furnaceDac; bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, furnaceDac;
signed char vol, outVol, wave; signed char vol, outVol, wave;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -274,6 +274,12 @@ void DivPlatformOPL::tick(bool sysTick) {
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
@ -417,9 +423,9 @@ void DivPlatformOPL::tick(bool sysTick) {
bool updateDrums=false; bool updateDrums=false;
for (int i=0; i<totalChans; i++) { for (int i=0; i<totalChans; i++) {
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].pitch2);
if (chan[i].freq>131071) chan[i].freq=131071; if (chan[i].freq>131071) chan[i].freq=131071;
int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val; int freqt=toFreq(chan[i].freq)+chan[i].pitch2;
chan[i].freqH=freqt>>8; chan[i].freqH=freqt>>8;
chan[i].freqL=freqt&0xff; chan[i].freqL=freqt&0xff;
immWrite(chanMap[i]+ADDR_FREQ,chan[i].freqL); immWrite(chanMap[i]+ADDR_FREQ,chan[i].freqL);
@ -541,7 +547,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
chan[c.chan].state=ins->fm; chan[c.chan].state=ins->fm;
} }
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) { if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
} }
@ -549,7 +555,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
chan[c.chan].fourOp=(ops==4); chan[c.chan].fourOp=(ops==4);
if (chan[c.chan].fourOp) { if (chan[c.chan].fourOp) {
chan[c.chan+1].std.init(NULL); chan[c.chan+1].macroInit(NULL);
} }
update4OpMask=true; update4OpMask=true;
for (int i=0; i<ops; i++) { for (int i=0; i<ops; i++) {

View File

@ -34,6 +34,10 @@ class DivPlatformOPL: public DivDispatch {
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta, fourOp; bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta, fourOp;
int vol, outVol; int vol, outVol;
unsigned char pan; unsigned char pan;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freqH(0), freqH(0),
freqL(0), freqL(0),

View File

@ -146,6 +146,12 @@ void DivPlatformOPLL::tick(bool sysTick) {
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
@ -261,9 +267,9 @@ void DivPlatformOPLL::tick(bool sysTick) {
for (int i=0; i<11; i++) { for (int i=0; i<11; i++) {
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].pitch2);
if (chan[i].freq>262143) chan[i].freq=262143; if (chan[i].freq>262143) chan[i].freq=262143;
int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val; int freqt=toFreq(chan[i].freq)+chan[i].pitch2;
chan[i].freqL=freqt&0xff; chan[i].freqL=freqt&0xff;
if (i>=6 && properDrums) { if (i>=6 && properDrums) {
immWrite(0x10+drumSlot[i],freqt&0xff); immWrite(0x10+drumSlot[i],freqt&0xff);
@ -370,7 +376,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
chan[c.chan].state=ins->fm; chan[c.chan].state=ins->fm;
} }
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) { if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
} }

View File

@ -37,6 +37,10 @@ class DivPlatformOPLL: public DivDispatch {
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta; bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta;
int vol, outVol; int vol, outVol;
unsigned char pan; unsigned char pan;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freqH(0), freqH(0),
freqL(0), freqL(0),

View File

@ -208,6 +208,12 @@ void DivPlatformPCE::tick(bool sysTick) {
chWrite(i,0x05,isMuted[i]?0:chan[i].pan); chWrite(i,0x05,isMuted[i]?0:chan[i].pan);
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].active) { if (chan[i].active) {
@ -217,7 +223,7 @@ void DivPlatformPCE::tick(bool sysTick) {
} }
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,DIV_INS_PCE); //DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_PCE);
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2);
if (chan[i].furnaceDac) { if (chan[i].furnaceDac) {
double off=1.0; double off=1.0;
if (chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) { if (chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) {
@ -279,7 +285,7 @@ int DivPlatformPCE::dispatch(DivCommand c) {
chan[c.chan].note=c.value; chan[c.chan].note=c.value;
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
//chan[c.chan].keyOn=true; //chan[c.chan].keyOn=true;
chan[c.chan].furnaceDac=true; chan[c.chan].furnaceDac=true;
} else { } else {
@ -316,7 +322,7 @@ int DivPlatformPCE::dispatch(DivCommand c) {
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chWrite(c.chan,0x04,0x80|chan[c.chan].vol); chWrite(c.chan,0x04,0x80|chan[c.chan].vol);
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (chan[c.chan].wave<0) { if (chan[c.chan].wave<0) {
chan[c.chan].wave=0; chan[c.chan].wave=0;
chan[c.chan].ws.changeWave1(chan[c.chan].wave); chan[c.chan].ws.changeWave1(chan[c.chan].wave);
@ -331,7 +337,7 @@ int DivPlatformPCE::dispatch(DivCommand c) {
chan[c.chan].pcm=false; chan[c.chan].pcm=false;
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -429,7 +435,7 @@ int DivPlatformPCE::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_PCE)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PCE));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -37,6 +37,10 @@ class DivPlatformPCE: public DivDispatch {
signed char vol, outVol, wave; signed char vol, outVol, wave;
DivMacroInt std; DivMacroInt std;
DivWaveSynth ws; DivWaveSynth ws;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -190,10 +190,16 @@ void DivPlatformPCSpeaker::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1; chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2)-1;
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].freq>65535) chan[i].freq=65535;
if (chan[i].keyOn) { if (chan[i].keyOn) {
@ -220,12 +226,12 @@ int DivPlatformPCSpeaker::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER)); chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER));
break; break;
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -285,7 +291,7 @@ int DivPlatformPCSpeaker::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -30,6 +30,10 @@ class DivPlatformPCSpeaker: public DivDispatch {
bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, furnaceDac; bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, furnaceDac;
signed char vol, outVol, wave; signed char vol, outVol, wave;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -116,7 +116,7 @@ void DivPlatformPET::tick(bool sysTick) {
chan.freqChanged=true; chan.freqChanged=true;
} }
if (chan.freqChanged || chan.keyOn || chan.keyOff) { if (chan.freqChanged || chan.keyOn || chan.keyOff) {
chan.freq=parent->calcFreq(chan.baseFreq,chan.pitch,true,0,chan.std.pitch.val); chan.freq=parent->calcFreq(chan.baseFreq,chan.pitch,true,0,chan.pitch2);
if (chan.freq>257) chan.freq=257; if (chan.freq>257) chan.freq=257;
if (chan.freq<2) chan.freq=2; if (chan.freq<2) chan.freq=2;
rWrite(8,chan.freq-2); rWrite(8,chan.freq-2);
@ -146,13 +146,13 @@ int DivPlatformPET::dispatch(DivCommand c) {
} }
chan.active=true; chan.active=true;
chan.keyOn=true; chan.keyOn=true;
chan.std.init(ins); chan.macroInit(ins);
break; break;
} }
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan.active=false; chan.active=false;
chan.keyOff=true; chan.keyOff=true;
chan.std.init(NULL); chan.macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -213,7 +213,7 @@ int DivPlatformPET::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan.active && c.value2) { if (chan.active && c.value2) {
if (parent->song.resetMacroOnPorta) chan.std.init(parent->getIns(chan.ins,DIV_INS_PET)); if (parent->song.resetMacroOnPorta) chan.macroInit(parent->getIns(chan.ins,DIV_INS_PET));
} }
chan.inPorta=c.value; chan.inPorta=c.value;
break; break;

View File

@ -32,6 +32,10 @@ class DivPlatformPET: public DivDispatch {
int cnt; int cnt;
short out; short out;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -327,11 +327,17 @@ void DivPlatformQSound::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
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,DIV_INS_AMIGA); //DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA);
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2);
if (chan[i].freq>0xffff) chan[i].freq=0xffff; if (chan[i].freq>0xffff) chan[i].freq=0xffff;
if (chan[i].keyOn) { if (chan[i].keyOn) {
rWrite(q1_reg_map[Q1V_BANK][i], qsound_bank); rWrite(q1_reg_map[Q1V_BANK][i], qsound_bank);
@ -386,14 +392,14 @@ int DivPlatformQSound::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
break; break;
} }
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].sample=-1; chan[c.chan].sample=-1;
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -487,7 +493,7 @@ int DivPlatformQSound::dispatch(DivCommand c) {
} }
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -36,6 +36,10 @@ class DivPlatformQSound: public DivDispatch {
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, useWave; bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, useWave;
int vol, outVol; int vol, outVol;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -187,6 +187,12 @@ void DivPlatformSAA1099::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].std.ex1.had) { if (chan[i].std.ex1.had) {
@ -194,7 +200,7 @@ void DivPlatformSAA1099::tick(bool sysTick) {
rWrite(0x18+(i/3),saaEnv[i/3]); rWrite(0x18+(i/3),saaEnv[i/3]);
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2);
if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].freq>65535) chan[i].freq=65535;
if (chan[i].freq>=32768) { if (chan[i].freq>=32768) {
chan[i].freqH=7; chan[i].freqH=7;
@ -257,7 +263,7 @@ int DivPlatformSAA1099::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (isMuted[c.chan]) { if (isMuted[c.chan]) {
rWrite(c.chan,0); rWrite(c.chan,0);
} else { } else {
@ -268,7 +274,7 @@ int DivPlatformSAA1099::dispatch(DivCommand c) {
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -356,7 +362,7 @@ int DivPlatformSAA1099::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_SAA1099)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SAA1099));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -42,6 +42,10 @@ class DivPlatformSAA1099: public DivDispatch {
int vol, outVol; int vol, outVol;
unsigned char pan; unsigned char pan;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), psgMode(1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), inPorta(false), vol(0), outVol(15), pan(255) {} Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), psgMode(1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), inPorta(false), vol(0), outVol(15), pan(255) {}
}; };
Channel chan[6]; Channel chan[6];

View File

@ -116,6 +116,12 @@ void DivPlatformSegaPCM::tick(bool sysTick) {
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
/*if (chan[i].keyOn || chan[i].keyOff) { /*if (chan[i].keyOn || chan[i].keyOff) {
@ -132,7 +138,7 @@ void DivPlatformSegaPCM::tick(bool sysTick) {
DivSample* s=parent->getSample(chan[i].pcm.sample); DivSample* s=parent->getSample(chan[i].pcm.sample);
off=(double)s->centerRate/8363.0; off=(double)s->centerRate/8363.0;
} }
chan[i].pcm.freq=MIN(255,(15625+(off*parent->song.tuning*pow(2.0,double(chan[i].freq+256)/(64.0*12.0)))*255)/31250)+chan[i].std.pitch.val; chan[i].pcm.freq=MIN(255,(15625+(off*parent->song.tuning*pow(2.0,double(chan[i].freq+256)/(64.0*12.0)))*255)/31250)+chan[i].pitch2;
if (dumpWrites) { if (dumpWrites) {
addWrite(0x10007+(i<<3),chan[i].pcm.freq); addWrite(0x10007+(i<<3),chan[i].pcm.freq);
} }
@ -158,7 +164,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
if (dumpWrites) { if (dumpWrites) {
addWrite(0x10086+(c.chan<<3),3); addWrite(0x10086+(c.chan<<3),3);
} }
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
} }
chan[c.chan].pcm.pos=0; chan[c.chan].pcm.pos=0;
@ -168,7 +174,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
chan[c.chan].freqChanged=true; chan[c.chan].freqChanged=true;
} }
chan[c.chan].furnacePCM=true; chan[c.chan].furnacePCM=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (dumpWrites) { // Sega PCM writes if (dumpWrites) { // Sega PCM writes
DivSample* s=parent->getSample(chan[c.chan].pcm.sample); DivSample* s=parent->getSample(chan[c.chan].pcm.sample);
addWrite(0x10086+(c.chan<<3),3+((s->offSegaPCM>>16)<<3)); addWrite(0x10086+(c.chan<<3),3+((s->offSegaPCM>>16)<<3));
@ -185,7 +191,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
} }
} }
} else { } else {
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
if (c.value!=DIV_NOTE_NULL) { if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value; chan[c.chan].note=c.value;
} }
@ -227,7 +233,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].keyOn=false; chan[c.chan].keyOn=false;
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;

View File

@ -42,6 +42,10 @@ class DivPlatformSegaPCM: public DivDispatch {
unsigned char freq; unsigned char freq;
PCMChannel(): sample(-1), pos(0), len(0), freq(0) {} PCMChannel(): sample(-1), pos(0), len(0), freq(0) {}
} pcm; } pcm;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), inPorta(false), portaPause(false), furnacePCM(false), vol(0), outVol(0), chVolL(127), chVolR(127) {} Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), inPorta(false), portaPause(false), furnacePCM(false), vol(0), outVol(0), chVolL(127), chVolR(127) {}
}; };
Channel chan[16]; Channel chan[16];

View File

@ -101,12 +101,18 @@ void DivPlatformSMS::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
} }
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2);
if (chan[i].freq>1023) chan[i].freq=1023; if (chan[i].freq>1023) chan[i].freq=1023;
if (chan[i].freq<8) chan[i].freq=1; if (chan[i].freq<8) chan[i].freq=1;
//if (chan[i].actualNote>0x5d) chan[i].freq=0x01; //if (chan[i].actualNote>0x5d) chan[i].freq=0x01;
@ -121,7 +127,7 @@ void DivPlatformSMS::tick(bool sysTick) {
} }
} }
if (chan[3].freqChanged || updateSNMode) { if (chan[3].freqChanged || updateSNMode) {
chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true,0,chan[3].std.pitch.val); chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true,0,chan[3].pitch2);
if (chan[3].freq>1023) chan[3].freq=1023; if (chan[3].freq>1023) chan[3].freq=1023;
if (chan[3].actualNote>0x5d) chan[3].freq=0x01; if (chan[3].actualNote>0x5d) chan[3].freq=0x01;
if (snNoiseMode&2) { // take period from channel 3 if (snNoiseMode&2) { // take period from channel 3
@ -177,12 +183,12 @@ int DivPlatformSMS::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
rWrite(0x90|c.chan<<5|(isMuted[c.chan]?15:(15-(chan[c.chan].vol&15)))); rWrite(0x90|c.chan<<5|(isMuted[c.chan]?15:(15-(chan[c.chan].vol&15))));
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
break; break;
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].active=false; chan[c.chan].active=false;
rWrite(0x9f|c.chan<<5); rWrite(0x9f|c.chan<<5);
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -190,7 +196,7 @@ int DivPlatformSMS::dispatch(DivCommand c) {
break; break;
case DIV_CMD_INSTRUMENT: case DIV_CMD_INSTRUMENT:
chan[c.chan].ins=c.value; chan[c.chan].ins=c.value;
//chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); //chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
break; break;
case DIV_CMD_VOLUME: case DIV_CMD_VOLUME:
if (chan[c.chan].vol!=c.value) { if (chan[c.chan].vol!=c.value) {
@ -246,7 +252,7 @@ int DivPlatformSMS::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -30,6 +30,10 @@ class DivPlatformSMS: public DivDispatch {
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta; bool active, insChanged, freqChanged, keyOn, keyOff, inPorta;
signed char vol, outVol; signed char vol, outVol;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -151,6 +151,12 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
chWrite(i,0x03,chan[i].pan); chWrite(i,0x03,chan[i].pan);
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].std.ex1.had) { if (chan[i].std.ex1.had) {
@ -168,7 +174,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
} }
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,DIV_INS_SU); //DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2);
chWrite(i,0x00,chan[i].freq&0xff); chWrite(i,0x00,chan[i].freq&0xff);
chWrite(i,0x01,chan[i].freq>>8); chWrite(i,0x01,chan[i].freq>>8);
if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].freq>65535) chan[i].freq=65535;
@ -198,14 +204,14 @@ int DivPlatformSoundUnit::dispatch(DivCommand c) {
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chWrite(c.chan,0x02,chan[c.chan].vol); chWrite(c.chan,0x02,chan[c.chan].vol);
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
chan[c.chan].insChanged=false; chan[c.chan].insChanged=false;
break; break;
} }
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -275,7 +281,7 @@ int DivPlatformSoundUnit::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_SU)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SU));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -35,6 +35,10 @@ class DivPlatformSoundUnit: public DivDispatch {
bool pcmLoop, timerSync, freqSweep, volSweep, cutSweep; bool pcmLoop, timerSync, freqSweep, volSweep, cutSweep;
signed char vol, outVol, wave; signed char vol, outVol, wave;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -185,6 +185,12 @@ void DivPlatformSwan::tick(bool sysTick) {
calcAndWriteOutVol(i,chan[i].std.vol.will?chan[i].std.vol.val:15); calcAndWriteOutVol(i,chan[i].std.vol.will?chan[i].std.vol.val:15);
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].active) { if (chan[i].active) {
@ -194,7 +200,7 @@ void DivPlatformSwan::tick(bool sysTick) {
} }
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2);
if (i==1 && pcm && furnaceDac) { if (i==1 && pcm && furnaceDac) {
double off=1.0; double off=1.0;
if (dacSample>=0 && dacSample<parent->song.sampleLen) { if (dacSample>=0 && dacSample<parent->song.sampleLen) {
@ -271,7 +277,7 @@ int DivPlatformSwan::dispatch(DivCommand c) {
} }
chan[1].active=true; chan[1].active=true;
chan[1].keyOn=true; chan[1].keyOn=true;
chan[1].std.init(ins); chan[1].macroInit(ins);
furnaceDac=true; furnaceDac=true;
} else { } else {
if (c.value!=DIV_NOTE_NULL) { if (c.value!=DIV_NOTE_NULL) {
@ -303,7 +309,7 @@ int DivPlatformSwan::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (chan[c.chan].wave<0) { if (chan[c.chan].wave<0) {
chan[c.chan].wave=0; chan[c.chan].wave=0;
chan[c.chan].ws.changeWave1(chan[c.chan].wave); chan[c.chan].ws.changeWave1(chan[c.chan].wave);
@ -320,7 +326,7 @@ int DivPlatformSwan::dispatch(DivCommand c) {
} }
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -417,7 +423,7 @@ int DivPlatformSwan::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_SWAN)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_SWAN));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -34,6 +34,10 @@ class DivPlatformSwan: public DivDispatch {
int vol, outVol, wave; int vol, outVol, wave;
DivMacroInt std; DivMacroInt std;
DivWaveSynth ws; DivWaveSynth ws;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -117,6 +117,12 @@ void DivPlatformTIA::tick(bool sysTick) {
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
@ -127,14 +133,14 @@ void DivPlatformTIA::tick(bool sysTick) {
} }
chan[i].insChanged=false; chan[i].insChanged=false;
} }
chan[i].freq=dealWithFreq(chan[i].shape,chan[i].baseFreq,chan[i].pitch)+chan[i].std.pitch.val; chan[i].freq=dealWithFreq(chan[i].shape,chan[i].baseFreq,chan[i].pitch)+chan[i].pitch2;
if ((chan[i].shape==4 || chan[i].shape==5) && !(chan[i].baseFreq&0x80000000 && ((chan[i].baseFreq&0x7fffffff)<32))) { if ((chan[i].shape==4 || chan[i].shape==5) && !(chan[i].baseFreq&0x80000000 && ((chan[i].baseFreq&0x7fffffff)<32))) {
if (chan[i].baseFreq<39*256) { if (chan[i].baseFreq<39*256) {
rWrite(0x15+i,6); rWrite(0x15+i,6);
chan[i].freq=dealWithFreq(6,chan[i].baseFreq,chan[i].pitch)+chan[i].std.pitch.val; chan[i].freq=dealWithFreq(6,chan[i].baseFreq,chan[i].pitch)+chan[i].pitch2;
} else if (chan[i].baseFreq<59*256) { } else if (chan[i].baseFreq<59*256) {
rWrite(0x15+i,12); rWrite(0x15+i,12);
chan[i].freq=dealWithFreq(12,chan[i].baseFreq,chan[i].pitch)+chan[i].std.pitch.val; chan[i].freq=dealWithFreq(12,chan[i].baseFreq,chan[i].pitch)+chan[i].pitch2;
} else { } else {
rWrite(0x15+i,chan[i].shape); rWrite(0x15+i,chan[i].shape);
} }
@ -163,7 +169,7 @@ int DivPlatformTIA::dispatch(DivCommand c) {
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
rWrite(0x15+c.chan,chan[c.chan].shape); rWrite(0x15+c.chan,chan[c.chan].shape);
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (isMuted[c.chan]) { if (isMuted[c.chan]) {
rWrite(0x19+c.chan,0); rWrite(0x19+c.chan,0);
} else { } else {
@ -174,7 +180,7 @@ int DivPlatformTIA::dispatch(DivCommand c) {
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -248,7 +254,7 @@ int DivPlatformTIA::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_TIA)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_TIA));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -33,6 +33,10 @@ class DivPlatformTIA: public DivDispatch {
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta; bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta;
int vol, outVol; int vol, outVol;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), shape(4), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), inPorta(false), vol(0), outVol(15) {} Channel(): freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), shape(4), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), inPorta(false), vol(0), outVol(15) {}
}; };
Channel chan[2]; Channel chan[2];

View File

@ -229,6 +229,12 @@ void DivPlatformTX81Z::tick(bool sysTick) {
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
@ -391,7 +397,7 @@ void DivPlatformTX81Z::tick(bool sysTick) {
for (int i=0; i<8; i++) { for (int i=0; i<8; i++) {
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
chan[i].freq=chan[i].baseFreq+(chan[i].pitch>>1)-64+chan[i].std.pitch.val; chan[i].freq=chan[i].baseFreq+(chan[i].pitch>>1)-64+chan[i].pitch2;
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].freq>=(95<<6)) chan[i].freq=(95<<6)-1; if (chan[i].freq>=(95<<6)) chan[i].freq=(95<<6)-1;
immWrite(i+0x28,hScale(chan[i].freq>>6)); immWrite(i+0x28,hScale(chan[i].freq>>6));
@ -430,7 +436,7 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
chan[c.chan].state=ins->fm; chan[c.chan].state=ins->fm;
} }
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) { if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
} }

View File

@ -40,6 +40,10 @@ class DivPlatformTX81Z: public DivDispatch {
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, portaPause, furnacePCM, hardReset; bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, portaPause, furnacePCM, hardReset;
int vol, outVol; int vol, outVol;
unsigned char chVolL, chVolR; unsigned char chVolL, chVolR;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freqH(0), freqH(0),
freqL(0), freqL(0),

View File

@ -191,10 +191,16 @@ void DivPlatformVERA::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8,chan[i].pitch2);
if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].freq>65535) chan[i].freq=65535;
rWrite(i,0,chan[i].freq&0xff); rWrite(i,0,chan[i].freq&0xff);
rWrite(i,1,(chan[i].freq>>8)&0xff); rWrite(i,1,(chan[i].freq>>8)&0xff);
@ -223,7 +229,7 @@ void DivPlatformVERA::tick(bool sysTick) {
} }
} }
if (chan[16].freqChanged) { if (chan[16].freqChanged) {
chan[16].freq=parent->calcFreq(chan[16].baseFreq,chan[16].pitch,false,8)+chan[16].std.pitch.val; chan[16].freq=parent->calcFreq(chan[16].baseFreq,chan[16].pitch,false,8,chan[16].pitch2);
if (chan[16].freq>128) chan[16].freq=128; if (chan[16].freq>128) chan[16].freq=128;
rWritePCMRate(chan[16].freq&0xff); rWritePCMRate(chan[16].freq&0xff);
chan[16].freqChanged=false; chan[16].freqChanged=false;
@ -259,7 +265,7 @@ int DivPlatformVERA::dispatch(DivCommand c) {
chan[c.chan].note=c.value; chan[c.chan].note=c.value;
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_VERA)); chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VERA));
break; break;
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].active=false; chan[c.chan].active=false;
@ -270,7 +276,7 @@ int DivPlatformVERA::dispatch(DivCommand c) {
rWritePCMCtrl(0x80); rWritePCMCtrl(0x80);
rWritePCMRate(0); rWritePCMRate(0);
} }
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -327,7 +333,7 @@ int DivPlatformVERA::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_VERA)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VERA));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -46,6 +46,10 @@ class DivPlatformVERA: public DivDispatch {
PCMChannel(): sample(-1), pos(0), len(0), freq(0), depth16(false) {} PCMChannel(): sample(-1), pos(0), len(0), freq(0), depth16(false) {}
} pcm; } pcm;
// somebody please split this into multiple lines! // somebody please split this into multiple lines!
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), pan(0), active(false), freqChanged(false), inPorta(false), vol(0), outVol(0), accum(0), noiseval(0) {} Channel(): freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), pan(0), active(false), freqChanged(false), inPorta(false), vol(0), outVol(0), accum(0), noiseval(0) {}
}; };
Channel chan[17]; Channel chan[17];

View File

@ -120,10 +120,16 @@ void DivPlatformVIC20::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2);
if (i<3) { if (i<3) {
chan[i].freq>>=(2-i); chan[i].freq>>=(2-i);
} else { } else {
@ -166,13 +172,13 @@ int DivPlatformVIC20::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
break; break;
} }
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -232,7 +238,7 @@ int DivPlatformVIC20::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_VIC)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VIC));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -32,6 +32,10 @@ class DivPlatformVIC20: public DivDispatch {
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta; bool active, insChanged, freqChanged, keyOn, keyOff, inPorta;
int vol, outVol, wave, waveWriteCycle; int vol, outVol, wave, waveWriteCycle;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -179,13 +179,19 @@ void DivPlatformVRC6::tick(bool sysTick) {
} }
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
if (i==2) { // sawtooth if (i==2) { // sawtooth
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1; chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2)-1;
} else { // pulse } else { // pulse
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1; chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2)-1;
if (chan[i].furnaceDac) { if (chan[i].furnaceDac) {
double off=1.0; double off=1.0;
if (chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) { if (chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) {
@ -249,7 +255,7 @@ int DivPlatformVRC6::dispatch(DivCommand c) {
chan[c.chan].note=c.value; chan[c.chan].note=c.value;
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
//chan[c.chan].keyOn=true; //chan[c.chan].keyOn=true;
chan[c.chan].furnaceDac=true; chan[c.chan].furnaceDac=true;
} else { } else {
@ -284,7 +290,7 @@ int DivPlatformVRC6::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_VRC6)); chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VRC6));
if (!isMuted[c.chan]) { if (!isMuted[c.chan]) {
if (c.chan==2) { // sawtooth if (c.chan==2) { // sawtooth
chWrite(c.chan,0,chan[c.chan].vol); chWrite(c.chan,0,chan[c.chan].vol);
@ -299,7 +305,7 @@ int DivPlatformVRC6::dispatch(DivCommand c) {
chan[c.chan].pcm=false; chan[c.chan].pcm=false;
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -380,7 +386,7 @@ int DivPlatformVRC6::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_VRC6)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VRC6));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -36,6 +36,10 @@ class DivPlatformVRC6: public DivDispatch {
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, pcm, furnaceDac; bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, pcm, furnaceDac;
signed char vol, outVol; signed char vol, outVol;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), freq(0),
baseFreq(0), baseFreq(0),

View File

@ -383,6 +383,12 @@ void DivPlatformX1_010::tick(bool sysTick) {
chan[i].envChanged=true; chan[i].envChanged=true;
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
if (chan[i].std.ex1.had) { if (chan[i].std.ex1.had) {
@ -476,7 +482,7 @@ void DivPlatformX1_010::tick(bool sysTick) {
chan[i].envChanged=false; chan[i].envChanged=false;
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2);
if (chan[i].pcm) { if (chan[i].pcm) {
if (chan[i].freq<1) chan[i].freq=1; if (chan[i].freq<1) chan[i].freq=1;
if (chan[i].freq>255) chan[i].freq=255; if (chan[i].freq>255) chan[i].freq=255;
@ -535,7 +541,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) {
if (skipRegisterWrites) break; if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) { if (chan[c.chan].furnacePCM) {
chan[c.chan].pcm=true; chan[c.chan].pcm=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
chan[c.chan].sample=ins->amiga.initSample; chan[c.chan].sample=ins->amiga.initSample;
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) { if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample); DivSample* s=parent->getSample(chan[c.chan].sample);
@ -548,7 +554,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) {
chan[c.chan].freqChanged=true; chan[c.chan].freqChanged=true;
} }
} else { } else {
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) { if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
chWrite(c.chan,0,0); // reset chWrite(c.chan,0,0); // reset
@ -560,7 +566,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) {
} }
} }
} else { } else {
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) { if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
chWrite(c.chan,0,0); // reset chWrite(c.chan,0,0); // reset
@ -585,7 +591,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) {
chan[c.chan].active=true; chan[c.chan].active=true;
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
chan[c.chan].envChanged=true; chan[c.chan].envChanged=true;
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (chan[c.chan].wave<0) { if (chan[c.chan].wave<0) {
chan[c.chan].wave=0; chan[c.chan].wave=0;
chan[c.chan].ws.changeWave1(chan[c.chan].wave); chan[c.chan].ws.changeWave1(chan[c.chan].wave);
@ -599,7 +605,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) {
chan[c.chan].pcm=false; chan[c.chan].pcm=false;
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE: case DIV_CMD_ENV_RELEASE:
@ -703,7 +709,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_X1_010)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_X1_010));
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;

View File

@ -99,6 +99,10 @@ class DivPlatformX1_010: public DivDispatch {
vol = outVol = lvol = rvol = 15; vol = outVol = lvol = rvol = 15;
waveBank = 0; waveBank = 0;
} }
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), freq(0), baseFreq(0), pitch(0), pitch2(0), note(0),
wave(-1), sample(-1), ins(-1), wave(-1), sample(-1), ins(-1),

View File

@ -414,6 +414,12 @@ void DivPlatformYM2610::tick(bool sysTick) {
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
@ -572,9 +578,9 @@ void DivPlatformYM2610::tick(bool sysTick) {
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
if (i==1 && extMode) continue; if (i==1 && extMode) continue;
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].pitch2);
if (chan[i].freq>262143) chan[i].freq=262143; if (chan[i].freq>262143) chan[i].freq=262143;
int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val; int freqt=toFreq(chan[i].freq)+chan[i].pitch2;
immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8); immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8);
immWrite(chanOffs[i]+ADDR_FREQ,freqt&0xff); immWrite(chanOffs[i]+ADDR_FREQ,freqt&0xff);
chan[i].freqChanged=false; chan[i].freqChanged=false;
@ -643,7 +649,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
} }
if (skipRegisterWrites) break; if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) { if (chan[c.chan].furnacePCM) {
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) { if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
immWrite(0x1b,chan[c.chan].outVol); immWrite(0x1b,chan[c.chan].outVol);
@ -675,7 +681,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
} }
} else { } else {
chan[c.chan].sample=-1; chan[c.chan].sample=-1;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) { if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
immWrite(0x10,0x01); // reset immWrite(0x10,0x01); // reset
@ -719,7 +725,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
break; break;
} }
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM); DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (c.chan<4) { if (c.chan<4) {
if (!chan[c.chan].std.vol.will) { if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
@ -779,7 +785,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].keyOn=false; chan[c.chan].keyOn=false;
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
if (c.chan>12) { if (c.chan>12) {
@ -981,7 +987,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (c.chan>3) { if (c.chan>3) {
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_FM)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FM));
} }
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;

View File

@ -51,6 +51,10 @@ class DivPlatformYM2610: public DivDispatch {
int sample; int sample;
unsigned char pan; unsigned char pan;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freqH(0), freqH(0),
freqL(0), freqL(0),

View File

@ -478,6 +478,12 @@ void DivPlatformYM2610B::tick(bool sysTick) {
} }
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
CLAMP_VAR(chan[i].pitch2,-2048,2048);
} else {
chan[i].pitch2=chan[i].std.pitch.val;
}
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
@ -635,9 +641,9 @@ void DivPlatformYM2610B::tick(bool sysTick) {
for (int i=0; i<6; i++) { for (int i=0; i<6; i++) {
if (i==2 && extMode) continue; if (i==2 && extMode) continue;
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].std.pitch.val); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].pitch2);
if (chan[i].freq>262143) chan[i].freq=262143; if (chan[i].freq>262143) chan[i].freq=262143;
int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val; int freqt=toFreq(chan[i].freq)+chan[i].pitch2;
immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8); immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8);
immWrite(chanOffs[i]+ADDR_FREQ,freqt&0xff); immWrite(chanOffs[i]+ADDR_FREQ,freqt&0xff);
chan[i].freqChanged=false; chan[i].freqChanged=false;
@ -706,7 +712,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
} }
if (skipRegisterWrites) break; if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) { if (chan[c.chan].furnacePCM) {
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) { if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
immWrite(0x1b,chan[c.chan].outVol); immWrite(0x1b,chan[c.chan].outVol);
@ -738,7 +744,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
} }
} else { } else {
chan[c.chan].sample=-1; chan[c.chan].sample=-1;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) { if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
immWrite(0x10,0x01); // reset immWrite(0x10,0x01); // reset
@ -782,7 +788,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
break; break;
} }
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM); DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
chan[c.chan].std.init(ins); chan[c.chan].macroInit(ins);
if (c.chan<6) { if (c.chan<6) {
if (!chan[c.chan].std.vol.will) { if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
@ -842,7 +848,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].keyOn=false; chan[c.chan].keyOn=false;
chan[c.chan].active=false; chan[c.chan].active=false;
chan[c.chan].std.init(NULL); chan[c.chan].macroInit(NULL);
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
if (c.chan>14) { if (c.chan>14) {
@ -1044,7 +1050,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (c.chan>5) { if (c.chan>5) {
if (chan[c.chan].active && c.value2) { if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_FM)); if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FM));
} }
} }
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;

View File

@ -43,6 +43,10 @@ class DivPlatformYM2610B: public DivDispatch {
int sample; int sample;
unsigned char pan; unsigned char pan;
DivMacroInt std; DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
pitch2=0;
}
Channel(): Channel():
freqH(0), freqH(0),
freqL(0), freqL(0),

View File

@ -235,7 +235,7 @@ void DivPlatformYM2610BExt::tick(bool sysTick) {
unsigned char writeMask=2; unsigned char writeMask=2;
if (extMode) for (int i=0; i<4; i++) { if (extMode) for (int i=0; i<4; i++) {
if (opChan[i].freqChanged) { if (opChan[i].freqChanged) {
opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch); opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch,false,octave(opChan[i].baseFreq),opChan[i].pitch2);
if (opChan[i].freq>262143) opChan[i].freq=262143; if (opChan[i].freq>262143) opChan[i].freq=262143;
int freqt=toFreq(opChan[i].freq); int freqt=toFreq(opChan[i].freq);
opChan[i].freqH=freqt>>8; opChan[i].freqH=freqt>>8;

View File

@ -235,7 +235,7 @@ void DivPlatformYM2610Ext::tick(bool sysTick) {
unsigned char writeMask=2; unsigned char writeMask=2;
if (extMode) for (int i=0; i<4; i++) { if (extMode) for (int i=0; i<4; i++) {
if (opChan[i].freqChanged) { if (opChan[i].freqChanged) {
opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch); opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch,false,octave(opChan[i].baseFreq),opChan[i].pitch2);
if (opChan[i].freq>262143) opChan[i].freq=262143; if (opChan[i].freq>262143) opChan[i].freq=262143;
int freqt=toFreq(opChan[i].freq); int freqt=toFreq(opChan[i].freq);
opChan[i].freqH=freqt>>8; opChan[i].freqH=freqt>>8;

View File

@ -210,15 +210,10 @@ const char* dualWSEffects[7]={
"Phase (dual)", "Phase (dual)",
}; };
const char* macroAbsoluteMode[2]={ const char* macroAbsoluteMode="Fixed";
"Relative", const char* macroRelativeMode="Relative";
"Absolute"
};
const char* macroDummyMode[2]={ const char* macroDummyMode="Bug";
"Bug",
"Bug"
};
String macroHoverNote(int id, float val) { String macroHoverNote(int id, float val) {
if (val<-60 || val>=120) return "???"; if (val<-60 || val>=120) return "???";
@ -1086,7 +1081,8 @@ void FurnaceGUI::drawGBEnv(unsigned char vol, unsigned char len, unsigned char s
} \ } \
if (macroMode) { \ if (macroMode) { \
bool modeVal=macro.mode; \ bool modeVal=macro.mode; \
if (ImGui::Checkbox("Fixed##IMacroMode_" macroName,&modeVal)) { \ String modeName=fmt::sprintf("%s##IMacroMode_" macroName,displayModeName); \
if (ImGui::Checkbox(modeName.c_str(),&modeVal)) { \
macro.mode=modeVal; \ macro.mode=modeVal; \
} \ } \
} \ } \
@ -2880,7 +2876,7 @@ void FurnaceGUI::drawInsEdit() {
NORMAL_MACRO(ins->std.panRMacro,0,panMax,"panR","Panning (right)",(31+panMax),ins->std.panRMacro.open,false,NULL,false,NULL,0,0,0,0,false,0,macroDummyMode,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[14],0,panMax,NULL,false); NORMAL_MACRO(ins->std.panRMacro,0,panMax,"panR","Panning (right)",(31+panMax),ins->std.panRMacro.open,false,NULL,false,NULL,0,0,0,0,false,0,macroDummyMode,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[14],0,panMax,NULL,false);
} }
} }
NORMAL_MACRO(ins->std.pitchMacro,pitchMacroScroll,pitchMacroScroll+160,"pitch","Pitch",160,ins->std.pitchMacro.open,false,NULL,true,&pitchMacroScroll,-2048,2047,0,0,true,1,macroAbsoluteMode,uiColors[GUI_COLOR_MACRO_PITCH],mmlString[15],-2048,2047,NULL,!ins->std.pitchMacro.mode); NORMAL_MACRO(ins->std.pitchMacro,pitchMacroScroll,pitchMacroScroll+160,"pitch","Pitch",160,ins->std.pitchMacro.open,false,NULL,true,&pitchMacroScroll,-2048,2047,0,0,true,1,macroRelativeMode,uiColors[GUI_COLOR_MACRO_PITCH],mmlString[15],-2048,2047,NULL,!ins->std.pitchMacro.mode);
if (ins->type==DIV_INS_FM || if (ins->type==DIV_INS_FM ||
ins->type==DIV_INS_STD || ins->type==DIV_INS_STD ||
ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL ||