diff --git a/src/engine/platform/snes.cpp b/src/engine/platform/snes.cpp index 4c133ec28..fb36cabdb 100644 --- a/src/engine/platform/snes.cpp +++ b/src/engine/platform/snes.cpp @@ -841,6 +841,8 @@ void DivPlatformSNES::reset() { memcpy(sampleMem,copyOfSampleMem,65536); dsp.init(sampleMem); dsp.set_output(NULL,0); + dsp.setupInterpolation(interpolationOn); + memset(regPool,0,128); // this can't be 0 or channel 1 won't play // this can't be 0x100 either as that's used by SPC700 page 1 and the stack @@ -1023,6 +1025,8 @@ void DivPlatformSNES::setFlags(const DivConfig& flags) { initEchoFIR[7]=flags.getInt("echoFilter7",0); initEchoMask=flags.getInt("echoMask",0); + + interpolationOn=flags.getBool("interpolationOn",true); } int DivPlatformSNES::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { diff --git a/src/engine/platform/snes.h b/src/engine/platform/snes.h index a2eea2853..a1aae9734 100644 --- a/src/engine/platform/snes.h +++ b/src/engine/platform/snes.h @@ -69,6 +69,7 @@ class DivPlatformSNES: public DivDispatch { bool writeEcho; bool writeDryVol; bool echoOn; + bool interpolationOn; bool initEchoOn; signed char initEchoVolL; diff --git a/src/engine/platform/sound/snes/SPC_DSP.cpp b/src/engine/platform/sound/snes/SPC_DSP.cpp index 6ae8275bc..25cddd884 100644 --- a/src/engine/platform/sound/snes/SPC_DSP.cpp +++ b/src/engine/platform/sound/snes/SPC_DSP.cpp @@ -135,24 +135,39 @@ static short const gauss [512] = 1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305, }; +void SPC_DSP::setupInterpolation(bool interpolate) +{ + for(int i = 0; i < voice_count; i++) + { + m.voices[i].interpolate = interpolate; + } +} + inline int SPC_DSP::interpolate( voice_t const* v ) { // Make pointers into gaussian based on fractional position between samples - int offset = v->interp_pos >> 4 & 0xFF; - short const* fwd = gauss + 255 - offset; - short const* rev = gauss + offset; // mirror left half of gaussian + if(v->interpolate) + { + int offset = v->interp_pos >> 4 & 0xFF; + short const* fwd = gauss + 255 - offset; + short const* rev = gauss + offset; // mirror left half of gaussian - int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; - int out; - out = (fwd [ 0] * in [0]) >> 11; - out += (fwd [256] * in [1]) >> 11; - out += (rev [256] * in [2]) >> 11; - out = (int16_t) out; - out += (rev [ 0] * in [3]) >> 11; + int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; + int out; + out = (fwd [ 0] * in [0]) >> 11; + out += (fwd [256] * in [1]) >> 11; + out += (rev [256] * in [2]) >> 11; + out = (int16_t) out; + out += (rev [ 0] * in [3]) >> 11; - CLAMP16( out ); - out &= ~1; - return out; + CLAMP16( out ); + out &= ~1; + return out; + } + else + { + return v->buf [(v->interp_pos >> 12) + v->buf_pos]; //Furnace addition -- no interpolation + } } diff --git a/src/engine/platform/sound/snes/SPC_DSP.h b/src/engine/platform/sound/snes/SPC_DSP.h index 924d9ae2c..6c6ff64ce 100644 --- a/src/engine/platform/sound/snes/SPC_DSP.h +++ b/src/engine/platform/sound/snes/SPC_DSP.h @@ -27,6 +27,9 @@ public: // output buffer could hold. int sample_count() const; + // Furnace addition: disable/enable Gaussian interpolation + void setupInterpolation(bool interpolate); + // Emulation // Resets DSP to power-on state @@ -122,6 +125,7 @@ public: int hidden_env; // used by GAIN mode 7, very obscure quirk uint8_t t_envx_out; sample_t out[2]; // Furnace addition, for per-channel oscilloscope + bool interpolate; // Furnace addition, to disable interpolation }; // Furnace addition, gets a voice diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index f460a5434..6e2b0f7ca 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -1969,6 +1969,8 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl echoFilter[6]=flags.getInt("echoFilter6",0); echoFilter[7]=flags.getInt("echoFilter7",0); + bool interpolationOn=flags.getBool("interpolationOn",true); + ImGui::Text(_("Volume scale:")); if (CWSliderInt(_("Left##VolScaleL"),&vsL,0,127)) { if (vsL<0) vsL=0; @@ -2084,6 +2086,10 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl ImGui::Text(_("sum: %d"),filterSum); ImGui::PopStyleColor(); + if (ImGui::Checkbox(_("Gaussian interpolation"),&interpolationOn)) { + altered=true; + } + if (altered) { e->lockSave([&]() { flags.set("volScaleL",127-vsL); @@ -2102,6 +2108,7 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl flags.set("echoFilter6",echoFilter[6]); flags.set("echoFilter7",echoFilter[7]); flags.set("echoMask",echoMask); + flags.set("interpolationOn",interpolationOn); }); }