diff --git a/src/Filter.h b/src/Filter.h index 2bf9f6b..2d5dabc 100644 --- a/src/Filter.h +++ b/src/Filter.h @@ -92,6 +92,10 @@ class Filter bool lp = false; //@} + double leakMixer = 0.001628; // 6581: 0.002531 / 8580: 0.001628 + double leakFilter = 0.001733; // 6581: 0.001688 / 8580: 0.001733 + double leakV3 = 0.0525; // 6581: 0.1125 / 8580: 0.0525 + private: /// Current volume. uint8_t vol = 0; @@ -102,19 +106,13 @@ class Filter /// Selects which inputs to route through filter. uint8_t filt = 0; + private: inline int32_t getNormalizedVoice(Voice& v) const { return fmc.getNormalizedVoice(v.output(), v.envelope()->output()); } - // If voice 3 is off we still need to clock the waveform generator - inline static int32_t getSilentVoice(Voice& v) - { - v.wave()->output(); - return 0; - } - protected: /** * Update filter cutoff frequency. @@ -140,6 +138,12 @@ class Filter virtual int32_t solveIntegrators() = 0; + static inline int32_t signalLeak(int32_t input, double leak) + { + int32_t leaked = static_cast(leak * (1 << 12)); + return ((input-32767) * leaked) >> 12; + } + public: Filter(FilterModelConfig& fmc); @@ -215,16 +219,23 @@ uint16_t Filter::clock(Voice& voice1, Voice& voice2, Voice& voice3) { const int32_t V1 = getNormalizedVoice(voice1); const int32_t V2 = getNormalizedVoice(voice2); - // Voice 3 is silenced by voice3off if it is not routed through the filter. - const int32_t V3 = (filt3 || !voice3off) ? getNormalizedVoice(voice3) : getSilentVoice(voice3); + const int32_t V3 = getNormalizedVoice(voice3); int32_t Vsum = 0; int32_t Vmix = 0; - (filt1 ? Vsum : Vmix) += V1; - (filt2 ? Vsum : Vmix) += V2; - (filt3 ? Vsum : Vmix) += V3; - (filtE ? Vsum : Vmix) += Ve; + Vsum += filt1 ? V1 : signalLeak(V1, leakFilter); + Vmix += filt1 ? signalLeak(V1, leakMixer) : V1; + + Vsum += filt2 ? V2 : signalLeak(V2, leakFilter); + Vmix += filt2 ? signalLeak(V2, leakMixer) : V2; + + Vsum += filt3 ? V3 : signalLeak(V3, leakFilter); + // Voice 3 is silenced by voice3off if it is not routed through the filter. + Vmix += filt3 ? signalLeak(V3, leakMixer) : voice3off ? signalLeak(V3, leakV3) : V3; + + Vsum += filtE ? Ve : signalLeak(Ve, leakFilter); + Vmix += filtE ? signalLeak(Ve, leakMixer) : Ve; Vhp = currentSummer[currentResonance[Vbp] + Vlp + Vsum]; diff --git a/src/Filter6581.cpp b/src/Filter6581.cpp index a09105e..cf48a3f 100644 --- a/src/Filter6581.cpp +++ b/src/Filter6581.cpp @@ -35,9 +35,10 @@ int32_t Filter6581::solveIntegrators() Vlp = bpIntegrator.solve(Vbp); int32_t Vfilt = 0; - if (lp) Vfilt += Vlp; - if (bp) Vfilt += Vbp; - if (hp) Vfilt += Vhp; + + Vfilt += lp ? Vlp : signalLeak(Vlp, leakFilter); + Vfilt += bp ? Vbp : signalLeak(Vbp, leakFilter); + Vfilt += hp ? Vhp : signalLeak(Vhp, leakFilter); // The filter input resistors are slightly bigger than the voice ones // Scale the values accordingly diff --git a/src/Filter8580.cpp b/src/Filter8580.cpp index 64faa3f..2c67c80 100644 --- a/src/Filter8580.cpp +++ b/src/Filter8580.cpp @@ -33,9 +33,10 @@ int32_t Filter8580::solveIntegrators() Vlp = bpIntegrator.solve(Vbp); int32_t Vfilt = 0; - if (lp) Vfilt += Vlp; - if (bp) Vfilt += Vbp; - if (hp) Vfilt += Vhp; + + Vfilt += lp ? Vlp : signalLeak(Vlp, leakFilter); + Vfilt += bp ? Vbp : signalLeak(Vbp, leakFilter); + Vfilt += hp ? Vhp : signalLeak(Vhp, leakFilter); return Vfilt; }