feat: change to an SVF filter design
This commit is contained in:
parent
821f3d7d65
commit
a80c6276a8
2 changed files with 106 additions and 53 deletions
109
core/Filter.cpp
109
core/Filter.cpp
|
|
@ -1,49 +1,90 @@
|
|||
#include "Filter.hpp"
|
||||
#include <cmath>
|
||||
|
||||
Filter::Filter(float initCutOff, float initSampleRate)
|
||||
: cutOff_(initCutOff), feedback_(0.0f), alpha_(0.0f),
|
||||
sampleRate_(initSampleRate), zL_(0.0f), zR_(0.0f) {
|
||||
recompute();
|
||||
};
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
void Filter::process(const float *in, float *out, uint32_t frames) {
|
||||
filter(in, out, frames, &zL_);
|
||||
};
|
||||
void Filter::processStereo(const float *inLeft, const float *inRight,
|
||||
float *outLeft, float *outRight, uint32_t frames) {
|
||||
filter(inLeft, outLeft, frames, &zL_);
|
||||
filter(inRight, outRight, frames, &zR_);
|
||||
};
|
||||
Filter::Filter(float initCutOff, float initQ, float initSampleRate)
|
||||
: cutOff_(initCutOff), q_(initQ), sampleRate_(initSampleRate),
|
||||
type_(kLowPass), g_(0.0f), lpL_(0.0f), bpL_(0.0f), lpR_(0.0f),
|
||||
bpR_(0.0f) {
|
||||
updateCoeffs();
|
||||
}
|
||||
|
||||
void Filter::filter(const float *in, float *out, uint32_t frames, float *z) {
|
||||
for (uint32_t i = 0; i < frames; ++i) {
|
||||
float feedbackInput = in[i] + (feedback_ * (*z));
|
||||
*z = *z + alpha_ * (feedbackInput - *z);
|
||||
out[i] = *z;
|
||||
Filter::FilterType Filter::getType() const { return type_; }
|
||||
|
||||
void Filter::updateCoeffs() {
|
||||
float f = cutOff_ / std::fmax(sampleRate_, 1.0f);
|
||||
if (f > kMaxNormalizedFrequency)
|
||||
f = kMaxNormalizedFrequency;
|
||||
g_ = 2.0f * std::sin(M_PI * f);
|
||||
}
|
||||
|
||||
float Filter::processFrame(float input, float &lp, float &bp) const {
|
||||
|
||||
float hp = input - (bp / q_) - lp;
|
||||
|
||||
bp = bp + g_ * hp;
|
||||
lp = lp + g_ * bp;
|
||||
|
||||
switch (type_) {
|
||||
case kHighPass:
|
||||
return hp;
|
||||
case kBandPass:
|
||||
return bp;
|
||||
case kNotch:
|
||||
return input - lp;
|
||||
case kLowPass:
|
||||
default:
|
||||
return lp;
|
||||
}
|
||||
}
|
||||
|
||||
void Filter::recompute() {
|
||||
float fc = std::fmax(cutOff_, 1.0f);
|
||||
float rc = 1.0f / (2.0f * M_PI * fc);
|
||||
float val = 1.0f - std::exp(-1.0f / (rc * sampleRate_));
|
||||
alpha_ = std::fmin(val, 0.999f);
|
||||
};
|
||||
void Filter::process(const float *in, float *out, uint32_t frames) {
|
||||
float lp = lpL_;
|
||||
float bp = bpL_;
|
||||
|
||||
void Filter::setCutOff(float newCutOff) {
|
||||
cutOff_ = newCutOff;
|
||||
recompute();
|
||||
for (uint32_t i = 0; i < frames; ++i) {
|
||||
out[i] = processFrame(in[i], lp, bp);
|
||||
}
|
||||
|
||||
lpL_ = lp;
|
||||
bpL_ = bp;
|
||||
}
|
||||
|
||||
void Filter::processStereo(const float *inL, const float *inR, float *outL,
|
||||
float *outR, uint32_t frames) {
|
||||
float lpL = lpL_, bpL = bpL_;
|
||||
float lpR = lpR_, bpR = bpR_;
|
||||
|
||||
for (uint32_t i = 0; i < frames; ++i) {
|
||||
outL[i] = processFrame(inL[i], lpL, bpL);
|
||||
outR[i] = processFrame(inR[i], lpR, bpR);
|
||||
}
|
||||
|
||||
lpL_ = lpL;
|
||||
bpL_ = bpL;
|
||||
lpR_ = lpR;
|
||||
bpR_ = bpR;
|
||||
}
|
||||
|
||||
float Filter::getCutOff() const { return cutOff_; }
|
||||
|
||||
void Filter::setFeedback(float newFeedback) {
|
||||
feedback_ = std::fmin(std::fmax(newFeedback, 0.0f), 0.99f);
|
||||
void Filter::setCutOff(float freq) {
|
||||
cutOff_ = std::fmax(freq, 1.0f);
|
||||
updateCoeffs();
|
||||
}
|
||||
float Filter::getFeedback() const { return feedback_; }
|
||||
|
||||
void Filter::setSampleRate(float newSampleRate) {
|
||||
sampleRate_ = newSampleRate;
|
||||
recompute();
|
||||
float Filter::getQ() const { return q_; }
|
||||
void Filter::setQ(float q) {
|
||||
q_ = std::fmax(q, 0.1f);
|
||||
updateCoeffs();
|
||||
}
|
||||
|
||||
void Filter::setType(FilterType type) { type_ = type; }
|
||||
|
||||
float Filter::getSampleRate() const { return sampleRate_; }
|
||||
void Filter::setSampleRate(float sr) {
|
||||
sampleRate_ = sr;
|
||||
updateCoeffs();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,45 @@
|
|||
#ifndef FILTER_HPP_INCLUDED
|
||||
#define FILTER_HPP_INCLUDED
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
constexpr float kMaxNormalizedFrequency = 0.16667f;
|
||||
|
||||
class Filter {
|
||||
public:
|
||||
Filter(float initCutOff = 1.0f, float initSampleRate = 48000.0f);
|
||||
void process(const float *in, float *out, uint32_t frames);
|
||||
void processStereo(const float *inLeft, const float *inRight, float *outLeft,
|
||||
float *outRight, uint32_t frames);
|
||||
Filter(float initCutOff = 1000.0f, float initQ = 0.707f,
|
||||
float initSampleRate = 48000.0f);
|
||||
|
||||
enum FilterType { kLowPass, kHighPass, kBandPass, kNotch, kFilterTypeCount };
|
||||
|
||||
void setCutOff(float freq);
|
||||
void setQ(float q);
|
||||
void setSampleRate(float sr);
|
||||
void setType(FilterType type);
|
||||
|
||||
void recompute();
|
||||
void setCutOff(float newCutOff);
|
||||
float getCutOff() const;
|
||||
void setFeedback(float newFeedback);
|
||||
float getFeedback() const;
|
||||
void setSampleRate(float newSampleRate);
|
||||
float getQ() const;
|
||||
float getSampleRate() const;
|
||||
FilterType getType() const;
|
||||
|
||||
void process(const float *in, float *out, uint32_t frames);
|
||||
void processStereo(const float *inL, const float *inR, float *outL,
|
||||
float *outR, uint32_t frames);
|
||||
|
||||
private:
|
||||
void filter(const float *in, float *out, uint32_t frames, float *z);
|
||||
void updateCoeffs();
|
||||
|
||||
float processFrame(float input, float &lp, float &bp) const;
|
||||
|
||||
float cutOff_;
|
||||
float feedback_;
|
||||
float alpha_;
|
||||
float q_;
|
||||
float sampleRate_;
|
||||
float zL_;
|
||||
float zR_;
|
||||
FilterType type_;
|
||||
|
||||
float g_;
|
||||
|
||||
float lpL_, bpL_;
|
||||
float lpR_, bpR_;
|
||||
};
|
||||
|
||||
#endif // FILTER_HPP_INCLUDED
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue