#include "fx_delay.h" #include #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 Delay::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); } Delay::LowHighPassFilter::~LowHighPassFilter() { } void Delay::LowHighPassFilter::setCutoffChangeRatio(float32_t ratio) { ratio += 1.0f; this->lpf_.setCutoff(LPF_CUTOFF_REF * ratio); this->hpf_.setCutoff(HPF_CUTOFF_REF * ratio); } void Delay::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); } Delay::Delay(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) { 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->setFeedbak(default_feedback_level); } Delay::~Delay() { delete[] this->buffer_L_; delete[] this->buffer_R_; } void Delay::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) { float32_t delay_time_L = (MAX_DELAY_TIME * this->getLeftDelayTime() ) * this->getSamplingRate(); float32_t delay_time_R = (MAX_DELAY_TIME * this->getRightDelayTime()) * this->getSamplingRate(); // Calculate write positions unsigned write_pos_L = static_cast(this->MaxSampleDelayTime + this->read_pos_L_ + delay_time_L) % this->MaxSampleDelayTime; unsigned write_pos_R = static_cast(this->MaxSampleDelayTime + this->read_pos_R_ + 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 Delay::setLeftDelayTime(float32_t delay_time) { this->delay_time_L_ = constrain(delay_time, 0.0f, 1.0f); } float32_t Delay::getLeftDelayTime() const { return this->delay_time_L_; } void Delay::setRightDelayTime(float32_t delay_time) { this->delay_time_R_ = constrain(delay_time, 0.0f, 1.0f); } float32_t Delay::getRightDelayTime() const { return this->delay_time_R_; } void Delay::setFeedbak(float32_t feedback) { this->feedback_ = constrain(feedback, 0.0, 1.0); } float32_t Delay::getFeedbackLevel() const { return this->feedback_; }