mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-27 06:53:01 +00:00
SNES: invert/pitch mod/noise control
echo still work in progress
This commit is contained in:
parent
b4c260dc2a
commit
b4c020c11b
3 changed files with 124 additions and 45 deletions
|
@ -93,24 +93,15 @@ void DivPlatformSNES::tick(bool sysTick) {
|
||||||
// so they have to be accumulated
|
// so they have to be accumulated
|
||||||
unsigned char kon=0;
|
unsigned char kon=0;
|
||||||
unsigned char koff=0;
|
unsigned char koff=0;
|
||||||
|
bool writeControl=false;
|
||||||
|
bool writeNoise=false;
|
||||||
|
bool writePitchMod=false;
|
||||||
|
bool writeEcho=false;
|
||||||
for (int i=0; i<8; i++) {
|
for (int i=0; i<8; i++) {
|
||||||
//bool hadGain=chan[i].std.vol.had || chan[i].std.ex1.had || chan[i].std.ex2.had;
|
|
||||||
chan[i].std.next();
|
chan[i].std.next();
|
||||||
if (chan[i].std.vol.had) {
|
if (chan[i].std.vol.had) {
|
||||||
chan[i].outVol=VOL_SCALE_LOG(chan[i].vol&127,MIN(127,chan[i].std.vol.val),127);
|
chan[i].outVol=VOL_SCALE_LOG(chan[i].vol&127,MIN(127,chan[i].std.vol.val),127);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if (chan[i].std.vol.had) {
|
|
||||||
chWrite(i,7,MIN(127,chan[i].std.vol.val*2));
|
|
||||||
} else if (!chan[i].state.useEnv && hadGain) {
|
|
||||||
if (chan[i].std.ex1.val==0) {
|
|
||||||
// direct gain
|
|
||||||
chWrite(i,7,chan[i].std.vol.val);
|
|
||||||
} else {
|
|
||||||
// inc/dec
|
|
||||||
chWrite(i,7,chan[i].std.ex2.val|((chan[i].std.ex1.val-1)<<5)|0x80);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
if (chan[i].std.arp.had) {
|
if (chan[i].std.arp.had) {
|
||||||
if (!chan[i].inPorta) {
|
if (!chan[i].inPorta) {
|
||||||
if (chan[i].std.arp.mode) {
|
if (chan[i].std.arp.mode) {
|
||||||
|
@ -126,6 +117,10 @@ void DivPlatformSNES::tick(bool sysTick) {
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (chan[i].std.duty.had) {
|
||||||
|
noiseFreq=chan[i].std.duty.val;
|
||||||
|
writeControl=true;
|
||||||
|
}
|
||||||
if (chan[i].useWave && chan[i].std.wave.had) {
|
if (chan[i].useWave && chan[i].std.wave.had) {
|
||||||
if (chan[i].wave!=chan[i].std.wave.val || chan[i].ws.activeChanged()) {
|
if (chan[i].wave!=chan[i].std.wave.val || chan[i].ws.activeChanged()) {
|
||||||
chan[i].wave=chan[i].std.wave.val;
|
chan[i].wave=chan[i].std.wave.val;
|
||||||
|
@ -149,7 +144,30 @@ void DivPlatformSNES::tick(bool sysTick) {
|
||||||
int val=chan[i].std.panR.val&0x7f;
|
int val=chan[i].std.panR.val&0x7f;
|
||||||
chan[i].panR=(val<<1)|(val>>6);
|
chan[i].panR=(val<<1)|(val>>6);
|
||||||
}
|
}
|
||||||
if (chan[i].std.vol.had || chan[i].std.panL.had || chan[i].std.panR.had) {
|
bool hasInverted=false;
|
||||||
|
if (chan[i].std.ex1.had) {
|
||||||
|
if (chan[i].invertL!=(chan[i].std.ex1.val&16)) {
|
||||||
|
chan[i].invertL=chan[i].std.ex1.val&16;
|
||||||
|
hasInverted=true;
|
||||||
|
}
|
||||||
|
if (chan[i].invertR!=(chan[i].std.ex1.val&8)) {
|
||||||
|
chan[i].invertR=chan[i].std.ex1.val&8;
|
||||||
|
hasInverted=true;
|
||||||
|
}
|
||||||
|
if (chan[i].pitchMod!=(chan[i].std.ex1.val&4)) {
|
||||||
|
chan[i].pitchMod=chan[i].std.ex1.val&4;
|
||||||
|
writePitchMod=true;
|
||||||
|
}
|
||||||
|
if (chan[i].echo!=(chan[i].std.ex1.val&2)) {
|
||||||
|
chan[i].echo=chan[i].std.ex1.val&2;
|
||||||
|
writeEcho=true;
|
||||||
|
}
|
||||||
|
if (chan[i].noise!=(chan[i].std.ex1.val&1)) {
|
||||||
|
chan[i].noise=chan[i].std.ex1.val&1;
|
||||||
|
writeNoise=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[i].std.vol.had || chan[i].std.panL.had || chan[i].std.panR.had || hasInverted) {
|
||||||
writeOutVol(i);
|
writeOutVol(i);
|
||||||
}
|
}
|
||||||
if (chan[i].setPos) {
|
if (chan[i].setPos) {
|
||||||
|
@ -173,29 +191,6 @@ void DivPlatformSNES::tick(bool sysTick) {
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
unsigned int start, end, loop;
|
unsigned int start, end, loop;
|
||||||
unsigned short tabAddr=sampleTableAddr(i);
|
unsigned short tabAddr=sampleTableAddr(i);
|
||||||
if (chan[i].state.useEnv) {
|
|
||||||
chWrite(i,5,chan[i].state.a|(chan[i].state.d<<4)|0x80);
|
|
||||||
chWrite(i,6,chan[i].state.r|(chan[i].state.s<<5));
|
|
||||||
} else {
|
|
||||||
chWrite(i,5,0);
|
|
||||||
switch (chan[i].state.gainMode) {
|
|
||||||
case DivInstrumentSNES::GAIN_MODE_DIRECT:
|
|
||||||
chWrite(i,7,chan[i].state.gain&127);
|
|
||||||
break;
|
|
||||||
case DivInstrumentSNES::GAIN_MODE_DEC_LINEAR:
|
|
||||||
chWrite(i,7,0x80|(chan[i].state.gain&31));
|
|
||||||
break;
|
|
||||||
case DivInstrumentSNES::GAIN_MODE_INC_LINEAR:
|
|
||||||
chWrite(i,7,0xc0|(chan[i].state.gain&31));
|
|
||||||
break;
|
|
||||||
case DivInstrumentSNES::GAIN_MODE_DEC_LOG:
|
|
||||||
chWrite(i,7,0xa0|(chan[i].state.gain&31));
|
|
||||||
break;
|
|
||||||
case DivInstrumentSNES::GAIN_MODE_INC_INVLOG:
|
|
||||||
chWrite(i,7,0xe0|(chan[i].state.gain&31));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chan[i].useWave) {
|
if (chan[i].useWave) {
|
||||||
start=waveTableAddr(i);
|
start=waveTableAddr(i);
|
||||||
loop=start;
|
loop=start;
|
||||||
|
@ -228,6 +223,49 @@ void DivPlatformSNES::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (writeControl) {
|
||||||
|
unsigned char control=noiseFreq&0x1f;
|
||||||
|
rWrite(0x6c,control);
|
||||||
|
}
|
||||||
|
if (writeNoise) {
|
||||||
|
unsigned char noiseBits=(
|
||||||
|
(chan[0].noise?1:0)|
|
||||||
|
(chan[1].noise?2:0)|
|
||||||
|
(chan[2].noise?4:0)|
|
||||||
|
(chan[3].noise?8:0)|
|
||||||
|
(chan[4].noise?0x10:0)|
|
||||||
|
(chan[5].noise?0x20:0)|
|
||||||
|
(chan[6].noise?0x40:0)|
|
||||||
|
(chan[7].noise?0x80:0)
|
||||||
|
);
|
||||||
|
rWrite(0x3d,noiseBits);
|
||||||
|
}
|
||||||
|
if (writePitchMod) {
|
||||||
|
unsigned char pitchModBits=(
|
||||||
|
(chan[0].pitchMod?1:0)|
|
||||||
|
(chan[1].pitchMod?2:0)|
|
||||||
|
(chan[2].pitchMod?4:0)|
|
||||||
|
(chan[3].pitchMod?8:0)|
|
||||||
|
(chan[4].pitchMod?0x10:0)|
|
||||||
|
(chan[5].pitchMod?0x20:0)|
|
||||||
|
(chan[6].pitchMod?0x40:0)|
|
||||||
|
(chan[7].pitchMod?0x80:0)
|
||||||
|
);
|
||||||
|
rWrite(0x2d,pitchModBits);
|
||||||
|
}
|
||||||
|
if (writeEcho) {
|
||||||
|
unsigned char echoBits=(
|
||||||
|
(chan[0].echo?1:0)|
|
||||||
|
(chan[1].echo?2:0)|
|
||||||
|
(chan[2].echo?4:0)|
|
||||||
|
(chan[3].echo?8:0)|
|
||||||
|
(chan[4].echo?0x10:0)|
|
||||||
|
(chan[5].echo?0x20:0)|
|
||||||
|
(chan[6].echo?0x40:0)|
|
||||||
|
(chan[7].echo?0x80:0)
|
||||||
|
);
|
||||||
|
rWrite(0x4d,echoBits);
|
||||||
|
}
|
||||||
if (kon!=0) {
|
if (kon!=0) {
|
||||||
rWrite(0x4c,kon);
|
rWrite(0x4c,kon);
|
||||||
}
|
}
|
||||||
|
@ -260,6 +298,29 @@ int DivPlatformSNES::dispatch(DivCommand c) {
|
||||||
if (chan[c.chan].insChanged) {
|
if (chan[c.chan].insChanged) {
|
||||||
chan[c.chan].state=ins->snes;
|
chan[c.chan].state=ins->snes;
|
||||||
}
|
}
|
||||||
|
if (chan[c.chan].state.useEnv) {
|
||||||
|
chWrite(c.chan,5,chan[c.chan].state.a|(chan[c.chan].state.d<<4)|0x80);
|
||||||
|
chWrite(c.chan,6,chan[c.chan].state.r|(chan[c.chan].state.s<<5));
|
||||||
|
} else {
|
||||||
|
chWrite(c.chan,5,0);
|
||||||
|
switch (chan[c.chan].state.gainMode) {
|
||||||
|
case DivInstrumentSNES::GAIN_MODE_DIRECT:
|
||||||
|
chWrite(c.chan,7,chan[c.chan].state.gain&127);
|
||||||
|
break;
|
||||||
|
case DivInstrumentSNES::GAIN_MODE_DEC_LINEAR:
|
||||||
|
chWrite(c.chan,7,0x80|(chan[c.chan].state.gain&31));
|
||||||
|
break;
|
||||||
|
case DivInstrumentSNES::GAIN_MODE_INC_LINEAR:
|
||||||
|
chWrite(c.chan,7,0xc0|(chan[c.chan].state.gain&31));
|
||||||
|
break;
|
||||||
|
case DivInstrumentSNES::GAIN_MODE_DEC_LOG:
|
||||||
|
chWrite(c.chan,7,0xa0|(chan[c.chan].state.gain&31));
|
||||||
|
break;
|
||||||
|
case DivInstrumentSNES::GAIN_MODE_INC_INVLOG:
|
||||||
|
chWrite(c.chan,7,0xe0|(chan[c.chan].state.gain&31));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
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));
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
|
@ -375,6 +436,8 @@ void DivPlatformSNES::writeOutVol(int ch) {
|
||||||
if (!isMuted[ch]) {
|
if (!isMuted[ch]) {
|
||||||
outL=(globalVolL*((chan[ch].outVol*chan[ch].panL)/127))/127;
|
outL=(globalVolL*((chan[ch].outVol*chan[ch].panL)/127))/127;
|
||||||
outR=(globalVolR*((chan[ch].outVol*chan[ch].panR)/127))/127;
|
outR=(globalVolR*((chan[ch].outVol*chan[ch].panR)/127))/127;
|
||||||
|
if (chan[ch].invertL) outL=-outL;
|
||||||
|
if (chan[ch].invertR) outR=-outR;
|
||||||
}
|
}
|
||||||
chWrite(ch,0,outL);
|
chWrite(ch,0,outL);
|
||||||
chWrite(ch,1,outR);
|
chWrite(ch,1,outR);
|
||||||
|
|
|
@ -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;
|
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, useWave, setPos, noise, echo, pitchMod, invertL, invertR;
|
||||||
int vol, outVol;
|
int vol, outVol;
|
||||||
int wtLen;
|
int wtLen;
|
||||||
DivInstrumentSNES state;
|
DivInstrumentSNES state;
|
||||||
|
@ -63,6 +63,7 @@ class DivPlatformSNES: public DivDispatch {
|
||||||
inPorta(false),
|
inPorta(false),
|
||||||
useWave(false),
|
useWave(false),
|
||||||
setPos(false),
|
setPos(false),
|
||||||
|
noise(false),
|
||||||
vol(127),
|
vol(127),
|
||||||
outVol(127),
|
outVol(127),
|
||||||
wtLen(16) {}
|
wtLen(16) {}
|
||||||
|
@ -71,6 +72,7 @@ class DivPlatformSNES: public DivDispatch {
|
||||||
DivDispatchOscBuffer* oscBuf[8];
|
DivDispatchOscBuffer* oscBuf[8];
|
||||||
bool isMuted[8];
|
bool isMuted[8];
|
||||||
signed char globalVolL, globalVolR;
|
signed char globalVolL, globalVolR;
|
||||||
|
unsigned char noiseFreq;
|
||||||
size_t sampleTableBase;
|
size_t sampleTableBase;
|
||||||
|
|
||||||
struct QueuedWrite {
|
struct QueuedWrite {
|
||||||
|
|
|
@ -227,6 +227,10 @@ const char* saaEnvBits[9]={
|
||||||
"mirror", "loop", "cut", "direction", "resolution", "fixed", "N/A","enabled", NULL
|
"mirror", "loop", "cut", "direction", "resolution", "fixed", "N/A","enabled", NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char* snesModeBits[6]={
|
||||||
|
"noise", "echo", "pitch mod", "invert right", "invert left", NULL
|
||||||
|
};
|
||||||
|
|
||||||
const char* filtModeBits[5]={
|
const char* filtModeBits[5]={
|
||||||
"low", "band", "high", "ch3off", NULL
|
"low", "band", "high", "ch3off", NULL
|
||||||
};
|
};
|
||||||
|
@ -4380,9 +4384,12 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
dutyLabel="Noise";
|
dutyLabel="Noise";
|
||||||
dutyMax=ins->amiga.useSample?0:8;
|
dutyMax=ins->amiga.useSample?0:8;
|
||||||
}
|
}
|
||||||
|
if (ins->type==DIV_INS_SNES) {
|
||||||
|
dutyLabel="Noise Freq";
|
||||||
|
dutyMax=31;
|
||||||
|
}
|
||||||
if (ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS ||
|
if (ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS ||
|
||||||
ins->type==DIV_INS_VRC6_SAW || ins->type==DIV_INS_FDS || ins->type==DIV_INS_MULTIPCM ||
|
ins->type==DIV_INS_VRC6_SAW || ins->type==DIV_INS_FDS || ins->type==DIV_INS_MULTIPCM) {
|
||||||
ins->type==DIV_INS_SNES) {
|
|
||||||
dutyMax=0;
|
dutyMax=0;
|
||||||
}
|
}
|
||||||
if (ins->type==DIV_INS_VERA) {
|
if (ins->type==DIV_INS_VERA) {
|
||||||
|
@ -4504,9 +4511,9 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
ex1Max=65535;
|
ex1Max=65535;
|
||||||
ex2Max=65535;
|
ex2Max=65535;
|
||||||
}
|
}
|
||||||
if (ins->type==DIV_INS_SNES && !ins->snes.useEnv) {
|
if (ins->type==DIV_INS_SNES) {
|
||||||
ex1Max=4;
|
ex1Max=5;
|
||||||
ex2Max=31;
|
ex2Max=5;
|
||||||
}
|
}
|
||||||
|
|
||||||
int panMin=0;
|
int panMin=0;
|
||||||
|
@ -4557,6 +4564,10 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
panMax=127;
|
panMax=127;
|
||||||
panSingleNoBit=true;
|
panSingleNoBit=true;
|
||||||
}
|
}
|
||||||
|
if (ins->type==DIV_INS_SNES) {
|
||||||
|
panMin=0;
|
||||||
|
panMax=127;
|
||||||
|
}
|
||||||
if (ins->type==DIV_INS_ES5506) {
|
if (ins->type==DIV_INS_ES5506) {
|
||||||
panMax=65535;
|
panMax=65535;
|
||||||
}
|
}
|
||||||
|
@ -4649,7 +4660,7 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
} else if (ins->type==DIV_INS_QSOUND) {
|
} else if (ins->type==DIV_INS_QSOUND) {
|
||||||
macroList.push_back(FurnaceGUIMacroDesc("Echo Feedback",&ins->std.ex1Macro,0,ex1Max,160,uiColors[GUI_COLOR_MACRO_OTHER]));
|
macroList.push_back(FurnaceGUIMacroDesc("Echo Feedback",&ins->std.ex1Macro,0,ex1Max,160,uiColors[GUI_COLOR_MACRO_OTHER]));
|
||||||
} else if (ins->type==DIV_INS_SNES) {
|
} else if (ins->type==DIV_INS_SNES) {
|
||||||
macroList.push_back(FurnaceGUIMacroDesc("Gain Mode",&ins->std.ex1Macro,0,ex1Max,64,uiColors[GUI_COLOR_MACRO_VOLUME],false,NULL,NULL,false,snesGainModes));
|
macroList.push_back(FurnaceGUIMacroDesc("Special",&ins->std.ex1Macro,0,ex1Max,96,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,snesModeBits));
|
||||||
} else {
|
} else {
|
||||||
macroList.push_back(FurnaceGUIMacroDesc("Duty",&ins->std.ex1Macro,0,ex1Max,160,uiColors[GUI_COLOR_MACRO_OTHER]));
|
macroList.push_back(FurnaceGUIMacroDesc("Duty",&ins->std.ex1Macro,0,ex1Max,160,uiColors[GUI_COLOR_MACRO_OTHER]));
|
||||||
}
|
}
|
||||||
|
@ -4668,7 +4679,7 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
} else if (ins->type==DIV_INS_QSOUND) {
|
} else if (ins->type==DIV_INS_QSOUND) {
|
||||||
macroList.push_back(FurnaceGUIMacroDesc("Echo Length",&ins->std.ex2Macro,0,ex2Max,160,uiColors[GUI_COLOR_MACRO_OTHER]));
|
macroList.push_back(FurnaceGUIMacroDesc("Echo Length",&ins->std.ex2Macro,0,ex2Max,160,uiColors[GUI_COLOR_MACRO_OTHER]));
|
||||||
} else if (ins->type==DIV_INS_SNES) {
|
} else if (ins->type==DIV_INS_SNES) {
|
||||||
macroList.push_back(FurnaceGUIMacroDesc("Gain Rate",&ins->std.ex2Macro,0,ex2Max,160,uiColors[GUI_COLOR_MACRO_VOLUME]));
|
macroList.push_back(FurnaceGUIMacroDesc("Gain Mode",&ins->std.ex2Macro,0,ex2Max,64,uiColors[GUI_COLOR_MACRO_VOLUME],false,NULL,NULL,false,snesGainModes));
|
||||||
} else {
|
} else {
|
||||||
macroList.push_back(FurnaceGUIMacroDesc("Envelope",&ins->std.ex2Macro,0,ex2Max,ex2Bit?64:160,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,ex2Bit,ayEnvBits));
|
macroList.push_back(FurnaceGUIMacroDesc("Envelope",&ins->std.ex2Macro,0,ex2Max,ex2Bit?64:160,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,ex2Bit,ayEnvBits));
|
||||||
}
|
}
|
||||||
|
@ -4708,6 +4719,9 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
macroList.push_back(FurnaceGUIMacroDesc("Envelope mode",&ins->std.ex8Macro,0,2,64,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,es5506EnvelopeModes));
|
macroList.push_back(FurnaceGUIMacroDesc("Envelope mode",&ins->std.ex8Macro,0,2,64,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,es5506EnvelopeModes));
|
||||||
macroList.push_back(FurnaceGUIMacroDesc("Control",&ins->std.algMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,es5506ControlModes));
|
macroList.push_back(FurnaceGUIMacroDesc("Control",&ins->std.algMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,es5506ControlModes));
|
||||||
}
|
}
|
||||||
|
if (ins->type==DIV_INS_SNES) {
|
||||||
|
macroList.push_back(FurnaceGUIMacroDesc("Gain Rate",&ins->std.ex3Macro,0,127,160,uiColors[GUI_COLOR_MACRO_VOLUME]));
|
||||||
|
}
|
||||||
|
|
||||||
drawMacros(macroList);
|
drawMacros(macroList);
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
|
|
Loading…
Reference in a new issue