OPM/OPZ: Seamless Legato Ins Change

This commit is contained in:
tildearrow 2023-01-19 02:28:12 -05:00
parent 1b05fe577d
commit 6832f92b99
4 changed files with 97 additions and 77 deletions

View File

@ -382,53 +382,57 @@ void DivPlatformArcade::muteChannel(int ch, bool mute) {
}
}
void DivPlatformArcade::commitState(int ch, DivInstrument* ins) {
if (chan[ch].insChanged) {
chan[ch].state=ins->fm;
chan[ch].opMask=
(chan[ch].state.op[0].enable?1:0)|
(chan[ch].state.op[2].enable?2:0)|
(chan[ch].state.op[1].enable?4:0)|
(chan[ch].state.op[3].enable?8:0);
}
for (int i=0; i<4; i++) {
unsigned short baseAddr=chanOffs[ch]|opOffs[i];
DivInstrumentFM::Operator op=chan[ch].state.op[i];
if (KVS(ch,i)) {
if (!chan[ch].active || chan[ch].insChanged) {
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[ch].outVol&0x7f,127));
}
} else {
if (chan[ch].insChanged) {
rWrite(baseAddr+ADDR_TL,op.tl);
}
}
if (chan[ch].insChanged) {
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
}
}
if (chan[ch].insChanged) {
if (isMuted[ch]) {
rWrite(chanOffs[ch]+ADDR_LR_FB_ALG,(chan[ch].state.alg&7)|(chan[ch].state.fb<<3));
} else {
rWrite(chanOffs[ch]+ADDR_LR_FB_ALG,(chan[ch].state.alg&7)|(chan[ch].state.fb<<3)|((chan[ch].chVolL&1)<<6)|((chan[ch].chVolR&1)<<7));
}
rWrite(chanOffs[ch]+ADDR_FMS_AMS,((chan[ch].state.fms&7)<<4)|(chan[ch].state.ams&3));
}
}
int DivPlatformArcade::dispatch(DivCommand c) {
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
if (chan[c.chan].insChanged) {
chan[c.chan].state=ins->fm;
chan[c.chan].opMask=
(chan[c.chan].state.op[0].enable?1:0)|
(chan[c.chan].state.op[2].enable?2:0)|
(chan[c.chan].state.op[1].enable?4:0)|
(chan[c.chan].state.op[3].enable?8:0);
}
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
for (int i=0; i<4; i++) {
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
DivInstrumentFM::Operator op=chan[c.chan].state.op[i];
if (KVS(c.chan,i)) {
if (!chan[c.chan].active || chan[c.chan].insChanged) {
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127));
}
} else {
if (chan[c.chan].insChanged) {
rWrite(baseAddr+ADDR_TL,op.tl);
}
}
if (chan[c.chan].insChanged) {
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
}
}
if (chan[c.chan].insChanged) {
if (isMuted[c.chan]) {
rWrite(chanOffs[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
} else {
rWrite(chanOffs[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)|((chan[c.chan].chVolL&1)<<6)|((chan[c.chan].chVolR&1)<<7));
}
rWrite(chanOffs[c.chan]+ADDR_FMS_AMS,((chan[c.chan].state.fms&7)<<4)|(chan[c.chan].state.ams&3));
}
commitState(c.chan,ins);
chan[c.chan].insChanged=false;
if (c.value!=DIV_NOTE_NULL) {
@ -521,6 +525,11 @@ int DivPlatformArcade::dispatch(DivCommand c) {
break;
}
case DIV_CMD_LEGATO: {
if (chan[c.chan].insChanged) {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPM);
commitState(c.chan,ins);
chan[c.chan].insChanged=false;
}
chan[c.chan].baseFreq=NOTE_LINEAR(c.value);
chan[c.chan].freqChanged=true;
break;

View File

@ -57,6 +57,7 @@ class DivPlatformArcade: public DivPlatformOPM {
int octave(int freq);
int toFreq(int freq);
void commitState(int ch, DivInstrument* ins);
void acquire_nuked(short** buf, size_t len);
void acquire_ymfm(short** buf, size_t len);

View File

@ -350,56 +350,60 @@ void DivPlatformTX81Z::muteChannel(int ch, bool mute) {
}
}
void DivPlatformTX81Z::commitState(int ch, DivInstrument* ins) {
if (chan[ch].insChanged) {
chan[ch].state=ins->fm;
}
for (int i=0; i<4; i++) {
unsigned short baseAddr=chanOffs[ch]|opOffs[i];
DivInstrumentFM::Operator op=chan[ch].state.op[i];
if (isMuted[ch]) {
rWrite(baseAddr+ADDR_TL,127);
} else {
if (KVS(ch,i)) {
if (!chan[ch].active || chan[ch].insChanged) {
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[ch].outVol&0x7f,127));
}
} else {
if (chan[ch].insChanged) {
rWrite(baseAddr+ADDR_TL,op.tl);
}
}
}
if (chan[ch].insChanged) {
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|((op.egt?(op.dt&7):dtTable[op.dt&7])<<4));
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.egt<<5)|(op.rs<<6));
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
rWrite(baseAddr+ADDR_WS_FINE,(op.dvb&15)|(op.ws<<4));
rWrite(baseAddr+ADDR_EGS_REV,(op.dam&7)|(op.ksl<<6));
}
}
if (chan[ch].insChanged) {
/*
if (isMuted[ch]) {
rWrite(chanOffs[ch]+ADDR_LR_FB_ALG,(chan[ch].state.alg&7)|(chan[ch].state.fb<<3));
} else {
rWrite(chanOffs[ch]+ADDR_LR_FB_ALG,(chan[ch].state.alg&7)|(chan[ch].state.fb<<3)|((chan[ch].chVolL&1)<<6)|((chan[ch].chVolR&1)<<7));
}*/
rWrite(chanOffs[ch]+ADDR_FMS_AMS,((chan[ch].state.fms&7)<<4)|(chan[ch].state.ams&3));
//rWrite(chanOffs[ch]+ADDR_FMS_AMS,0x84|((chan[ch].state.fms2&7)<<4)|(chan[ch].state.ams2&3));
}
}
int DivPlatformTX81Z::dispatch(DivCommand c) {
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPZ);
if (chan[c.chan].insChanged) {
chan[c.chan].state=ins->fm;
}
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
for (int i=0; i<4; i++) {
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
DivInstrumentFM::Operator op=chan[c.chan].state.op[i];
if (isMuted[c.chan]) {
rWrite(baseAddr+ADDR_TL,127);
} else {
if (KVS(c.chan,i)) {
if (!chan[c.chan].active || chan[c.chan].insChanged) {
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127));
}
} else {
if (chan[c.chan].insChanged) {
rWrite(baseAddr+ADDR_TL,op.tl);
}
}
}
if (chan[c.chan].insChanged) {
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|((op.egt?(op.dt&7):dtTable[op.dt&7])<<4));
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.egt<<5)|(op.rs<<6));
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
rWrite(baseAddr+ADDR_WS_FINE,(op.dvb&15)|(op.ws<<4));
rWrite(baseAddr+ADDR_EGS_REV,(op.dam&7)|(op.ksl<<6));
}
}
if (chan[c.chan].insChanged) {
/*
if (isMuted[c.chan]) {
rWrite(chanOffs[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
} else {
rWrite(chanOffs[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)|((chan[c.chan].chVolL&1)<<6)|((chan[c.chan].chVolR&1)<<7));
}*/
rWrite(chanOffs[c.chan]+ADDR_FMS_AMS,((chan[c.chan].state.fms&7)<<4)|(chan[c.chan].state.ams&3));
//rWrite(chanOffs[c.chan]+ADDR_FMS_AMS,0x84|((chan[c.chan].state.fms2&7)<<4)|(chan[c.chan].state.ams2&3));
}
commitState(c.chan,ins);
chan[c.chan].insChanged=false;
if (c.value!=DIV_NOTE_NULL) {
@ -498,6 +502,11 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
break;
}
case DIV_CMD_LEGATO: {
if (chan[c.chan].insChanged) {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPZ);
commitState(c.chan,ins);
chan[c.chan].insChanged=false;
}
chan[c.chan].baseFreq=NOTE_LINEAR(c.value);
chan[c.chan].freqChanged=true;
break;

View File

@ -57,6 +57,7 @@ class DivPlatformTX81Z: public DivPlatformOPM {
int octave(int freq);
int toFreq(int freq);
void commitState(int ch, DivInstrument* ins);
friend void putDispatchChip(void*,int);
public: