mirror of
https://github.com/TomHarte/CLK.git
synced 2026-04-20 10:17:05 +00:00
Add commentary, use filter reconfiguration to retain sample history.
This commit is contained in:
@@ -107,15 +107,14 @@ void SID::update_filter() {
|
||||
case 7: type = Type::AllPass; break;
|
||||
}
|
||||
|
||||
filter_ =
|
||||
SignalProcessing::BiquadFilter(
|
||||
type,
|
||||
1'000'000.0f,
|
||||
30.0f + float(filter_cutoff_.get()) * 5.8f,
|
||||
0.707f + float(filter_resonance_.get()) * 0.125f,
|
||||
6.0f,
|
||||
true
|
||||
);
|
||||
filter_.configure(
|
||||
type,
|
||||
1'000'000.0f,
|
||||
30.0f + float(filter_cutoff_.get()) * 5.8f,
|
||||
0.707f + float(filter_resonance_.get()) * 0.125f,
|
||||
6.0f,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
uint8_t SID::read(const Numeric::SizedInt<5> address) {
|
||||
|
||||
@@ -14,10 +14,18 @@
|
||||
|
||||
namespace SignalProcessing {
|
||||
|
||||
/*!
|
||||
A biquad[ratic] filter approximates the real analogue thing in taking a 1d PCM signal and applying a
|
||||
filter to it as a function of the current input plus the two most-recent inputs plus the two most-recent outputs.
|
||||
|
||||
So both IIR and three-tap FIR filters are degenerate cases of the biquad.
|
||||
|
||||
It is used quite often in real designs, hence an implementation of this filter specifically.
|
||||
|
||||
(And the below is largely textbook; I can't claim any great knowledge)
|
||||
*/
|
||||
class BiquadFilter {
|
||||
public:
|
||||
BiquadFilter() {}
|
||||
|
||||
enum class Type {
|
||||
LowPass,
|
||||
HighPass,
|
||||
@@ -28,6 +36,10 @@ public:
|
||||
LowShelf,
|
||||
HighShelf
|
||||
};
|
||||
|
||||
// Default construction: a filter that produces _nothing_.
|
||||
BiquadFilter() {}
|
||||
|
||||
BiquadFilter(
|
||||
const Type type,
|
||||
const float sample_rate,
|
||||
@@ -35,6 +47,17 @@ public:
|
||||
const float resonance = 0.707f,
|
||||
const float gain = 8,
|
||||
const bool normalise = true
|
||||
) {
|
||||
configure(type, sample_rate, frequency, resonance, gain, normalise);
|
||||
}
|
||||
|
||||
void configure(
|
||||
const Type type,
|
||||
const float sample_rate,
|
||||
const float frequency,
|
||||
const float resonance = 0.707f,
|
||||
const float gain = 8,
|
||||
const bool normalise = true
|
||||
) {
|
||||
const float w0 = 2.0f * std::numbers::pi_v<float> * frequency / sample_rate;
|
||||
const float alpha = std::sin(w0) / (2.0f * resonance);
|
||||
@@ -183,7 +206,8 @@ private:
|
||||
float outputs_[2]{};
|
||||
float coefficients_[5]{};
|
||||
#endif
|
||||
// 0 = b0; 1 = b1; 2 = b2; 3 = a1; 4 = a2
|
||||
// Coefficients indices versus common textbook terms:
|
||||
// 0 = b0; 1 = b1; 2 = b2; 3 = a1; 4 = a2
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user