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
40 changes: 0 additions & 40 deletions src/Filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,49 +27,9 @@
namespace reSIDfp
{

static constexpr int summerIdx[5] =
{
FilterModelConfig::summer_offset<0>::value,
FilterModelConfig::summer_offset<1>::value,
FilterModelConfig::summer_offset<2>::value,
FilterModelConfig::summer_offset<3>::value,
FilterModelConfig::summer_offset<4>::value
};

static constexpr int mixerIdx[8] =
{
FilterModelConfig::mixer_offset<0>::value,
FilterModelConfig::mixer_offset<1>::value,
FilterModelConfig::mixer_offset<2>::value,
FilterModelConfig::mixer_offset<3>::value,
FilterModelConfig::mixer_offset<4>::value,
FilterModelConfig::mixer_offset<5>::value,
FilterModelConfig::mixer_offset<6>::value,
FilterModelConfig::mixer_offset<7>::value
};

void Filter::updateMixing()
{
currentVolume = volume + (vol * (1<<16));

int Nsum = 0;
int Nmix = 0;

(filt1 ? Nsum : Nmix)++;
(filt2 ? Nsum : Nmix)++;

if (filt3) Nsum++;
else if (!voice3off) Nmix++;

(filtE ? Nsum : Nmix)++;

currentSummer = summer + summerIdx[Nsum];

if (lp) Nmix++;
if (bp) Nmix++;
if (hp) Nmix++;

currentMixer = mixer + mixerIdx[Nmix];
}

void Filter::writeFC_LO(uint8_t fc_lo)
Expand Down
60 changes: 32 additions & 28 deletions src/Filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,6 @@ class Filter

const Integrator& m_bpIntegrator;

/// Current filter/voice mixer setting.
uint16_t* currentMixer = nullptr;

/// Filter input summer setting.
uint16_t* currentSummer = nullptr;

/// Filter resonance value.
uint16_t* currentResonance = nullptr;

Expand Down Expand Up @@ -106,6 +100,17 @@ class Filter
/// Selects which inputs to route through filter.
uint8_t filt = 0;

private:
inline int32_t getNormalizedVoice(float v, uint8_t env) const
{
return m_fmc.getNormalizedVoice(v, env);
}

inline int32_t getNormalizedScaledVoice(float v, uint8_t env, float scale) const
{
return m_fmc.getNormalizedVoice(v*scale, env);
}

protected:
/**
* Update filter cutoff frequency.
Expand All @@ -131,12 +136,11 @@ class Filter

virtual void restartIntegrators() = 0;

inline int32_t getNormalizedVoice(float v, uint8_t env) const
{
return m_fmc.getNormalizedVoice(v, env);
}
virtual float toFilterScale() const = 0;

virtual float toMixerScale(bool filter) const = 0;

virtual int32_t getNormalizedMixerVoice(float v, uint8_t env) const = 0;
virtual float voice3OffScale() const = 0;

public:
Filter(const FilterModelConfig& fmc,
Expand Down Expand Up @@ -227,33 +231,33 @@ uint16_t Filter::clock(Voice& voice1, Voice& voice2, Voice& voice3)

// Voltage summer for filter input
int32_t Vsum = 0;
Vsum += filt1 ? getNormalizedVoice(wav1, env1) : 0;
Vsum += filt2 ? getNormalizedVoice(wav2, env2) : 0;
Vsum += filt3 ? getNormalizedVoice(wav3, env3) : 0;
Vsum += filtE ? getNormalizedVoice(extin, 0) : 0;
Vsum += filt1 ? getNormalizedVoice(wav1, env1) : getNormalizedScaledVoice(wav1, env1, toFilterScale());
Vsum += filt2 ? getNormalizedVoice(wav2, env2) : getNormalizedScaledVoice(wav2, env2, toFilterScale());
Vsum += filt3 ? getNormalizedVoice(wav3, env3) : getNormalizedScaledVoice(wav3, env3, toFilterScale());
Vsum += filtE ? getNormalizedVoice(extin, 0) : getNormalizedScaledVoice(extin, 0, toFilterScale());
Vsum += Vlp;
Vsum += currentResonance[Vbp];

// Filter
Vhp = currentSummer[Vsum];
Vhp = summer[Vsum];
Vbp = m_hpIntegrator.solve(Vhp);
Vlp = m_bpIntegrator.solve(Vbp);

int32_t Vfilt = 0;
if (lp) Vfilt += Vlp;
if (bp) Vfilt += Vbp;
if (hp) Vfilt += Vhp;
// Voice 3 is silenced by voice3off if it is not routed through the filter.
const float v3Scale = voice3off ? voice3OffScale() : 1.f;

// Voltage summer for mixer input
int32_t Vmix = 0;
Vmix += filt1 ? 0 : getNormalizedMixerVoice(wav1, env1);
Vmix += filt2 ? 0 : getNormalizedMixerVoice(wav2, env2);
// Voice 3 is silenced by voice3off if it is not routed through the filter
Vmix += (filt3 || voice3off) ? 0 : getNormalizedMixerVoice(wav3, env3);
Vmix += filtE ? 0 : getNormalizedMixerVoice(extin, 0);
Vmix += Vfilt;

return currentVolume[currentMixer[Vmix]];
Vmix += getNormalizedScaledVoice(wav1, env1, toMixerScale(filt1));
Vmix += getNormalizedScaledVoice(wav2, env2, toMixerScale(filt2));
Vmix += getNormalizedScaledVoice(wav3, env3, toMixerScale(filt3) * v3Scale);
Vmix += getNormalizedScaledVoice(extin, 0, toMixerScale(filtE));
// FIXME
Vmix += lp ? Vlp : 32768;
Vmix += bp ? Vbp : 32768;
Vmix += hp ? Vhp : 32768;

return currentVolume[mixer[Vmix]];
}

} // namespace reSIDfp
Expand Down
12 changes: 6 additions & 6 deletions src/Filter6581.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,15 +338,15 @@ class Filter6581 final : public Filter

void restartIntegrators() override { hpIntegrator.restart(); bpIntegrator.restart(); }

/*
* The filter input resistors on the 6581 are slightly bigger than the voice ones,
* scale the values accordingly.
*/
int32_t getNormalizedMixerVoice(float v, uint8_t env) const override
constexpr float toFilterScale() const override { return 0.05625f * 0.03f; }

constexpr float toMixerScale(bool filter) const override
{
return getNormalizedVoice(v * static_cast<float>(FilterModelConfig6581::VF_TR_RATIO), env);
return filter ? 0.05625f * 0.045f : static_cast<float>(FilterModelConfig6581::VF_TR_RATIO);
}

constexpr float voice3OffScale() const override { return 0.05625f * 2.f; }

public:
Filter6581() :
Filter(*FilterModelConfig6581::getInstance(), hpIntegrator, bpIntegrator),
Expand Down
8 changes: 6 additions & 2 deletions src/Filter8580.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,11 +295,15 @@ class Filter8580 final : public Filter

void restartIntegrators() override { hpIntegrator.restart(); bpIntegrator.restart(); }

int32_t getNormalizedMixerVoice(float v, uint8_t env) const override
constexpr float toFilterScale() const override { return 0.02625f * 0.03f; }

constexpr float toMixerScale(bool filter) const override
{
return getNormalizedVoice(v, env);
return filter ? 0.02625f * 0.045f : 1.f;
}

constexpr float voice3OffScale() const override { return 0.02625f * 2.f; }

public:
Filter8580() :
Filter(*FilterModelConfig8580::getInstance(), hpIntegrator, bpIntegrator),
Expand Down
4 changes: 2 additions & 2 deletions src/FilterModelConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ FilterModelConfig::FilterModelConfig(
norm(1.0 / denorm),
N16(norm * UINT16_MAX),
voice_voltage_range(vvr),
mixer(new uint16_t[mixer_offset<8>::value]),
summer(new uint16_t[summer_offset<5>::value]),
mixer(new uint16_t[7 << 16]),
summer(new uint16_t[6 << 16]),
volume(new uint16_t[16 * (1 << 16)]),
resonance(new uint16_t[16 * (1 << 16)])
{
Expand Down
50 changes: 20 additions & 30 deletions src/FilterModelConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,7 @@ class FilterModelConfig
virtual double getVoiceDC(uint8_t env) const = 0;

/**
* The filter summer operates at n ~ 1, and has 5 fundamentally different
* input configurations (2 - 6 input "resistors").
* The filter summer operates at n ~ 1, and has 6 input "resistors".
*
* Note that all "on" transistors are modeled as one. This is not
* entirely accurate, since the input for each transistor is different,
Expand All @@ -185,27 +184,22 @@ class FilterModelConfig
{
const double r_N16 = 1. / N16;

int idx = 0;
for (int i = 0; i < 5; i++)
{
const int idiv = 2 + i; // 2 - 6 input "resistors".
const int size = idiv << 16;
const double n = idiv;
const double r_idiv = 1. / idiv;
opampModel.reset();
constexpr int idiv = 6;
constexpr int size = idiv << 16;
const double n = idiv;
constexpr double r_idiv = 1. / idiv;
opampModel.reset();

for (int vi = 0; vi < size; vi++)
{
const double vin = vmin + vi * r_N16 * r_idiv; /* vmin .. vmax */
summer[idx++] = getNormalizedValue(opampModel.solve(n, vin));
}
for (int vi = 0; vi < size; vi++)
{
const double vin = vmin + vi * r_N16 * r_idiv; /* vmin .. vmax */
summer[vi] = getNormalizedValue(opampModel.solve(n, vin));
}
}

/**
* The audio mixer operates at n ~ 8/6 (6581) or 8/5 (8580),
* and has 8 fundamentally different input configurations
* (0 - 7 input "resistors").
* and has 7 input "resistors".
*
* All "on", transistors are modeled as one - see comments above for
* the filter summer.
Expand All @@ -214,20 +208,16 @@ class FilterModelConfig
{
const double r_N16 = 1. / N16;

int idx = 0;
for (int i = 0; i < 8; i++)
{
const int idiv = (i == 0) ? 1 : i;
const int size = (i == 0) ? 1 : i << 16;
const double n = i * nRatio;
const double r_idiv = 1. / idiv;
opampModel.reset();
constexpr int idiv = 7;
constexpr int size = idiv << 16;
const double n = idiv * nRatio;
constexpr double r_idiv = 1. / idiv;
opampModel.reset();

for (int vi = 0; vi < size; vi++)
{
const double vin = vmin + vi * r_N16 * r_idiv; /* vmin .. vmax */
mixer[idx++] = getNormalizedValue(opampModel.solve(n, vin));
}
for (int vi = 0; vi < size; vi++)
{
const double vin = vmin + vi * r_N16 * r_idiv; /* vmin .. vmax */
mixer[vi] = getNormalizedValue(opampModel.solve(n, vin));
}
}

Expand Down
Loading