Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions src/Filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -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<int32_t>(leak * (1 << 12));
return ((input-32767) * leaked) >> 12;
}

public:
Filter(FilterModelConfig& fmc);

Expand Down Expand Up @@ -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];

Expand Down
7 changes: 4 additions & 3 deletions src/Filter6581.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 4 additions & 3 deletions src/Filter8580.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Loading