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