SNES: fix some clicking issues

This commit is contained in:
tildearrow 2022-10-08 22:22:01 -05:00
parent ec22150fb5
commit 6179ef493c
2 changed files with 49 additions and 25 deletions

View File

@ -69,14 +69,16 @@ void DivPlatformSNES::acquire(short* bufL, short* bufR, size_t start, size_t len
short out[2]; short out[2];
short chOut[16]; short chOut[16];
for (size_t h=start; h<start+len; h++) { for (size_t h=start; h<start+len; h++) {
// TODO: delay if (--delay<=0) {
if (!writes.empty()) { delay=0;
QueuedWrite w=writes.front(); if (!writes.empty()) {
dsp.write(w.addr,w.val); QueuedWrite w=writes.front();
regPool[w.addr&0x7f]=w.val; dsp.write(w.addr,w.val);
writes.pop(); regPool[w.addr&0x7f]=w.val;
writes.pop();
delay=(w.addr==0x5c)?8:1;
}
} }
dsp.set_output(out,1); dsp.set_output(out,1);
dsp.run(32); dsp.run(32);
dsp.get_voice_outputs(chOut); dsp.get_voice_outputs(chOut);
@ -159,7 +161,7 @@ void DivPlatformSNES::tick(bool sysTick) {
} }
} }
if (chan[i].std.vol.had || chan[i].std.panL.had || chan[i].std.panR.had || hasInverted) { if (chan[i].std.vol.had || chan[i].std.panL.had || chan[i].std.panR.had || hasInverted) {
writeOutVol(i); chan[i].shallWriteVol=true;
} }
if (chan[i].std.ex2.had) { if (chan[i].std.ex2.had) {
if (chan[i].std.ex2.val&0x80) { if (chan[i].std.ex2.val&0x80) {
@ -182,7 +184,7 @@ void DivPlatformSNES::tick(bool sysTick) {
chan[i].state.gainMode=DivInstrumentSNES::GAIN_MODE_DIRECT; chan[i].state.gainMode=DivInstrumentSNES::GAIN_MODE_DIRECT;
chan[i].state.gain=chan[i].std.ex2.val&127; chan[i].state.gain=chan[i].std.ex2.val&127;
} }
writeEnv(i); chan[i].shallWriteEnv=true;
} }
if (chan[i].setPos) { if (chan[i].setPos) {
// force keyon // force keyon
@ -196,6 +198,8 @@ void DivPlatformSNES::tick(bool sysTick) {
updateWave(i); updateWave(i);
} }
} }
}
for (int i=0; i<8; i++) {
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
DivSample* s=parent->getSample(chan[i].sample); DivSample* s=parent->getSample(chan[i].sample);
double off=(s->centerRate>=1)?((double)s->centerRate/8363.0):1.0; double off=(s->centerRate>=1)?((double)s->centerRate/8363.0):1.0;
@ -228,6 +232,7 @@ void DivPlatformSNES::tick(bool sysTick) {
sampleMem[tabAddr+2]=loop&0xff; sampleMem[tabAddr+2]=loop&0xff;
sampleMem[tabAddr+3]=loop>>8; sampleMem[tabAddr+3]=loop>>8;
kon|=(1<<i); kon|=(1<<i);
koff|=(1<<i);
chan[i].keyOn=false; chan[i].keyOn=false;
} }
if (chan[i].keyOff) { if (chan[i].keyOff) {
@ -243,6 +248,9 @@ void DivPlatformSNES::tick(bool sysTick) {
} }
} }
} }
if (koff!=0) {
rWrite(0x5c,koff);
}
if (writeControl) { if (writeControl) {
unsigned char control=(noiseFreq&0x1f)|(echoOn?0:0x20); unsigned char control=(noiseFreq&0x1f)|(echoOn?0:0x20);
rWrite(0x6c,control); rWrite(0x6c,control);
@ -290,11 +298,24 @@ void DivPlatformSNES::tick(bool sysTick) {
rWrite(0x4d,echoBits); rWrite(0x4d,echoBits);
writeEcho=false; writeEcho=false;
} }
for (int i=0; i<8; i++) {
if (chan[i].shallWriteEnv) {
writeEnv(i);
chan[i].shallWriteEnv=false;
}
}
if (koff!=0) {
rWrite(0x5c,0);
}
if (kon!=0) { if (kon!=0) {
rWrite(0x4c,kon); rWrite(0x4c,kon);
} }
// always write KOFF as it's constantly polled for (int i=0; i<8; i++) {
rWrite(0x5c,koff); if (chan[i].shallWriteVol) {
writeOutVol(i);
chan[i].shallWriteVol=false;
}
}
} }
int DivPlatformSNES::dispatch(DivCommand c) { int DivPlatformSNES::dispatch(DivCommand c) {
@ -324,7 +345,7 @@ int DivPlatformSNES::dispatch(DivCommand c) {
} }
chan[c.chan].active=true; chan[c.chan].active=true;
if (chan[c.chan].insChanged || chan[c.chan].state.sus) { if (chan[c.chan].insChanged || chan[c.chan].state.sus) {
writeEnv(c.chan); chan[c.chan].shallWriteEnv=true;
} }
if (c.value!=DIV_NOTE_NULL) { if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=round(NOTE_FREQUENCY(c.value)); chan[c.chan].baseFreq=round(NOTE_FREQUENCY(c.value));
@ -341,7 +362,7 @@ int DivPlatformSNES::dispatch(DivCommand c) {
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].keyOn=false; chan[c.chan].keyOn=false;
if (chan[c.chan].state.sus) { if (chan[c.chan].state.sus) {
writeEnv(c.chan); chan[c.chan].shallWriteEnv=true;
} else { } else {
chan[c.chan].macroInit(NULL); chan[c.chan].macroInit(NULL);
} }
@ -351,7 +372,7 @@ int DivPlatformSNES::dispatch(DivCommand c) {
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].keyOn=false; chan[c.chan].keyOn=false;
if (chan[c.chan].state.sus) { if (chan[c.chan].state.sus) {
writeEnv(c.chan); chan[c.chan].shallWriteEnv=true;
} }
chan[c.chan].std.release(); chan[c.chan].std.release();
break; break;
@ -369,7 +390,7 @@ int DivPlatformSNES::dispatch(DivCommand c) {
chan[c.chan].vol=c.value; chan[c.chan].vol=c.value;
if (!chan[c.chan].std.vol.has) { if (!chan[c.chan].std.vol.has) {
chan[c.chan].outVol=c.value; chan[c.chan].outVol=c.value;
writeOutVol(c.chan); chan[c.chan].shallWriteVol=true;
} }
} }
break; break;
@ -379,7 +400,7 @@ int DivPlatformSNES::dispatch(DivCommand c) {
case DIV_CMD_PANNING: case DIV_CMD_PANNING:
chan[c.chan].panL=c.value>>1; chan[c.chan].panL=c.value>>1;
chan[c.chan].panR=c.value2>>1; chan[c.chan].panR=c.value2>>1;
writeOutVol(c.chan); chan[c.chan].shallWriteVol=true;
break; break;
case DIV_CMD_PITCH: case DIV_CMD_PITCH:
chan[c.chan].pitch=c.value; chan[c.chan].pitch=c.value;
@ -441,7 +462,7 @@ int DivPlatformSNES::dispatch(DivCommand c) {
case DIV_CMD_SNES_INVERT: case DIV_CMD_SNES_INVERT:
chan[c.chan].invertL=(c.value>>4); chan[c.chan].invertL=(c.value>>4);
chan[c.chan].invertR=c.chan&15; chan[c.chan].invertR=c.chan&15;
writeOutVol(c.chan); chan[c.chan].shallWriteVol=true;
break; break;
case DIV_CMD_SNES_GAIN_MODE: case DIV_CMD_SNES_GAIN_MODE:
if (c.value) { if (c.value) {
@ -466,7 +487,7 @@ int DivPlatformSNES::dispatch(DivCommand c) {
} else { } else {
chan[c.chan].state.useEnv=true; chan[c.chan].state.useEnv=true;
} }
writeEnv(c.chan); chan[c.chan].shallWriteEnv=true;
break; break;
case DIV_CMD_SNES_GAIN: case DIV_CMD_SNES_GAIN:
if (chan[c.chan].state.gainMode==DivInstrumentSNES::GAIN_MODE_DIRECT) { if (chan[c.chan].state.gainMode==DivInstrumentSNES::GAIN_MODE_DIRECT) {
@ -474,7 +495,7 @@ int DivPlatformSNES::dispatch(DivCommand c) {
} else { } else {
chan[c.chan].state.gain=c.value&0x1f; chan[c.chan].state.gain=c.value&0x1f;
} }
if (!chan[c.chan].state.useEnv) writeEnv(c.chan); if (!chan[c.chan].state.useEnv) chan[c.chan].shallWriteEnv=true;
break; break;
case DIV_CMD_STD_NOISE_FREQ: case DIV_CMD_STD_NOISE_FREQ:
noiseFreq=c.value&0x1f; noiseFreq=c.value&0x1f;
@ -482,19 +503,19 @@ int DivPlatformSNES::dispatch(DivCommand c) {
break; break;
case DIV_CMD_FM_AR: case DIV_CMD_FM_AR:
chan[c.chan].state.a=c.value&15; chan[c.chan].state.a=c.value&15;
if (chan[c.chan].state.useEnv) writeEnv(c.chan); if (chan[c.chan].state.useEnv) chan[c.chan].shallWriteEnv=true;
break; break;
case DIV_CMD_FM_DR: case DIV_CMD_FM_DR:
chan[c.chan].state.d=c.value&7; chan[c.chan].state.d=c.value&7;
if (chan[c.chan].state.useEnv) writeEnv(c.chan); if (chan[c.chan].state.useEnv) chan[c.chan].shallWriteEnv=true;
break; break;
case DIV_CMD_FM_SL: case DIV_CMD_FM_SL:
chan[c.chan].state.s=c.value&7; chan[c.chan].state.s=c.value&7;
if (chan[c.chan].state.useEnv) writeEnv(c.chan); if (chan[c.chan].state.useEnv) chan[c.chan].shallWriteEnv=true;
break; break;
case DIV_CMD_FM_RR: case DIV_CMD_FM_RR:
chan[c.chan].state.r=c.value&0x1f; chan[c.chan].state.r=c.value&0x1f;
if (chan[c.chan].state.useEnv) writeEnv(c.chan); if (chan[c.chan].state.useEnv) chan[c.chan].shallWriteEnv=true;
break; break;
case DIV_CMD_SNES_ECHO: case DIV_CMD_SNES_ECHO:
chan[c.chan].echo=c.value; chan[c.chan].echo=c.value;
@ -605,7 +626,7 @@ void DivPlatformSNES::writeEnv(int ch) {
void DivPlatformSNES::muteChannel(int ch, bool mute) { void DivPlatformSNES::muteChannel(int ch, bool mute) {
isMuted[ch]=mute; isMuted[ch]=mute;
writeOutVol(ch); chan[ch].shallWriteVol=true;
} }
void DivPlatformSNES::forceIns() { void DivPlatformSNES::forceIns() {

View File

@ -33,7 +33,7 @@ class DivPlatformSNES: public DivDispatch {
int sample, wave, ins; int sample, wave, ins;
int note; int note;
int panL, panR; int panL, panR;
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, useWave, setPos, noise, echo, pitchMod, invertL, invertR; bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, useWave, setPos, noise, echo, pitchMod, invertL, invertR, shallWriteVol, shallWriteEnv;
int vol, outVol; int vol, outVol;
int wtLen; int wtLen;
DivInstrumentSNES state; DivInstrumentSNES state;
@ -68,6 +68,8 @@ class DivPlatformSNES: public DivDispatch {
pitchMod(false), pitchMod(false),
invertL(false), invertL(false),
invertR(false), invertR(false),
shallWriteVol(false),
shallWriteEnv(false),
vol(127), vol(127),
outVol(127), outVol(127),
wtLen(16) {} wtLen(16) {}
@ -77,6 +79,7 @@ class DivPlatformSNES: public DivDispatch {
bool isMuted[8]; bool isMuted[8];
int globalVolL, globalVolR; int globalVolL, globalVolR;
unsigned char noiseFreq; unsigned char noiseFreq;
signed char delay;
signed char echoVolL, echoVolR, echoFeedback; signed char echoVolL, echoVolR, echoFeedback;
signed char echoFIR[8]; signed char echoFIR[8];
unsigned char echoDelay; unsigned char echoDelay;