mirror of https://github.com/probonopd/MiniDexed
parent
8227a3abe1
commit
d0fe01f652
@ -1,153 +0,0 @@ |
||||
#include "fx_tape_delay.h" |
||||
|
||||
#include <cmath> |
||||
|
||||
#define MAX_DELAY_TIME 1.0f |
||||
#define MAX_FLUTTER_DELAY_TIME 0.01f |
||||
|
||||
#define LPF_CUTOFF_REF 14000.0f |
||||
#define HPF_CUTOFF_REF 60.0f |
||||
|
||||
TapeDelay::LowHighPassFilter::LowHighPassFilter(float32_t sampling_rate) : |
||||
FXElement(sampling_rate), |
||||
lpf_(sampling_rate, StateVariableFilter::Type::LPF, LPF_CUTOFF_REF), |
||||
hpf_(sampling_rate, StateVariableFilter::Type::HPF, HPF_CUTOFF_REF) |
||||
{ |
||||
this->setCutoffChangeRatio(0.0f); |
||||
} |
||||
|
||||
TapeDelay::LowHighPassFilter::~LowHighPassFilter() |
||||
{ |
||||
} |
||||
|
||||
void TapeDelay::LowHighPassFilter::setCutoffChangeRatio(float32_t ratio) |
||||
{ |
||||
ratio += 1.0f; |
||||
|
||||
this->lpf_.setCutoff(LPF_CUTOFF_REF * ratio); |
||||
this->hpf_.setCutoff(HPF_CUTOFF_REF * ratio); |
||||
} |
||||
|
||||
void TapeDelay::LowHighPassFilter::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) |
||||
{ |
||||
this->lpf_.processSample(inL, inR, outL, outR); |
||||
this->hpf_.processSample(outL, outR, outL, outR); |
||||
} |
||||
|
||||
TapeDelay::TapeDelay(const float32_t sampling_rate, float32_t default_delay_time, float32_t default_flutter_level, float32_t default_feedback_level) : |
||||
FXElement(sampling_rate), |
||||
MaxSampleDelayTime((MAX_DELAY_TIME + MAX_FLUTTER_DELAY_TIME) * sampling_rate * MAX_DELAY_TIME), |
||||
read_pos_L_(0), |
||||
read_pos_R_(0), |
||||
filter_(sampling_rate), |
||||
jitter_generator_(sampling_rate) |
||||
{ |
||||
this->buffer_L_ = new float32_t[this->MaxSampleDelayTime]; |
||||
this->buffer_R_ = new float32_t[this->MaxSampleDelayTime]; |
||||
|
||||
memset(this->buffer_L_, 0, this->MaxSampleDelayTime * sizeof(float32_t)); |
||||
memset(this->buffer_R_, 0, this->MaxSampleDelayTime * sizeof(float32_t)); |
||||
|
||||
this->setLeftDelayTime(default_delay_time); |
||||
this->setRightDelayTime(default_delay_time); |
||||
this->setFlutterLevel(default_flutter_level); |
||||
this->setFeedbak(default_feedback_level); |
||||
} |
||||
|
||||
TapeDelay::~TapeDelay() |
||||
{ |
||||
delete[] this->buffer_L_; |
||||
delete[] this->buffer_R_; |
||||
} |
||||
|
||||
void TapeDelay::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) |
||||
{ |
||||
// Calculate the fluttered delay time
|
||||
float32_t fluttered_delay_time = this->getFlutteredDelayTime(); |
||||
this->filter_.setCutoffChangeRatio(fluttered_delay_time); |
||||
|
||||
float32_t fluttered_delay_time_L = (MAX_DELAY_TIME * this->getLeftDelayTime() * (1.0f + fluttered_delay_time)) * this->getSamplingRate(); |
||||
float32_t fluttered_delay_time_R = (MAX_DELAY_TIME * this->getRightDelayTime() * (1.0f + fluttered_delay_time)) * this->getSamplingRate(); |
||||
|
||||
// Calculate write positions
|
||||
unsigned write_pos_L = static_cast<unsigned>(this->MaxSampleDelayTime + this->read_pos_L_ + fluttered_delay_time_L) % this->MaxSampleDelayTime; |
||||
unsigned write_pos_R = static_cast<unsigned>(this->MaxSampleDelayTime + this->read_pos_R_ + fluttered_delay_time_R) % this->MaxSampleDelayTime; |
||||
|
||||
// Write input to delay buffers
|
||||
this->buffer_L_[write_pos_L] = inL; |
||||
this->buffer_R_[write_pos_R] = inR; |
||||
|
||||
// Read from delay buffers and apply feedback
|
||||
this->filter_.processSample( |
||||
this->buffer_L_[this->read_pos_L_], |
||||
this->buffer_R_[this->read_pos_R_], |
||||
outL, |
||||
outR |
||||
); |
||||
|
||||
this->buffer_L_[write_pos_L] += outL * this->getFeedbackLevel(); |
||||
this->buffer_R_[write_pos_R] += outR * this->getFeedbackLevel(); |
||||
|
||||
// Increment read positions
|
||||
++this->read_pos_L_; |
||||
if(this->read_pos_L_ >= this->MaxSampleDelayTime) |
||||
{ |
||||
this->read_pos_L_ -= this->MaxSampleDelayTime; |
||||
} |
||||
++this->read_pos_R_; |
||||
if(this->read_pos_R_ >= this->MaxSampleDelayTime) |
||||
{ |
||||
this->read_pos_R_ -= this->MaxSampleDelayTime; |
||||
} |
||||
} |
||||
|
||||
void TapeDelay::setLeftDelayTime(float32_t delay_time) |
||||
{ |
||||
this->delay_time_L_ = constrain(delay_time, 0.0f, 1.0f); |
||||
} |
||||
|
||||
float32_t TapeDelay::getLeftDelayTime() const |
||||
{ |
||||
return this->delay_time_L_; |
||||
} |
||||
|
||||
void TapeDelay::setRightDelayTime(float32_t delay_time) |
||||
{ |
||||
this->delay_time_R_ = constrain(delay_time, 0.0f, 1.0f); |
||||
} |
||||
|
||||
float32_t TapeDelay::getRightDelayTime() const |
||||
{ |
||||
return this->delay_time_R_; |
||||
} |
||||
|
||||
void TapeDelay::setFlutterLevel(float32_t flutter_level) |
||||
{ |
||||
this->flutter_level_ = constrain(flutter_level, 0.0f, 1.0f); |
||||
this->jitter_generator_.setSpeed(0.2f * (1.0f - this->flutter_level_)); |
||||
this->jitter_generator_.setMagnitude(this->flutter_level_ / 100.0f); |
||||
} |
||||
|
||||
float32_t TapeDelay::getFlutterLevel() const |
||||
{ |
||||
return this->flutter_level_; |
||||
} |
||||
|
||||
void TapeDelay::setFeedbak(float32_t feedback) |
||||
{ |
||||
this->feedback_ = constrain(feedback, 0.0, 1.0); |
||||
} |
||||
|
||||
float32_t TapeDelay::getFeedbackLevel() const |
||||
{ |
||||
return this->feedback_; |
||||
} |
||||
|
||||
float32_t TapeDelay::getFlutteredDelayTime() |
||||
{ |
||||
// Genarate a random number in the range [-1.0 , 1.0]
|
||||
float32_t r = this->jitter_generator_.process(); |
||||
|
||||
// Scale and bias the random number to the desired flutter range
|
||||
return MAX_FLUTTER_DELAY_TIME * r * this->getFlutterLevel(); |
||||
} |
Loading…
Reference in new issue