mirror of https://github.com/probonopd/MiniDexed
parent
1b33d6b94e
commit
fe340f2f99
@ -0,0 +1,108 @@ |
||||
#include "fx_components.h" |
||||
|
||||
#include <cmath> |
||||
|
||||
const float32_t Constants::M2PI = 2.0f * PI; |
||||
const float32_t Constants::M1_PI = 1.0f / PI; |
||||
|
||||
LFO::LFO(float32_t sampling_rate, Waveform waveform, float32_t min_frequency, float32_t max_frequency) : |
||||
FXBase(sampling_rate), |
||||
min_frequency_(min_frequency), |
||||
max_frequency_(max_frequency), |
||||
phase_(0.0f), |
||||
last_sample_(0.0f), |
||||
new_phase_(true), |
||||
rnd_generator_(rnd_device_()), |
||||
rnd_distribution_(-1.0f, 1.0f) |
||||
{ |
||||
this->setWaveform(waveform); |
||||
this->setFrequency(this->min_frequency_); |
||||
} |
||||
|
||||
LFO::~LFO() |
||||
{ |
||||
} |
||||
|
||||
void LFO::setWaveform(Waveform waveform) |
||||
{ |
||||
this->waveform_ = waveform; |
||||
} |
||||
|
||||
LFO::Waveform LFO::getWaveform() const |
||||
{ |
||||
return this->waveform_; |
||||
} |
||||
|
||||
void LFO::setNormalizedFrequency(float32_t normalized_frequency) |
||||
{ |
||||
normalized_frequency = constrain(normalized_frequency, 0.0f, 1.0f); |
||||
if(this->normalized_frequency_ != normalized_frequency) |
||||
{ |
||||
float32_t frequency = mapfloat(normalized_frequency, 0.0f, 1.0f, this->min_frequency_, this->max_frequency_); |
||||
this->normalized_frequency_ = normalized_frequency; |
||||
this->frequency_ = frequency; |
||||
this->phase_increment_ = Constants::M2PI * this->frequency_ / this->getSamplingRate(); |
||||
} |
||||
} |
||||
|
||||
float32_t LFO::getNormalizedFrequency() const |
||||
{ |
||||
return this->frequency_; |
||||
} |
||||
|
||||
void LFO::setFrequency(float32_t frequency) |
||||
{ |
||||
frequency = constrain(frequency, this->min_frequency_, this->max_frequency_); |
||||
if(this->frequency_ != frequency) |
||||
{ |
||||
float32_t normalized_frequency = mapfloat(frequency, this->min_frequency_, this->max_frequency_, 0.0f, 1.0f); |
||||
this->normalized_frequency_ = normalized_frequency; |
||||
this->frequency_ = frequency; |
||||
this->phase_increment_ = Constants::M2PI * this->frequency_ / this->getSamplingRate(); |
||||
} |
||||
} |
||||
|
||||
float32_t LFO::process() |
||||
{ |
||||
float32_t out = 0.0f; |
||||
switch(this->waveform_) |
||||
{ |
||||
case Waveform::Sine: |
||||
out = std::sin(this->phase_); |
||||
break; |
||||
case Waveform::Saw: |
||||
out = Constants::M1_PI * this->phase_ - 1.0f; |
||||
break; |
||||
case Waveform::Square: |
||||
out = this->phase_ < PI ? 1.0 : -1.0; |
||||
break; |
||||
case Waveform::SH: |
||||
if(this->new_phase_) |
||||
{ |
||||
out = this->rnd_distribution_(this->rnd_generator_); |
||||
} |
||||
else |
||||
{ |
||||
out = this->last_sample_; |
||||
} |
||||
break; |
||||
case Waveform::Noise: |
||||
out = this->rnd_distribution_(this->rnd_generator_); |
||||
break; |
||||
} |
||||
|
||||
this->last_sample_ = out; |
||||
|
||||
this->phase_ += this->phase_increment_; |
||||
if(this->phase_ >= Constants::M2PI) |
||||
{ |
||||
this->phase_ -= Constants::M2PI; |
||||
this->new_phase_ = true; |
||||
} |
||||
else |
||||
{ |
||||
this->new_phase_ = false; |
||||
} |
||||
|
||||
return out; |
||||
} |
@ -0,0 +1,109 @@ |
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//
|
||||
// fx_components.h
|
||||
//
|
||||
// Several tools and components used in the implemlentation of FX
|
||||
//
|
||||
#pragma once |
||||
|
||||
#include "fx.h" |
||||
|
||||
#include <random> |
||||
|
||||
struct Constants |
||||
{ |
||||
const static float32_t M2PI; // 2 * PI
|
||||
const static float32_t M1_PI; // 1 / PI
|
||||
}; |
||||
|
||||
class LFO : public FXBase |
||||
{ |
||||
DISALLOW_COPY_AND_ASSIGN(LFO); |
||||
|
||||
public: |
||||
typedef enum { |
||||
Sine, |
||||
Saw, |
||||
Square, |
||||
SH, |
||||
Noise |
||||
} Waveform; |
||||
|
||||
LFO(float32_t sampling_rate, Waveform waveform = Waveform::Sine, float32_t min_frequency = 0.01f, float32_t max_frequency = 10.0f); |
||||
~LFO(); |
||||
|
||||
void setWaveform(Waveform waveform); |
||||
Waveform getWaveform() const; |
||||
|
||||
void setNormalizedFrequency(float32_t normalized_frequency); |
||||
float32_t getNormalizedFrequency() const; |
||||
|
||||
void setFrequency(float32_t frequency); |
||||
float32_t getFrequency() const; |
||||
|
||||
float32_t process(); |
||||
|
||||
private: |
||||
const float32_t min_frequency_; |
||||
const float32_t max_frequency_; |
||||
Waveform waveform_; |
||||
float32_t normalized_frequency_; |
||||
float32_t frequency_; |
||||
float32_t phase_; |
||||
float32_t phase_increment_; |
||||
float32_t last_sample_; |
||||
bool new_phase_; |
||||
std::random_device rnd_device_; |
||||
std::mt19937 rnd_generator_; |
||||
std::uniform_real_distribution<float32_t> rnd_distribution_; |
||||
}; |
||||
|
||||
template<typename T> |
||||
class Buffer |
||||
{ |
||||
DISALLOW_COPY_AND_ASSIGN(Buffer); |
||||
|
||||
public: |
||||
Buffer(unsigned size) : |
||||
size_(size) |
||||
{ |
||||
this->values_ = new T[size]; |
||||
this->reset(); |
||||
} |
||||
|
||||
virtual ~Buffer() |
||||
{ |
||||
delete[] this->values_; |
||||
} |
||||
|
||||
void reset() |
||||
{ |
||||
memset(this->values_, 0, this->size_ * sizeof(T)); |
||||
} |
||||
|
||||
float32_t& operator[](unsigned index) |
||||
{ |
||||
return this->values_[index]; |
||||
} |
||||
|
||||
unsigned getSize() const |
||||
{ |
||||
return this->size_; |
||||
} |
||||
|
||||
private: |
||||
const unsigned size_; |
||||
T* values_; |
||||
}; |
@ -0,0 +1,182 @@ |
||||
#include "fx_svf.h" |
||||
|
||||
#include <cmath> |
||||
|
||||
StateVariableFilter::StateVariableFilter(float32_t sampling_rate, Type type, float32_t cutoff) : |
||||
FXElement(sampling_rate), |
||||
type_(type), |
||||
cutoff_(0.0f) |
||||
{ |
||||
memset(this->z1_, 0, 2 * sizeof(float32_t)); |
||||
memset(this->z2_, 0, 2 * sizeof(float32_t)); |
||||
|
||||
this->setCutoff(cutoff); |
||||
this->setResonance(0.0f); |
||||
} |
||||
|
||||
StateVariableFilter::~StateVariableFilter() |
||||
{ |
||||
} |
||||
|
||||
void StateVariableFilter::setFilterType(Type type) |
||||
{ |
||||
if(this->type_ != type) |
||||
{ |
||||
this->type_ = type; |
||||
this->updateCoefficients(); |
||||
} |
||||
} |
||||
|
||||
void StateVariableFilter::setCutoff(float32_t cutoff) |
||||
{ |
||||
cutoff = constrain(cutoff, 1.0f, this->getSamplingRate() / 2.0f); |
||||
if(this->cutoff_ != cutoff) |
||||
{ |
||||
this->cutoff_ = cutoff; |
||||
this->updateCoefficients(); |
||||
} |
||||
} |
||||
|
||||
void StateVariableFilter::setResonance(float32_t resonance) |
||||
{ |
||||
resonance = constrain(resonance, 0.005f, 1.0f); |
||||
if(this->resonance_ != resonance) |
||||
{ |
||||
this->resonance_ = resonance; |
||||
this->updateCoefficients(); |
||||
} |
||||
} |
||||
|
||||
void StateVariableFilter::setPeakGainDB(float32_t gain) |
||||
{ |
||||
if(this->peak_gain_ != gain) |
||||
{ |
||||
this->peak_gain_ = gain; |
||||
this->updateCoefficients(); |
||||
} |
||||
} |
||||
|
||||
void StateVariableFilter::updateCoefficients() |
||||
{ |
||||
// Compute the filter coefficients based on the current parameter values
|
||||
float32_t w0 = PI * this->cutoff_ / this->getSamplingRate(); |
||||
float32_t V = pow(10, fabs(this->peak_gain_) / 20.0f); |
||||
float32_t K = std::tan(w0); |
||||
float32_t K2 = K * K; |
||||
float32_t norm; |
||||
|
||||
switch(this->type_) |
||||
{ |
||||
case Type::LPF: |
||||
norm = 1.0f / (1.0f + K / this->resonance_ + K2); |
||||
this->a0_ = K2 * norm; |
||||
this->a1_ = 2.0f * this->a0_; |
||||
this->a2_ = this->a0_; |
||||
this->b1_ = 2.0f * (K2 - 1.0f) * norm; |
||||
this->b2_ = (1.0f - K / this->resonance_ + K2) * norm; |
||||
break; |
||||
case Type::HPF: |
||||
norm = 1.0f / (1.0f + K / this->resonance_ + K2); |
||||
this->a0_ = norm; |
||||
this->a1_ = -2.0f * this->a0_; |
||||
this->a2_ = this->a0_; |
||||
this->b1_ = 2.0f * (K2 - 1.0f) * norm; |
||||
this->b2_ = (1.0f - K / this->resonance_ + K2) * norm; |
||||
break; |
||||
case Type::BPF: |
||||
norm = 1.0f / (1.0f + K / this->resonance_ + K2); |
||||
this->a0_ = K / this->resonance_ * norm; |
||||
this->a1_ = 0.0f; |
||||
this->a2_ = -this->a0_; |
||||
this->b1_ = 2.0f * (K2 - 1.0f) * norm; |
||||
this->b2_ = (1.0f - K / this->resonance_ + K2) * norm; |
||||
break; |
||||
case Type::NOTCH: |
||||
norm = 1.0f / (1.0f + K / this->resonance_ + K2); |
||||
this->a0_ = (1.0f + K2) * norm; |
||||
this->a1_ = 2.0f * (K2 - 1.0f) * norm; |
||||
this->a2_ = this->a0_; |
||||
this->b1_ = 2.0f * (K2 - 1.0f) * norm; |
||||
this->b2_ = (1.0f - K / this->resonance_ + K2) * norm; |
||||
break; |
||||
case Type::PEQ: |
||||
if(this->peak_gain_ >= 0)
|
||||
{ |
||||
// boost
|
||||
norm = 1.0f / (1.0f + 1.0f / this->resonance_ * K + K2); |
||||
this->a0_ = (1.0f + V / this->resonance_ * K + K2) * norm; |
||||
this->a1_ = 2.0f * (K2 - 1) * norm; |
||||
this->a2_ = (1.0f - V / this->resonance_ * K + K2) * norm; |
||||
this->b1_ = this->a1_; |
||||
this->b2_ = (1.0f - 1.0f / this->resonance_ * K + K2) * norm; |
||||
} |
||||
else |
||||
{ |
||||
// cut
|
||||
norm = 1.0f / (1 + V / this->resonance_ * K + K2); |
||||
this->a0_ = (1.0f + 1.0f / this->resonance_ * K + K2) * norm; |
||||
this->a1_ = 2.0f * (K2 - 1) * norm; |
||||
this->a2_ = (1.0f - 1.0f / this->resonance_ * K + K2) * norm; |
||||
this->b1_ = this->a1_; |
||||
this->b2_ = (1.0f - V / this->resonance_ * K + K2) * norm; |
||||
} |
||||
break; |
||||
case Type::LSH: |
||||
if(this->peak_gain_ >= 0) |
||||
{
|
||||
// boost
|
||||
norm = 1 / (1 + std::sqrt(2) * K + K2); |
||||
this->a0_ = (1.0f + std::sqrt(2.0f * V) * K + V * K2) * norm; |
||||
this->a1_ = 2.0f * (V * K2 - 1.0f) * norm; |
||||
this->a2_ = (1.0f - std::sqrt(2.0f * V) * K + V * K2) * norm; |
||||
this->b1_ = 2.0f * (K2 - 1.0f) * norm; |
||||
this->b2_ = (1.0f - std::sqrt(2.0f) * K + K2) * norm; |
||||
} |
||||
else |
||||
{
|
||||
// cutK * K
|
||||
norm = 1.0f / (1.0f + std::sqrt(2.0f * V) * K + V * K2); |
||||
this->a0_ = (1.0f + std::sqrt(2.0f) * K + K2) * norm; |
||||
this->a1_ = 2.0f * (K2 - 1.0f) * norm; |
||||
this->a2_ = (1.0f - std::sqrt(2.0f) * K + K2) * norm; |
||||
this->b1_ = 2.0f * (V * K2 - 1.0f) * norm; |
||||
this->b2_ = (1.0f - std::sqrt(2.0f * V) * K + V * K2) * norm; |
||||
} |
||||
break; |
||||
case Type::HSH: |
||||
if(this->peak_gain_ >= 0) |
||||
{ |
||||
// boost
|
||||
norm = 1.0f / (1.0f + std::sqrt(2.0f) * K + K2); |
||||
this->a0_ = (V + std::sqrt(2.0f * V) * K + K2) * norm; |
||||
this->a1_ = 2.0f * (K2 - V) * norm; |
||||
this->a2_ = (V - std::sqrt(2.0f * V) * K + K2) * norm; |
||||
this->b1_ = 2.0f * (K2 - 1.0f) * norm; |
||||
this->b2_ = (1.0f - std::sqrt(2.0f) * K + K2) * norm; |
||||
} |
||||
else |
||||
{ |
||||
// cut
|
||||
norm = 1.0f / (V + std::sqrt(2.0f * V) * K + K2); |
||||
this->a0_ = (1.0f + std::sqrt(2.0f) * K + K2) * norm; |
||||
this->a1_ = 2.0f * (K2 - 1.0f) * norm; |
||||
this->a2_ = (1.0f - std::sqrt(2.0f) * K + K2) * norm; |
||||
this->b1_ = 2.0f * (K2 - V) * norm; |
||||
this->b2_ = (V - std::sqrt(2.0f * V) * K + K2) * norm; |
||||
} |
||||
break;
|
||||
} |
||||
} |
||||
|
||||
void StateVariableFilter::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) |
||||
{ |
||||
const float32_t gain = 10.0f; |
||||
|
||||
outL = (inL * this->a0_ + this->z1_[0]) * gain; |
||||
this->z1_[0] = inL * this->a1_ + this->z2_[0] - this->b1_ * outL; |
||||
this->z2_[0] = inL * this->a2_ - this->b2_ * outL; |
||||
|
||||
outR = (inR * this->a0_ + this->z1_[1]) * gain; |
||||
this->z1_[0] = inR * this->a1_ + this->z2_[1] - this->b1_ * outR; |
||||
this->z2_[0] = inR * this->a2_ - this->b2_ * outR; |
||||
} |
@ -0,0 +1,63 @@ |
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
//
|
||||
// fx_svf.h
|
||||
//
|
||||
// State Variable Filter used in Tape Delay
|
||||
//
|
||||
|
||||
#include "fx.h" |
||||
|
||||
class StateVariableFilter : public FXElement |
||||
{ |
||||
DISALLOW_COPY_AND_ASSIGN(StateVariableFilter); |
||||
|
||||
public: |
||||
typedef enum |
||||
{ |
||||
LPF, // Low pass filter
|
||||
HPF, // High pass filter
|
||||
BPF, // Band pass filter
|
||||
NOTCH, // Notch Filter
|
||||
PEQ, // Peaking band EQ filter
|
||||
LSH, // Low shelf filter
|
||||
HSH // High shelf filter
|
||||
} Type; |
||||
|
||||
StateVariableFilter(float32_t sampling_rate, Type type, float32_t cutoff); |
||||
virtual ~StateVariableFilter(); |
||||
|
||||
void setFilterType(Type type); |
||||
void setCutoff(float32_t cutoff); |
||||
void setResonance(float32_t resonance); |
||||
void setPeakGainDB(float32_t gainDB); |
||||
|
||||
virtual void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) override; |
||||
|
||||
private: |
||||
void updateCoefficients(); |
||||
|
||||
Type type_; |
||||
float32_t cutoff_; |
||||
float32_t resonance_; |
||||
float32_t peak_gain_; |
||||
float32_t a0_; |
||||
float32_t a1_; |
||||
float32_t a2_; |
||||
float32_t b1_; |
||||
float32_t b2_; |
||||
float32_t z1_[2]; |
||||
float32_t z2_[2]; |
||||
}; |
Loading…
Reference in new issue