FX fixes + optimizations + prepare for FX2 release

pull/409/head
abscisys 2 years ago
parent 20419bb077
commit 4c502ddd0c
  1. 1
      .gitignore
  2. 36
      src/Makefile
  3. 4
      src/fx.h
  4. 10
      src/fx_chorus.cpp
  5. 75
      src/fx_components.cpp
  6. 42
      src/fx_components.h
  7. 6
      src/fx_delay.cpp
  8. 9
      src/fx_engine.hpp
  9. 6
      src/fx_flanger.cpp
  10. 14
      src/fx_orbitone.cpp
  11. 6
      src/fx_phaser.cpp
  12. 10
      src/fx_rack.cpp
  13. 10
      src/fx_rack.h
  14. 26
      src/fx_reverberator.cpp
  15. 123
      src/fx_reverberator.h
  16. 65
      src/fx_shimmer_reverb.h
  17. 28
      src/fx_svf.cpp
  18. 248
      src/fx_svf.h
  19. 12
      src/minidexed.cpp
  20. 25
      src/test/Makefile
  21. 2
      src/test/cppcheck-suppression-list.txt
  22. 16
      src/test/test_cpp_performance.cpp
  23. 8
      src/test/test_fxLevelTuning.cpp
  24. 6
      src/test/test_fx_components.cpp
  25. 4
      src/test/test_fx_helper.cpp
  26. 2
      src/test/test_fx_helper.h
  27. 18
      src/test/test_fx_rack.cpp
  28. 74
      src/test/test_fx_reverberator.cpp
  29. 18
      src/test/test_unitFXTuning.cpp

1
.gitignore vendored

@ -49,5 +49,6 @@ sdcard
# temporary tests
src/test/*.bin
src/test/bin
src/test/results
src/test/objects

@ -6,14 +6,34 @@ CIRCLE_STDLIB_DIR = ../circle-stdlib
SYNTH_DEXED_DIR = ../Synth_Dexed/src
CMSIS_DIR = ../CMSIS_5/CMSIS
OBJS = main.o kernel.o minidexed.o config.o userinterface.o uimenu.o \
mididevice.o midikeyboard.o serialmididevice.o pckeyboard.o \
sysexfileloader.o performanceconfig.o perftimer.o \
effect_compressor.o effect_platervbstereo.o \
fx.o fx_components.o \
fx_svf.o fx_tube.o fx_chorus.o fx_flanger.o fx_orbitone.o fx_phaser.o \
fx_delay.o fx_shimmer_reverb.o fx_rack.o \
uibuttons.o midipin.o
OBJS := main.o
OBJS += kernel.o
OBJS += minidexed.o
OBJS += config.o
OBJS += userinterface.o
OBJS += uimenu.o
OBJS += mididevice.o
OBJS += midikeyboard.o
OBJS += serialmididevice.o
OBJS += pckeyboard.o
OBJS += sysexfileloader.o
OBJS += performanceconfig.o
OBJS += perftimer.o
OBJS += effect_compressor.o
OBJS += effect_platervbstereo.o
OBJS += fx.o
OBJS += fx_components.o
OBJS += fx_svf.o
OBJS += fx_tube.o
OBJS += fx_chorus.o
OBJS += fx_flanger.o
OBJS += fx_orbitone.o
OBJS += fx_phaser.o
OBJS += fx_delay.o
OBJS += fx_reverberator.o
OBJS += fx_rack.o
OBJS += uibuttons.o
OBJS += midipin.o
OPTIMIZE = -O3

@ -25,6 +25,10 @@
#include "debug.hpp"
#include "fx_base.h"
#define MAKE_INTEGRAL_FRACTIONAL(x) \
size_t x ## _integral = static_cast<size_t>(x); \
float32_t x ## _fractional = x - static_cast<float32_t>(x ## _integral)
class INSPECTABLE(FXBase)
{
DISALLOW_COPY_AND_ASSIGN(FXBase);

@ -6,17 +6,17 @@
#define LFO2_MAX_FREQ 0.35f
Chorus::Chorus(float32_t sampling_rate) :
FXElement(sampling_rate, 1.18f),
FXElement(sampling_rate, 1.1049f),
engine_(sampling_rate, 0.0f),
rate_(0.0f),
depth_(0.0f),
fullscale_depth_(0.0f),
feedback_(0.0f)
{
this->lfo_[LFOIndex::Sin1] = new LFO(sampling_rate, 0.0f, LFO1_MAX_FREQ);
this->lfo_[LFOIndex::Cos1] = new LFO(sampling_rate, 0.0f, LFO1_MAX_FREQ, Constants::MPI_2);
this->lfo_[LFOIndex::Sin2] = new LFO(sampling_rate, 0.0f, LFO2_MAX_FREQ);
this->lfo_[LFOIndex::Cos2] = new LFO(sampling_rate, 0.0f, LFO2_MAX_FREQ, Constants::MPI_2);
this->lfo_[LFOIndex::Sin1] = new LFO(sampling_rate, 0.0f, LFO1_MAX_FREQ, 0.0f, false);
this->lfo_[LFOIndex::Cos1] = new LFO(sampling_rate, 0.0f, LFO1_MAX_FREQ, Constants::MPI_2, false);
this->lfo_[LFOIndex::Sin2] = new LFO(sampling_rate, 0.0f, LFO2_MAX_FREQ, 0.0f, false);
this->lfo_[LFOIndex::Cos2] = new LFO(sampling_rate, 0.0f, LFO2_MAX_FREQ, Constants::MPI_2, false);
this->setRate(0.1f);
this->setDepth(0.15f);

@ -5,6 +5,13 @@
///////////////////////////////
// Constants implemlentation //
///////////////////////////////
const float32_t Constants::M_PI_POW_2 = PI * PI;
const float32_t Constants::M_PI_POW_3 = Constants::M_PI_POW_2 * PI;
const float32_t Constants::M_PI_POW_5 = Constants::M_PI_POW_2 * Constants::M_PI_POW_3;
const float32_t Constants::M_PI_POW_7 = Constants::M_PI_POW_2 * Constants::M_PI_POW_5;
const float32_t Constants::M_PI_POW_9 = Constants::M_PI_POW_2 * Constants::M_PI_POW_7;
const float32_t Constants::M_PI_POW_11 = Constants::M_PI_POW_2 * Constants::M_PI_POW_9;
const float32_t Constants::M2PI = 2.0f * PI;
const float32_t Constants::MPI_2 = PI / 2.0f;
const float32_t Constants::MPI_3 = PI / 3.0f;
@ -15,12 +22,15 @@ const float32_t Constants::M1_PI = 1.0f / PI;
/////////////////////////////
// FastLFO implemlentation //
/////////////////////////////
FastLFO::FastLFO(float32_t sampling_rate, float32_t min_frequency, float32_t max_frequency, float32_t initial_phase) :
FastLFO::FastLFO(float32_t sampling_rate, float32_t min_frequency, float32_t max_frequency, float32_t initial_phase, bool centered) :
FXBase(sampling_rate),
InitialPhase(initial_phase),
min_frequency_(min_frequency),
max_frequency_(max_frequency),
centered_(centered),
frequency_(0.0f),
nb_sub_increment_(1),
sub_increment_(0),
y0_(0.0f),
y1_(0.0f),
iir_coefficient_(0.0f),
@ -46,6 +56,9 @@ void FastLFO::setNormalizedFrequency(float32_t normalized_frequency)
this->frequency_ = frequency;
this->unitary_frequency_ = this->frequency_ / this->getSamplingRate();
this->nb_sub_increment_ = (frequency >= 3.0f ? 1 : 300);
this->unitary_frequency_ *= this->nb_sub_increment_;
this->updateCoefficient();
}
}
@ -65,6 +78,9 @@ void FastLFO::setFrequency(float32_t frequency)
this->frequency_ = frequency;
this->unitary_frequency_ = this->frequency_ / this->getSamplingRate();
this->nb_sub_increment_ = (frequency >= 3.0f ? 1 : 300);
this->unitary_frequency_ *= this->nb_sub_increment_;
this->updateCoefficient();
}
}
@ -76,7 +92,7 @@ float32_t FastLFO::getFrequency() const
void FastLFO::updateCoefficient()
{
float32_t frequency = this->unitary_frequency_;
float32_t frequency = this->unitary_frequency_ * 268.0f / 240.0f;
float32_t sign = 16.0f;
frequency -= 0.25f;
@ -104,6 +120,8 @@ void FastLFO::updateCoefficient()
void FastLFO::reset()
{
this->sub_increment_ = 0.0f;
// computing cos(0) = sin(-PI/2)
this->y1_ = this->initial_amplitude_;
this->y0_ = 0.5f;
@ -113,12 +131,12 @@ void FastLFO::reset()
return;
}
float32_t p_i = Constants::M2PI * this->unitary_frequency_;
float32_t p = 0.0f;
float32_t t_p = this->InitialPhase - Constants::MPI_2;
if(t_p < 0.0f)
float32_t p_i = Constants::M2PI * this->unitary_frequency_ / static_cast<float32_t>(this->nb_sub_increment_);
float32_t p = Constants::MPI_2;
float32_t t_p = this->InitialPhase;
if(t_p < p)
{
t_p += Constants::M2PI;
p -= Constants::M2PI;
}
while(p < t_p)
{
@ -130,11 +148,23 @@ void FastLFO::reset()
float32_t FastLFO::process()
{
float32_t temp = this->y0_;
this->y0_ = this->iir_coefficient_ * this->y0_ - this->y1_;
this->y1_ = temp;
this->current_ = (temp + 0.5f) * 2.0f - 1.0f;
float32_t current = temp + 0.5f;
if(this->centered_)
{
current = current * 2.0f - 1.0f;
}
return this->current_;
this->sub_increment_++;
if(this->sub_increment_ >= this->nb_sub_increment_)
{
this->sub_increment_ = 0;
this->y0_ = this->iir_coefficient_ * this->y0_ - this->y1_;
this->y1_ = temp;
this->current_ = current;
return current;
}
return mapfloat(this->sub_increment_, 0, this->nb_sub_increment_, this->current_, current);
}
float32_t FastLFO::current() const
@ -152,22 +182,25 @@ bool InterpolatedSineOscillator::ClassInitializer()
float32_t phase = 0.0;
for(size_t i = 0; i <= InterpolatedSineOscillator::DataPointSize; ++i)
{
InterpolatedSineOscillator::DataPoints[i] = std::sin(phase);
InterpolatedSineOscillator::CenteredDataPoints[i] = std::sin(phase);
InterpolatedSineOscillator::UpliftDataPoints[i] = InterpolatedSineOscillator::CenteredDataPoints[i] * 0.5f + 0.5f;
phase += phase_increment;
}
return true;
}
float32_t InterpolatedSineOscillator::DataPoints[InterpolatedSineOscillator::DataPointSize + 1];
float32_t InterpolatedSineOscillator::CenteredDataPoints[InterpolatedSineOscillator::DataPointSize + 1];
float32_t InterpolatedSineOscillator::UpliftDataPoints[InterpolatedSineOscillator::DataPointSize + 1];
const float32_t InterpolatedSineOscillator::DeltaTime = Constants::M2PI / static_cast<float32_t>(InterpolatedSineOscillator::DataPointSize);
InterpolatedSineOscillator::InterpolatedSineOscillator(float32_t sampling_rate, float32_t min_frequency, float32_t max_frequency, float32_t initial_phase) :
InterpolatedSineOscillator::InterpolatedSineOscillator(float32_t sampling_rate, float32_t min_frequency, float32_t max_frequency, float32_t initial_phase, bool centered) :
FXBase(sampling_rate),
InitialPhase(initial_phase),
min_frequency_(min_frequency),
max_frequency_(max_frequency),
centered_(centered),
frequency_(0.0f),
normalized_frequency_(-1.0f),
phase_index_(initial_phase / InterpolatedSineOscillator::DeltaTime),
@ -232,14 +265,16 @@ void InterpolatedSineOscillator::reset()
float32_t InterpolatedSineOscillator::process()
{
float32_t* dataPoints = this->centered_ ? InterpolatedSineOscillator::CenteredDataPoints : InterpolatedSineOscillator::UpliftDataPoints;
float32_t out = 0.0f;
float32_t findex = this->phase_index_;
size_t index1 = static_cast<size_t>(findex);
size_t index2 = index1 + 1;
float32_t f1 = InterpolatedSineOscillator::DataPoints[index1];
float32_t f2 = InterpolatedSineOscillator::DataPoints[index2];
float32_t f1 = dataPoints[index1];
float32_t f2 = dataPoints[index2];
float32_t r = findex - index1;
out = f1 + (f2 - f1) * r * InterpolatedSineOscillator::DeltaTime;
@ -262,11 +297,12 @@ float32_t InterpolatedSineOscillator::current() const
////////////////////////////////
// ComplexLFO implemlentation //
////////////////////////////////
ComplexLFO::ComplexLFO(float32_t sampling_rate, float32_t min_frequency, float32_t max_frequency, float32_t initial_phase) :
ComplexLFO::ComplexLFO(float32_t sampling_rate, float32_t min_frequency, float32_t max_frequency, float32_t initial_phase, bool centered) :
FXBase(sampling_rate),
InitialPhase(initial_phase),
min_frequency_(min_frequency),
max_frequency_(max_frequency),
centered_(centered),
normalized_frequency_(-1.0f),
frequency_(0.0f),
phase_(initial_phase),
@ -366,6 +402,11 @@ float32_t ComplexLFO::process()
break;
}
if(!this->centered_)
{
out = out * 0.5f + 0.5f;
}
this->current_sample_ = out;
this->phase_ += this->phase_increment_;

@ -24,8 +24,18 @@
#include <random>
#include <cassert>
#define LFO_MIN_FREQUENCY 0.01f
#define LFO_MAX_FREQUENCY 10.0f
struct Constants
{
const static float32_t M_PI_POW_2; // PI^2
const static float32_t M_PI_POW_3; // PI^3
const static float32_t M_PI_POW_5; // PI^5
const static float32_t M_PI_POW_7; // PI^7
const static float32_t M_PI_POW_9; // PI^9
const static float32_t M_PI_POW_11; // PI^11
const static float32_t M2PI; // 2 * PI
const static float32_t MPI_2; // PI / 2
const static float32_t MPI_3; // PI / 3
@ -39,7 +49,7 @@ class FastLFO : public FXBase
DISALLOW_COPY_AND_ASSIGN(FastLFO);
public:
FastLFO(float32_t sampling_rate, float32_t min_frequency = 0.01f, float32_t max_frequency = 10.0f, float32_t initial_phase = 0.0f);
FastLFO(float32_t sampling_rate, float32_t min_frequency = LFO_MIN_FREQUENCY, float32_t max_frequency = LFO_MAX_FREQUENCY, float32_t initial_phase = 0.0f, bool centered = true);
virtual ~FastLFO();
void setNormalizedFrequency(float32_t normalized_frequency);
@ -58,9 +68,12 @@ private:
const float32_t InitialPhase;
const float32_t min_frequency_;
const float32_t max_frequency_;
const bool centered_;
float32_t frequency_;
float32_t normalized_frequency_;
float32_t unitary_frequency_;
size_t nb_sub_increment_;
size_t sub_increment_;
float32_t y0_;
float32_t y1_;
@ -135,7 +148,7 @@ class InterpolatedSineOscillator : public FXBase
DISALLOW_COPY_AND_ASSIGN(InterpolatedSineOscillator);
public:
InterpolatedSineOscillator(float32_t sampling_rate, float32_t min_frequency = 0.01f, float32_t max_frequency = 10.0f, float32_t initial_phase = 0.0f);
InterpolatedSineOscillator(float32_t sampling_rate, float32_t min_frequency = LFO_MIN_FREQUENCY, float32_t max_frequency = LFO_MAX_FREQUENCY, float32_t initial_phase = 0.0f, bool centered = true);
virtual ~InterpolatedSineOscillator();
void setNormalizedFrequency(float32_t normalized_frequency);
@ -152,16 +165,18 @@ private:
static bool ClassInitializer();
static const size_t DataPointSize = 176400;
static const float32_t DeltaTime;
static float32_t DataPoints[];
static float32_t CenteredDataPoints[];
static float32_t UpliftDataPoints[];
const float32_t InitialPhase;
const float32_t min_frequency_;
const float32_t max_frequency_;
float32_t frequency_;
float32_t normalized_frequency_;
float32_t phase_index_;
float32_t phase_index_increment_;
float32_t current_sample_;
const float32_t InitialPhase;
const float32_t min_frequency_;
const float32_t max_frequency_;
const bool centered_;
float32_t frequency_;
float32_t normalized_frequency_;
float32_t phase_index_;
float32_t phase_index_increment_;
float32_t current_sample_;
IMPLEMENT_DUMP(
const size_t space = 22;
@ -227,7 +242,7 @@ public:
Noise
} Waveform;
ComplexLFO(float32_t sampling_rate, float32_t min_frequency = 0.01f, float32_t max_frequency = 10.0f, float32_t initial_phase = 0.0f);
ComplexLFO(float32_t sampling_rate, float32_t min_frequency = LFO_MIN_FREQUENCY, float32_t max_frequency = LFO_MAX_FREQUENCY, float32_t initial_phase = 0.0f, bool centered = true);
virtual ~ComplexLFO();
void setWaveform(Waveform waveform);
@ -247,6 +262,7 @@ private:
const float32_t InitialPhase;
const float32_t min_frequency_;
const float32_t max_frequency_;
const bool centered_;
Waveform waveform_;
float32_t normalized_frequency_;
float32_t frequency_;
@ -462,4 +478,4 @@ float32_t softSaturator2(float32_t in, float32_t saturation);
float32_t softSaturator3(float32_t in, float32_t saturation);
float32_t softSaturator4(float32_t in, float32_t saturation);
float32_t waveFolder(float32_t input, float32_t bias);
float32_t waveFolder(float32_t input, float32_t bias);

@ -10,8 +10,8 @@
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),
lpf_(sampling_rate, StateVariableFilter::FilterMode::LPF, LPF_CUTOFF_REF),
hpf_(sampling_rate, StateVariableFilter::FilterMode::HPF, HPF_CUTOFF_REF),
ratio_(1.0f)
{
this->setCutoffChangeRatio(0.0f);
@ -50,7 +50,7 @@ void Delay::LowHighPassFilter::processSample(float32_t inL, float32_t inR, float
}
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, 3.46f),
FXElement(sampling_rate, 2.2587f),
MaxSampleDelayTime((MAX_DELAY_TIME + MAX_FLUTTER_DELAY_TIME) * sampling_rate * MAX_DELAY_TIME),
read_pos_L_(0),
read_pos_R_(0),

@ -121,7 +121,7 @@ public:
write_ptr_(0)
{
this->buffer_ = new T[size];
for(unsigned i = 0; i < LFOIndex::kLFOCount; ++i) this->lfo_[i] = enable_lfo ? new LFO(sampling_rate, 0.0f, max_lfo_frequency) : nullptr;
for(unsigned i = 0; i < LFOIndex::kLFOCount; ++i) this->lfo_[i] = enable_lfo ? new LFO(sampling_rate, 0.0f, max_lfo_frequency, 0.0f, false) : nullptr;
this->clear();
}
@ -338,8 +338,7 @@ public:
{
assert((D::base + D::length) <= size);
int32_t offset_integral = static_cast<int32_t>(offset);
float32_t offset_fractional = offset - static_cast<float32_t>(offset_integral);
MAKE_INTEGRAL_FRACTIONAL(offset);
int32_t index = this->write_ptr_ + offset_integral + D::base;
float32_t a = DataType<format>::decompress(this->buffer_[index & MASK]);
@ -355,7 +354,7 @@ public:
{
assert(index < LFOIndex::kLFOCount);
this->interpolate(d, offset + amplitude * this->lfo_value_[index], scale);
this->interpolate(d, offset + amplitude * (this->lfo_value_[index] * 0.5f + 0.5f), scale);
}
private:
@ -482,7 +481,7 @@ private:
if(enable_lfo)
{
for(size_t i = 0; i < size; ++i)
for(size_t i = 0; i < LFOIndex::kLFOCount; ++i)
{
this->lfo_[i]->inspect(inspector, deepInspection, tag + ".lfo_[ " + std::to_string(i) + " ]");
}

@ -1,15 +1,15 @@
#include "fx_flanger.h"
Flanger::Flanger(float32_t sampling_rate, float32_t rate, float32_t depth, float32_t feedback) :
FXElement(sampling_rate, 1.17f),
FXElement(sampling_rate, 0.9288f),
MaxDelayLineSize(static_cast<unsigned>(MAX_FLANGER_DELAY * sampling_rate)),
write_index_(0)
{
this->delay_lineL_ = new float32_t[this->MaxDelayLineSize];
this->delay_lineR_ = new float32_t[this->MaxDelayLineSize];
this->lfo_[LFOIndex::LFO_L] = new LFO(sampling_rate, 0.1f, 5.0f);
this->lfo_[LFOIndex::LFO_R] = new LFO(sampling_rate, 0.1f, 5.0f, Constants::MPI_2);
this->lfo_[LFOIndex::LFO_L] = new LFO(sampling_rate, 0.1f, 5.0f, 0.0f, false);
this->lfo_[LFOIndex::LFO_R] = new LFO(sampling_rate, 0.1f, 5.0f, Constants::MPI_2, false);
this->setRate(rate);
this->setDepth(depth);

@ -4,18 +4,18 @@
#define LFO_FAST_MAX_FREQUENCY 8.8f
Orbitone::Orbitone(float32_t sampling_rate, float32_t rate, float32_t depth) :
FXElement(sampling_rate, 1.8f),
FXElement(sampling_rate, 1.4442f),
engine_(sampling_rate, 0.0f),
depth_(0.0f),
fullscale_depth_(0.0f)
{
this->lfo_[LFOIndex::Slow0 ] = new LFO(sampling_rate, 0.0f, LFO_SLOW_MAX_FREQUENCY, 0.0f);
this->lfo_[LFOIndex::Slow120] = new LFO(sampling_rate, 0.0f, LFO_SLOW_MAX_FREQUENCY, 2.0f * PI / 3.0);
this->lfo_[LFOIndex::Slow240] = new LFO(sampling_rate, 0.0f, LFO_SLOW_MAX_FREQUENCY, 4.0f * PI / 3.0);
this->lfo_[LFOIndex::Slow0 ] = new LFO(sampling_rate, 0.0f, LFO_SLOW_MAX_FREQUENCY, 0.0f, false);
this->lfo_[LFOIndex::Slow120] = new LFO(sampling_rate, 0.0f, LFO_SLOW_MAX_FREQUENCY, 2.0f * PI / 3.0, false);
this->lfo_[LFOIndex::Slow240] = new LFO(sampling_rate, 0.0f, LFO_SLOW_MAX_FREQUENCY, 4.0f * PI / 3.0, false);
this->lfo_[LFOIndex::Fast0 ] = new LFO(sampling_rate, 0.0f, LFO_FAST_MAX_FREQUENCY, 0.0f);
this->lfo_[LFOIndex::Fast120] = new LFO(sampling_rate, 0.0f, LFO_FAST_MAX_FREQUENCY, 2.0f * PI / 3.0);
this->lfo_[LFOIndex::Fast240] = new LFO(sampling_rate, 0.0f, LFO_FAST_MAX_FREQUENCY, 4.0f * PI / 3.0);
this->lfo_[LFOIndex::Fast0 ] = new LFO(sampling_rate, 0.0f, LFO_FAST_MAX_FREQUENCY, 0.0f, false);
this->lfo_[LFOIndex::Fast120] = new LFO(sampling_rate, 0.0f, LFO_FAST_MAX_FREQUENCY, 2.0f * PI / 3.0, false);
this->lfo_[LFOIndex::Fast240] = new LFO(sampling_rate, 0.0f, LFO_FAST_MAX_FREQUENCY, 4.0f * PI / 3.0, false);
for(unsigned i = 0; i < LFOIndex::kLFOCount; ++i)
{

@ -33,15 +33,15 @@ void Phaser::AllpassDelay::setDelay(float32_t delayL, float32_t delayR)
Phaser::Phaser(float32_t sampling_rate, float32_t rate, float32_t depth, float32_t feedback, unsigned nb_stages) :
FXElement(sampling_rate),
FXElement(sampling_rate, 1.3804f),
depth_(0.0f),
gain_(1.0f),
feedback_(0.0f),
dmin_(0.0f),
dmax_(0.0f)
{
this->lfo_[StereoChannels::Left ] = new LFO(sampling_rate, 0.0f, 2.5f);
this->lfo_[StereoChannels::Right] = new LFO(sampling_rate, 0.0f, 2.5f, Constants::MPI_2);
this->lfo_[StereoChannels::Left ] = new LFO(sampling_rate, 0.0f, 2.5f, 0.0f, false);
this->lfo_[StereoChannels::Right] = new LFO(sampling_rate, 0.0f, 2.5f, Constants::MPI_2, false);
this->setRate(rate);
this->setDepth(depth);

@ -15,7 +15,7 @@ FXRack::FXRack(float32_t sampling_rate, bool enable, float32_t wet) :
this->fxOrbitone_ = new FXUnit<Orbitone>(sampling_rate);
this->fxPhaser_ = new FXUnit<Phaser>(sampling_rate);
this->fxDelay_ = new FXUnit<Delay>(sampling_rate);
this->fxShimmerReverb_ = new FXUnit<ShimmerReverb>(sampling_rate);
this->fxReverberator_ = new FXUnit<Reverberator>(sampling_rate);
this->registerFX(this->fxTube_);
this->registerFX(this->fxChorus_);
@ -23,7 +23,7 @@ FXRack::FXRack(float32_t sampling_rate, bool enable, float32_t wet) :
this->registerFX(this->fxOrbitone_);
this->registerFX(this->fxPhaser_);
this->registerFX(this->fxDelay_);
this->registerFX(this->fxShimmerReverb_);
this->registerFX(this->fxReverberator_);
}
FXRack::~FXRack()
@ -36,7 +36,7 @@ FXRack::~FXRack()
delete this->fxOrbitone_;
delete this->fxPhaser_;
delete this->fxDelay_;
delete this->fxShimmerReverb_;
delete this->fxReverberator_;
}
inline void FXRack::reset()
@ -147,7 +147,7 @@ FXUnit<Delay>* FXRack::getDelay()
return this->fxDelay_;
}
FXUnit<ShimmerReverb>* FXRack::getShimmerReverb()
FXUnit<Reverberator>* FXRack::getReverberator()
{
return this->fxShimmerReverb_;
return this->fxReverberator_;
}

@ -25,7 +25,7 @@
#include "fx_orbitone.h"
#include "fx_phaser.h"
#include "fx_delay.h"
#include "fx_shimmer_reverb.h"
#include "fx_reverberator.h"
#include "fx_unit.hpp"
#include <vector>
@ -56,7 +56,7 @@ public:
FXUnit<Orbitone>* getOrbitone();
FXUnit<Phaser>* getPhaser();
FXUnit<Delay>* getDelay();
FXUnit<ShimmerReverb>* getShimmerReverb();
FXUnit<Reverberator>* getReverberator();
private:
void registerFX(FXElement* fx);
@ -71,7 +71,7 @@ private:
FXUnit<Orbitone>* fxOrbitone_;
FXUnit<Phaser>* fxPhaser_;
FXUnit<Delay>* fxDelay_;
FXUnit<ShimmerReverb>* fxShimmerReverb_;
FXUnit<Reverberator>* fxReverberator_;
IMPLEMENT_DUMP(
const size_t space = 10;
@ -104,7 +104,7 @@ private:
this->fxOrbitone_->dump(out, deepInspection, tag + ".fxOrbitone_");
this->fxPhaser_->dump(out, deepInspection, tag + ".fxPhaser_");
this->fxDelay_->dump(out, deepInspection, tag + ".fxDelay_");
this->fxShimmerReverb_->dump(out, deepInspection, tag + ".fxShimmerReverb_");
this->fxReverberator_->dump(out, deepInspection, tag + ".fxReverberator_");
}
out << "END " << tag << "(" << typeid(*this).name() << ") dump" << std::endl << std::endl;
@ -124,7 +124,7 @@ private:
nb_errors += this->fxOrbitone_->inspect(inspector, deepInspection, tag + ".fxOrbitone_");
nb_errors += this->fxPhaser_->inspect(inspector, deepInspection, tag + ".fxPhaser_");
nb_errors += this->fxDelay_->inspect(inspector, deepInspection, tag + ".fxDelay_");
nb_errors += this->fxShimmerReverb_->inspect(inspector, deepInspection, tag + ".fxShimmerReverb_");
nb_errors += this->fxReverberator_->inspect(inspector, deepInspection, tag + ".fxReverberator_");
}
return nb_errors;

@ -1,8 +1,8 @@
#include "fx_shimmer_reverb.h"
#include "fx_reverberator.h"
#define TAIL , -1
ShimmerReverb::ShimmerReverb(float32_t sampling_rate) :
Reverberator::Reverberator(float32_t sampling_rate) :
FXElement(sampling_rate),
engine_(sampling_rate),
input_gain_(-1.0f),
@ -23,18 +23,18 @@ ShimmerReverb::ShimmerReverb(float32_t sampling_rate) :
this->reset();
}
ShimmerReverb::~ShimmerReverb()
Reverberator::~Reverberator()
{
}
void ShimmerReverb::reset()
void Reverberator::reset()
{
this->engine_.reset();
this->lp_decay_1_ = 0.0f;
this->lp_decay_2_ = 0.0f;
}
void ShimmerReverb::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
void Reverberator::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{
// This is the Griesinger topology described in the Dattorro paper
// (4 AP diffusers on the input, then a loop of 2x 2AP+1Delay).
@ -119,42 +119,42 @@ void ShimmerReverb::processSample(float32_t inL, float32_t inR, float32_t& outL,
this->lp_decay_2_ = lp_2;
}
void ShimmerReverb::setInputGain(float32_t gain)
void Reverberator::setInputGain(float32_t gain)
{
this->input_gain_ = constrain(gain, 0.0f, 1.0f);
}
float32_t ShimmerReverb::getInputGain() const
float32_t Reverberator::getInputGain() const
{
return this->input_gain_;
}
void ShimmerReverb::setTime(float32_t time)
void Reverberator::setTime(float32_t time)
{
this->reverb_time_ = constrain(time, 0.0f, 1.0f);
}
float32_t ShimmerReverb::getTime() const
float32_t Reverberator::getTime() const
{
return this->reverb_time_;
}
void ShimmerReverb::setDiffusion(float32_t diffusion)
void Reverberator::setDiffusion(float32_t diffusion)
{
this->diffusion_ = constrain(diffusion, 0.0f, 1.0f);
}
float32_t ShimmerReverb::getDiffusion() const
float32_t Reverberator::getDiffusion() const
{
return this->diffusion_;
}
void ShimmerReverb::setLP(float32_t lp)
void Reverberator::setLP(float32_t lp)
{
this->lp_ = constrain(lp, 0.0f, 1.0f);
}
float32_t ShimmerReverb::getLP() const
float32_t Reverberator::getLP() const
{
return this->lp_;
}

@ -0,0 +1,123 @@
// 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_reverberator.h
//
// Stereo Reverberator proposed in the context of the MiniDexed project
// It is adapted from the Reverb that could be found on Cloud EuroRack module from Mutable Instrruments
//
#pragma once
#include "fx_components.h"
#include "fx_engine.hpp"
#define REVERBERATOR_BUFFER_SIZE 16384
class Reverberator : public FXElement
{
DISALLOW_COPY_AND_ASSIGN(Reverberator);
public:
Reverberator(float32_t sampling_rate);
virtual ~Reverberator();
virtual void reset() override;
virtual void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) override;
void setInputGain(float32_t gain);
float32_t getInputGain() const;
void setTime(float32_t time);
float32_t getTime() const;
void setDiffusion(float32_t diffusion);
float32_t getDiffusion() const;
void setLP(float32_t lp);
float32_t getLP() const;
private:
typedef FxEngine<REVERBERATOR_BUFFER_SIZE, Format::FORMAT_FLOAT32, true> Engine;
Engine engine_;
float32_t input_gain_;
float32_t reverb_time_;
float32_t diffusion_;
float32_t lp_;
float32_t lp_decay_1_;
float32_t lp_decay_2_;
IMPLEMENT_DUMP(
const size_t space = 12;
const size_t precision = 6;
std::stringstream ss;
out << "START " << tag << "(" << typeid(*this).name() << ") dump" << std::endl << std::endl;
SS_RESET(ss, precision, std::left);
SS__TEXT(ss, ' ', space, std::left, '|', "input_gain_");
SS__TEXT(ss, ' ', space, std::left, '|', "reverb_time_");
SS__TEXT(ss, ' ', space, std::left, '|', "diffusion_");
SS__TEXT(ss, ' ', space, std::left, '|', "lp_");
SS__TEXT(ss, ' ', space, std::left, '|', "lp_decay_1_");
SS__TEXT(ss, ' ', space, std::left, '|', "lp_decay_2_");
out << "\t" << ss.str() << std::endl;
SS_RESET(ss, precision, std::left);
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
out << "\t" << ss.str() << std::endl;
SS_RESET(ss, precision, std::left);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->input_gain_);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->reverb_time_);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->diffusion_);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->lp_);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->lp_decay_1_);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->lp_decay_2_);
out << "\t" << ss.str() << std::endl;
if(deepInspection)
{
this->engine_.dump(out, deepInspection, tag + ".engine_");
}
out << "END " << tag << "(" << typeid(*this).name() << ") dump" << std::endl << std::endl;
)
IMPLEMENT_INSPECT(
size_t nb_errors = 0u;
nb_errors += inspector(tag + ".input_gain_", this->input_gain_, 0.0f, 1.0f, deepInspection);
nb_errors += inspector(tag + ".reverb_time_", this->reverb_time_, 0.0f, 1.0f, deepInspection);
nb_errors += inspector(tag + ".diffusion_", this->diffusion_, 0.0f, 1.0f, deepInspection);
nb_errors += inspector(tag + ".lp_", this->lp_, 0.0f, 1.0f, deepInspection);
nb_errors += inspector(tag + ".lp_decay_1_", this->lp_decay_1_, -1.0f, 1.0f, deepInspection);
nb_errors += inspector(tag + ".lp_decay_2_", this->lp_decay_2_, -1.0f, 1.0f, deepInspection);
if(deepInspection)
{
nb_errors += this->engine_.inspect(inspector, deepInspection, tag + ".engine_");
}
return nb_errors;
)
};

@ -1,65 +0,0 @@
// 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_shimmer_reverb3.h
//
// Stereo Shimmer Reverb proposed in the context of the MiniDexed project
// It is adapted from the Shimmer Reverb that could be found on Cloud EuroRack module from Mutable Instrruments
//
#pragma once
#include "fx_components.h"
#include "fx_engine.hpp"
#define SHIMMER_REVERB_BUFFER_SIZE 16384
class ShimmerReverb : public FXElement
{
DISALLOW_COPY_AND_ASSIGN(ShimmerReverb);
public:
ShimmerReverb(float32_t sampling_rate);
virtual ~ShimmerReverb();
virtual void reset() override;
virtual void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) override;
void setInputGain(float32_t gain);
float32_t getInputGain() const;
void setTime(float32_t time);
float32_t getTime() const;
void setDiffusion(float32_t diffusion);
float32_t getDiffusion() const;
void setLP(float32_t lp);
float32_t getLP() const;
private:
typedef FxEngine<SHIMMER_REVERB_BUFFER_SIZE, Format::FORMAT_FLOAT32, true> Engine;
Engine engine_;
float32_t input_gain_;
float32_t reverb_time_;
float32_t diffusion_;
float32_t lp_;
float32_t lp_decay_1_;
float32_t lp_decay_2_;
IMPLEMENT_DUMP()
IMPLEMENT_INSPECT(return 0u;)
};

@ -2,9 +2,9 @@
#include <cmath>
StateVariableFilter::StateVariableFilter(float32_t sampling_rate, Type type, float32_t cutoff) :
StateVariableFilter::StateVariableFilter(float32_t sampling_rate, FilterMode mode, float32_t cutoff) :
FXElement(sampling_rate),
type_(type),
mode_(mode),
gain_(-1.0f),
cutoff_(cutoff),
resonance_(0.0f)
@ -20,11 +20,11 @@ StateVariableFilter::~StateVariableFilter()
{
}
void StateVariableFilter::setFilterType(Type type)
void StateVariableFilter::setFilterMode(FilterMode mode)
{
if(this->type_ != type)
if(this->mode_ != mode)
{
this->type_ = type;
this->mode_ = mode;
this->updateCoefficients();
}
}
@ -72,17 +72,19 @@ void StateVariableFilter::updateCoefficients()
this->c1_ = a_b / (1.0f + 0.5f * this->a_ + 0.25f * this->b_);
this->c2_ = this->b_ / a_b;
switch(this->type_)
switch(this->mode_)
{
case Type::LPF:
case FilterMode::LPF:
this->d1_ = 0.0f;
this->d0_ = 0.25f * this->c1_ * this->c2_;
break;
case Type::HPF:
case FilterMode::HPF:
this->d1_ = 0.0f;
this->d0_ = 1.0f - 0.5f * this->c1_ + 0.25f * this->c1_ * this->c2_;
break;
case Type::BPF:
case FilterMode::BPF:
this->d1_ = 1.0f - this->c2_;
this->d0_ = this->d1_ * this->c1_ * 0.5f;
break;
@ -101,9 +103,9 @@ void StateVariableFilter::processSample(float32_t inL, float32_t inR, float32_t&
{
const float32_t gain = this->g_;
switch(this->type_)
switch(this->mode_)
{
case Type::LPF:
case FilterMode::LPF:
{
const float32_t x = inL - this->z1_[StereoChannels::Left] - this->z2_[StereoChannels::Left] + 1e-20f;
this->z2_[StereoChannels::Left] += this->c2_ * this->z1_[StereoChannels::Left];
@ -118,7 +120,7 @@ void StateVariableFilter::processSample(float32_t inL, float32_t inR, float32_t&
}
break;
case Type::HPF:
case FilterMode::HPF:
{
const float32_t x = inL - this->z1_[StereoChannels::Left] - this->z2_[StereoChannels::Left] + 1e-20f;
outL = gain * this->d0_ * x;
@ -133,7 +135,7 @@ void StateVariableFilter::processSample(float32_t inL, float32_t inR, float32_t&
}
break;
case Type::BPF:
case FilterMode::BPF:
{
const float32_t x = inL - this->z1_[StereoChannels::Left] - this->z2_[StereoChannels::Left] + 1e-20f;
outL = gain * (this->d0_ * x) + this->d1_ * this->z1_[StereoChannels::Left];

@ -17,25 +17,27 @@
//
// State Variable Filter used in Tape Delay
//
#pragma once
#include "fx.h"
#include "fx_components.h"
class StateVariableFilter : public FXElement
{
DISALLOW_COPY_AND_ASSIGN(StateVariableFilter);
public:
typedef enum
enum FilterMode
{
LPF, // Low pass filter
HPF, // High pass filter
BPF // Band pass filter
} Type;
};
StateVariableFilter(float32_t sampling_rate, Type type, float32_t cutoff);
StateVariableFilter(float32_t sampling_rate, FilterMode mode, float32_t cutoff);
virtual ~StateVariableFilter();
void setFilterType(Type type);
void setFilterMode(FilterMode mode);
void setGainDB(float32_t gainDB);
void setCutoff(float32_t cutoff);
void setResonance(float32_t resonance);
@ -46,7 +48,7 @@ public:
private:
void updateCoefficients();
Type type_;
FilterMode mode_;
float32_t gain_;
float32_t cutoff_;
float32_t resonance_;
@ -70,6 +72,7 @@ private:
out << "START " << tag << "(" << typeid(*this).name() << ") dump" << std::endl << std::endl;
SS_RESET(ss, precision, std::left);
SS__TEXT(ss, ' ', space, std::left, '|', "mode_");
SS__TEXT(ss, ' ', space, std::left, '|', "gain_");
SS__TEXT(ss, ' ', space, std::left, '|', "cutoff_");
SS__TEXT(ss, ' ', space, std::left, '|', "resonance_");
@ -91,9 +94,11 @@ private:
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
out << "\t" << ss.str() << std::endl;
SS_RESET(ss, precision, std::left);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->mode_);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->gain_);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->cutoff_);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->resonance_);
@ -123,4 +128,235 @@ private:
return nb_errors;
)
};
};
class SVF : public FXElement
{
DISALLOW_COPY_AND_ASSIGN(SVF);
public:
enum FrequencyApproximation
{
FrequencyExact,
FrequencyAccurate,
FrequencyFast,
FrequencyDirty
};
enum FilterMode
{
SVF_LP,
SVF_BP,
SVF_BP_NORMALIZED,
SVF_HP
};
SVF(float32_t sampling_frequency, FilterMode mode = FilterMode::SVF_LP) :
FXElement(sampling_frequency),
Mode(mode),
g_(0.0f),
r_(0.0f),
h_(0.0f)
{
this->reset();
}
virtual ~SVF()
{
}
inline virtual void reset() override
{
memset(this->state1_, 0, StereoChannels::kNumChannels * sizeof(float32_t));
memset(this->state2_, 0, StereoChannels::kNumChannels * sizeof(float32_t));
}
virtual void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) override
{
float32_t hp, bp, lp;
{
hp = (inL - this->r_ * this->state1_[StereoChannels::Left ] - this->g_ * this->state1_[StereoChannels::Left ] - this->state2_[StereoChannels::Left ]) * this->h_;
bp = this->g_ * hp + this->state1_[StereoChannels::Left ];
this->state1_[StereoChannels::Left ] = this->g_ * hp + bp;
lp = this->g_ * bp + this->state2_[StereoChannels::Left ];
this->state2_[StereoChannels::Left ] = this->g_ * bp + lp;
switch(this->Mode)
{
case FilterMode::SVF_LP:
outL = lp;
break;
case FilterMode::SVF_BP:
outL = bp;
break;
case FilterMode::SVF_BP_NORMALIZED:
outL = bp * this->r_;
break;
case FilterMode::SVF_HP:
outL = hp;
break;
}
}
{
hp = (inR - this->r_ * this->state1_[StereoChannels::Right] - this->g_ * this->state1_[StereoChannels::Right] - this->state2_[StereoChannels::Right]) * this->h_;
bp = this->g_ * hp + this->state1_[StereoChannels::Right];
this->state1_[StereoChannels::Right] = this->g_ * hp + bp;
lp = this->g_ * bp + this->state2_[StereoChannels::Right];
this->state2_[StereoChannels::Right] = this->g_ * bp + lp;
switch(this->Mode)
{
case FilterMode::SVF_LP:
outR = lp;
break;
case FilterMode::SVF_BP:
outR = bp;
break;
case FilterMode::SVF_BP_NORMALIZED:
outR = bp * this->r_;
break;
case FilterMode::SVF_HP:
outR = hp;
break;
}
}
}
inline void setGRH(float32_t g, float32_t r, float32_t h)
{
this->g_ = g;
this->r_ = r;
this->h_ = h;
}
inline void setGR(float32_t g, float32_t r)
{
this->g_ = g;
this->r_ = r;
this->h_ = 1.0f / (1.0f + this->r_ * this->g_ * this->g_ * this->g_);
}
template<FrequencyApproximation approximation>
inline void setFQ(float32_t frequency, float32_t resonance)
{
this->g_ = SVF::tan<approximation>(frequency);
this->r_ = 1.0f / resonance;
this->h_ = 1.0f / (1.0f + this->r_ * this->g_ * this->g_ * this->g_);
}
private:
template<FrequencyApproximation approximation>
static inline float32_t tan(float32_t f)
{
switch(approximation)
{
case FrequencyApproximation::FrequencyExact:
{
// Clip coefficient to about 100.
f = constrain(f, 0.0f, 0.497f);
return ::tan(PI * f);
}
case FrequencyApproximation::FrequencyDirty:
{
// Optimized for frequencies below 8kHz.
const float32_t a = 3.736e-01 * Constants::M_PI_POW_3;
return f * (PI + a * f * f);
}
case FrequencyApproximation::FrequencyFast:
{
// The usual tangent approximation uses 3.1755e-01 and 2.033e-01, but
// the coefficients used here are optimized to minimize error for the
// 16Hz to 16kHz range, with a sample rate of 48kHz.
const float a = 3.260e-01 * Constants::M_PI_POW_3;
const float b = 1.823e-01 * Constants::M_PI_POW_5;
float f2 = f * f;
return f * (PI + f2 * (a + b * f2));
}
case FrequencyApproximation::FrequencyAccurate:
{
// These coefficients don't need to be tweaked for the audio range.
const float a = 3.333314036e-01 * Constants::M_PI_POW_3;
const float b = 1.333923995e-01 * Constants::M_PI_POW_5;
const float c = 5.33740603e-02 * Constants::M_PI_POW_7;
const float d = 2.900525e-03 * Constants::M_PI_POW_9;
const float e = 9.5168091e-03 * Constants::M_PI_POW_11;
float f2 = f * f;
return f * (PI + f2 * (a + f2 * (b + f2 * (c + f2 * (d + f2 * e)))));
}
}
}
const FilterMode Mode;
float32_t g_;
float32_t r_;
float32_t h_;
float32_t state1_[StereoChannels::kNumChannels];
float32_t state2_[StereoChannels::kNumChannels];
IMPLEMENT_DUMP(
const size_t space = 12;
const size_t precision = 6;
std::stringstream ss;
out << "START " << tag << "(" << typeid(*this).name() << ") dump" << std::endl << std::endl;
SS_RESET(ss, precision, std::left);
SS__TEXT(ss, ' ', space, std::left, '|', "g_");
SS__TEXT(ss, ' ', space, std::left, '|', "r_");
SS__TEXT(ss, ' ', space, std::left, '|', "h_");
SS__TEXT(ss, ' ', space, std::left, '|', "state1_[ L ]");
SS__TEXT(ss, ' ', space, std::left, '|', "state1_[ R ]");
SS__TEXT(ss, ' ', space, std::left, '|', "state2_[ L ]");
SS__TEXT(ss, ' ', space, std::left, '|', "state2_[ R ]");
out << "\t" << ss.str() << std::endl;
SS_RESET(ss, precision, std::left);
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
SS_SPACE(ss, '-', space, std::left, '+');
out << "\t" << ss.str() << std::endl;
SS_RESET(ss, precision, std::left);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->g_);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->r_);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->r_);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->state1_[StereoChannels::Left ]);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->state1_[StereoChannels::Right]);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->state2_[StereoChannels::Left ]);
SS__TEXT(ss, ' ', space - 1, std::right, " |", this->state2_[StereoChannels::Right]);
out << "\t" << ss.str() << std::endl;
out << "END " << tag << "(" << typeid(*this).name() << ") dump" << std::endl << std::endl;
)
IMPLEMENT_INSPECT(
size_t nb_errors = 0u;
nb_errors += inspector(tag + ".g_", this->g_, 0.0f, 106.11f, deepInspection);
nb_errors += inspector(tag + ".r_", this->r_, 0.0f, 1.0f, deepInspection);
nb_errors += inspector(tag + ".h_", this->h_, 0.0f, 1.0f, deepInspection);
nb_errors += inspector(tag + ".state1_[ L ]", this->state1_[StereoChannels::Left ], -1.0f, 1.0f, deepInspection);
nb_errors += inspector(tag + ".state1_[ R ]", this->state1_[StereoChannels::Right], -1.0f, 1.0f, deepInspection);
nb_errors += inspector(tag + ".state2_[ L ]", this->state2_[StereoChannels::Left ], -1.0f, 1.0f, deepInspection);
nb_errors += inspector(tag + ".state2_[ R ]", this->state2_[StereoChannels::Right], -1.0f, 1.0f, deepInspection);
return nb_errors;
)
};

@ -936,37 +936,37 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue)
case ParameterFXChainShimmerReverbEnable:
nValue = constrain((int)nValue, 0, 1);
this->m_FXSpinLock.Acquire();
this->fx_rack->getShimmerReverb()->setEnable(!!nValue);
this->fx_rack->getReverberator()->setEnable(!!nValue);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainShimmerReverbWet:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->fx_rack->getShimmerReverb()->setWetLevel(nValue / 99.0f);
this->fx_rack->getReverberator()->setWetLevel(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainShimmerReverbInputGain:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->fx_rack->getShimmerReverb()->setInputGain(nValue / 99.0f);
this->fx_rack->getReverberator()->setInputGain(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainShimmerReverbTime:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->fx_rack->getShimmerReverb()->setTime(nValue / 99.0f);
this->fx_rack->getReverberator()->setTime(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainShimmerReverbDiffusion:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->fx_rack->getShimmerReverb()->setDiffusion(nValue / 99.0f);
this->fx_rack->getReverberator()->setDiffusion(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainShimmerReverbLP:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->fx_rack->getShimmerReverb()->setLP(nValue / 99.0f);
this->fx_rack->getReverberator()->setLP(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
#endif

@ -5,15 +5,15 @@ OUTPUT_FOLDER := results
EXE := $(BINDIR)/all_tests.bin
BETA := $(BINDIR)/beta.bin
CXX = g++
CXX = g++
CXXFLAGS = -g -Wall -std=c++20 -MMD -MP
DEFINES = -DCPU=x86 -DDEBUG -DOUTPUT_FOLDER="\"$(OUTPUT_FOLDER)\""
INCLUDES = -I../../CMSIS_5/CMSIS/DSP/Include/ \
-I../../CMSIS_5/CMSIS/Core/Include/ \
-I../../Synth_Dexed/src/
CPPCHECK = cppcheck
CHECKFLAGS = -q -j 8 --enable=all --force --language=c++ \
CPPCHECK = cppcheck
CHECKFLAGS = -q -j 8 --enable=all --force --language=c++ \
$(INCLUDES) --platform=unix64 \
--error-exitcode=0 \
--suppressions-list=cppcheck-suppression-list.txt
@ -21,7 +21,7 @@ CHECKFLAGS = -q -j 8 --enable=all --force --language=c++ \
-include $(TST_OBJS:.o=.d)
-include $(FX__OBJS:.o=.d)
LD := g++
LD := g++
LIBS := -lm -lstdc++ -lgtest -lpthread
FX__SRCS := ../fx.cpp
@ -34,17 +34,29 @@ FX__SRCS += ../fx_orbitone.cpp
FX__SRCS += ../fx_flanger.cpp
FX__SRCS += ../fx_delay.cpp
FX__SRCS += ../effect_platervbstereo.cpp
FX__SRCS += ../fx_shimmer_reverb.cpp
FX__SRCS += ../fx_reverberator.cpp
FX__SRCS += ../fx_rack.cpp
TST_SRCS := $(filter-out waveplay.cpp $(wildcard beta*.cpp), $(wildcard *.cpp))
BETASRCS := $(wildcard beta*.cpp)
BETASRCS += arm_functions.cpp
BETASRCS += wavein.cpp
BETASRCS += waveout.cpp
BETASRCS += test_fx_helper.cpp
FX__OBJS = $(patsubst ../%, $(OBJDIR)/%, $(FX__SRCS:.cpp=.o))
TST_OBJS = $(TST_SRCS:%.cpp=$(OBJDIR)/%.o)
BETAOBJS = $(BETASRCS:%.cpp=$(OBJDIR)/%.o)
all: $(EXE) test
build: $(EXE)
cpp-check: $(FX__SRCS) $(TST_SRCS) $(BETASRCS)
flawfinder ../../src
$(CPPCHECK) $(CHECKFLAGS) $^
test: $(EXE) $(OUTPUT_FOLDER)
rm -rf $(OUTPUT_FOLDER)/*
./$(EXE)
@ -71,5 +83,8 @@ $(OBJDIR)/%.o: ../%.cpp $(OBJDIR)
$(EXE): $(BINDIR) $(TST_OBJS) $(FX__OBJS)
$(LD) $(CXXFLAGS) $(call wildcard,$(TST_OBJS)) $(call wildcard,$(FX__OBJS)) -o $@ $(LIBS)
$(BETA): $(BINDIR) $(BETAOBJS) $(FX__OBJS)
$(LD) $(CXXFLAGS) $(BETAOBJS) $(call wildcard,$(FX__OBJS)) -o $@ $(LIBS)
clean:
rm -rf $(OBJDIR) $(BINDIR) $(OUTPUT_FOLDER)

@ -4,8 +4,10 @@ noExplicitConstructor:*
unusedFunction:*
missingIncludeSystem:*
unmatchedSuppression:*
unreadVariable:test*.cpp
// unexplained exceptions
syntaxError:beta.cpp:52
syntaxError:test_fx_mixing_console.cpp:207
internalAstError:test_cpp_performance.cpp:22
unpreciseMathCall:*

@ -29,7 +29,7 @@ TEST(CppPerformance, LFOPerformance_ComplexLFO_InterpolatedSineOscillator)
}
auto d2 = LAP_TIME("lfo2");
EXPECT_LE(d1, d2);
EXPECT_GE(d1, d2);
}
TEST(CppPerformance, LFOPerformance_ComplexLFO_FastLFO)
@ -67,23 +67,27 @@ TEST(CppPerformance, FastLFOTuning)
full_test_name += test_info->name();
size_t NB = static_cast<size_t>(1.0f * SAMPLING_FREQUENCY);
float32_t freq = 5.0f;
float32_t freq = 1.5f;
FastLFO lfo1(SAMPLING_FREQUENCY, freq, 440.0f);
lfo1.setFrequency(freq);
ComplexLFO lfo2(SAMPLING_FREQUENCY, freq, 440.0f);
InterpolatedSineOscillator lfo2(SAMPLING_FREQUENCY, freq, 440.0f);
lfo2.setFrequency(freq);
std::ofstream out(getResultFile(full_test_name + ".FastLFOTuning-data.csv", true));
ComplexLFO lfo3(SAMPLING_FREQUENCY, freq, 440.0f);
lfo3.setFrequency(freq);
std::ofstream out(getResultFile(full_test_name + ".data.csv", true));
setupOuputStreamForCSV(out);
out << "index;FastLFO;ComplexLFO" << std::endl;
out << "index;FastLFO;InterpolatedSineOscillator;ComplexLFO" << std::endl;
for(size_t i = 0; i < NB; ++i)
{
out
<< i << ";"
<< lfo1.process() << ";"
<< lfo2.process() << std::endl;
<< lfo2.process() << ";"
<< lfo3.process() << std::endl;
}
out.close();
}

@ -7,7 +7,7 @@
#include "../fx_phaser.h"
#include "../fx_delay.h"
#include "../effect_platervbstereo.h"
#include "../fx_shimmer_reverb.h"
#include "../fx_reverberator.h"
TEST(LevelTuning, Tube)
{
@ -241,9 +241,9 @@ TEST(LevelTuning, PlateReverb)
EXPECT_LE(1.0f / ratio, 1.1f);
}
TEST(LevelTuning, ShimmerReverb)
TEST(LevelTuning, Reverberator)
{
ShimmerReverb fx(SAMPLING_FREQUENCY);
Reverberator fx(SAMPLING_FREQUENCY);
fx.reset();
fx.setInputGain(0.35f);
fx.setTime(0.89f);
@ -269,7 +269,7 @@ TEST(LevelTuning, ShimmerReverb)
float32_t ratio = std::sqrt(sumOut / sumIn);
ASSERT_EQ(nb_errors, 0) << "Sample value error for ShimmerReverb";
ASSERT_EQ(nb_errors, 0) << "Sample value error for Reverberator";
EXPECT_GE(ratio, 0.9f);
EXPECT_LE(1.0f / ratio, 1.1f);
}

@ -59,10 +59,10 @@ TEST(FXComponent, SVF)
{
float32_t inL, inR;
float32_t outL, outR;
StateVariableFilter svf(SAMPLING_FREQUENCY, StateVariableFilter::Type::LPF, 12000.0f);
StateVariableFilter svf(SAMPLING_FREQUENCY, StateVariableFilter::FilterMode::LPF, 12000.0f);
{
svf.setFilterType(StateVariableFilter::Type::LPF);
svf.setFilterMode(StateVariableFilter::FilterMode::LPF);
svf.setCutoff(12000.0f);
svf.setResonance(0.0f);
unsigned nbSamples = 0;
@ -83,7 +83,7 @@ TEST(FXComponent, SVF)
}
{
svf.setFilterType(StateVariableFilter::Type::LPF);
svf.setFilterMode(StateVariableFilter::FilterMode::LPF);
svf.setCutoff(60.0f);
svf.setResonance(0.0f);
unsigned nbSamples = 0;

@ -12,7 +12,7 @@ std::string getScenarioName(int scenario)
bool fxOrbitone = Active(scenario, FXSwitch::FX__Orbitone);
bool fxFlanger = Active(scenario, FXSwitch::FX__Flanger);
bool fxDelay = Active(scenario, FXSwitch::FX__Delay);
bool fxShimmer = Active(scenario, FXSwitch::FX__ShimmerReverb);
bool fxReverberator = Active(scenario, FXSwitch::FX__Reverberator);
bool fxReverb = Active(scenario, FXSwitch::FX__PlateReverb);
bool first = true;
@ -67,7 +67,7 @@ std::string getScenarioName(int scenario)
first = false;
}
if(fxShimmer)
if(fxReverberator)
{
if(!first) ss << ", ";
ss << "Shim";

@ -57,7 +57,7 @@ enum FXSwitch
FX__Orbitone,
FX__Phaser,
FX__Delay,
FX__ShimmerReverb,
FX__Reverberator,
FX__PlateReverb,
__kFXCount
};

@ -40,18 +40,18 @@ void setupRack(FXRack* rack, int scenario)
rack->getDelay()->setEnable(Active(scenario, FXSwitch::FX__Delay));
rack->getDelay()->setWetLevel(0.6f);
rack->getDelay()->setLeftDelayTime(0.15f);
rack->getDelay()->setLeftDelayTime(0.2f);
rack->getDelay()->setLeftDelayTime(0.05f);
rack->getDelay()->setLeftDelayTime(0.07f);
rack->getDelay()->setFeedback(0.35f);
rack->getDelay()->setFlutterRate(0.0f);
rack->getDelay()->setFlutterAmount(0.0f);
rack->getShimmerReverb()->setEnable(Active(scenario, FXSwitch::FX__ShimmerReverb));
rack->getShimmerReverb()->setWetLevel(0.5f);
rack->getShimmerReverb()->setInputGain(0.35f);
rack->getShimmerReverb()->setTime(0.89f);
rack->getShimmerReverb()->setDiffusion(0.75f);
rack->getShimmerReverb()->setLP(0.8f);
rack->getReverberator()->setEnable(Active(scenario, FXSwitch::FX__Reverberator));
rack->getReverberator()->setWetLevel(0.5f);
rack->getReverberator()->setInputGain(0.35f);
rack->getReverberator()->setTime(0.89f);
rack->getReverberator()->setDiffusion(0.75f);
rack->getReverberator()->setLP(0.8f);
}
TEST_P(FXScenarioTest, FXRackResetAllScenarios)
@ -84,4 +84,4 @@ TEST_P(FXScenarioTest, ScenarioProcessing)
CLEANUP_AUDIO_TEST(inSamples, outSamples);
}
INSTANTIATE_TEST_SUITE_P(FXRack, FXScenarioTest, testing::Range(0, 1 << (FXSwitch::FX__ShimmerReverb + 1)));
INSTANTIATE_TEST_SUITE_P(FXRack, FXScenarioTest, testing::Range(0, 1 << (FXSwitch::FX__Reverberator + 1)));

@ -1,9 +1,9 @@
#include <gtest/gtest.h>
#include "test_fx_helper.h"
#include "../fx_shimmer_reverb.h"
#include "../fx_reverberator.h"
TEST(FXShimmerReverb, TransientSilence)
TEST(FXReverberator, TransientSilence)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
@ -19,17 +19,17 @@ TEST(FXShimmerReverb, TransientSilence)
memset(outSamplesL, 0, size * sizeof(float32_t));
memset(outSamplesR, 0, size * sizeof(float32_t));
ShimmerReverb* shimmer = new ShimmerReverb(SAMPLING_FREQUENCY);
Reverberator fx(SAMPLING_FREQUENCY);
shimmer->setInputGain(0.55f);
shimmer->setTime(0.75f);
shimmer->setDiffusion(0.8f);
shimmer->setLP(0.7f);
fx.setInputGain(0.55f);
fx.setTime(0.75f);
fx.setDiffusion(0.8f);
fx.setLP(0.7f);
shimmer->reset();
fx.reset();
for(size_t i = 0; i < size; ++i)
{
shimmer->processSample(
fx.processSample(
inSamples[i],
inSamples[i],
outSamplesL[i],
@ -39,15 +39,13 @@ TEST(FXShimmerReverb, TransientSilence)
saveWaveFile(getResultFile(full_test_name + ".wav", true), outSamplesL, outSamplesR, size, SAMPLING_FREQUENCY, 16);
delete shimmer;
delete[] inSamples;
delete[] outSamplesL;
delete[] outSamplesR;
}
TEST(FXShimmerReverb, TransientSilenceWithDirac)
TEST(FXReverberator, TransientSilenceWithDirac)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
@ -64,17 +62,17 @@ TEST(FXShimmerReverb, TransientSilenceWithDirac)
memset(outSamplesL, 0, size * sizeof(float32_t));
memset(outSamplesR, 0, size * sizeof(float32_t));
ShimmerReverb* shimmer = new ShimmerReverb(SAMPLING_FREQUENCY);
Reverberator fx(SAMPLING_FREQUENCY);
shimmer->setInputGain(0.55f);
shimmer->setTime(0.75f);
shimmer->setDiffusion(0.8f);
shimmer->setLP(0.7f);
fx.setInputGain(0.55f);
fx.setTime(0.75f);
fx.setDiffusion(0.8f);
fx.setLP(0.7f);
shimmer->reset();
fx.reset();
for(size_t i = 0; i < size; ++i)
{
shimmer->processSample(
fx.processSample(
inSamples[i],
inSamples[i],
outSamplesL[i],
@ -84,15 +82,13 @@ TEST(FXShimmerReverb, TransientSilenceWithDirac)
saveWaveFile(getResultFile(full_test_name + ".wav", true), outSamplesL, outSamplesR, size, SAMPLING_FREQUENCY, 16);
delete shimmer;
delete[] inSamples;
delete[] outSamplesL;
delete[] outSamplesR;
}
TEST(FXShimmerReverb, TransientNoise)
TEST(FXReverberator, TransientNoise)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
@ -108,17 +104,17 @@ TEST(FXShimmerReverb, TransientNoise)
memset(outSamplesL, 0, size * sizeof(float32_t));
memset(outSamplesR, 0, size * sizeof(float32_t));
ShimmerReverb* shimmer = new ShimmerReverb(SAMPLING_FREQUENCY);
Reverberator fx(SAMPLING_FREQUENCY);
shimmer->setInputGain(0.55f);
shimmer->setTime(0.75f);
shimmer->setDiffusion(0.8f);
shimmer->setLP(0.7f);
fx.setInputGain(0.55f);
fx.setTime(0.75f);
fx.setDiffusion(0.8f);
fx.setLP(0.7f);
shimmer->reset();
fx.reset();
for(size_t i = 0; i < size; ++i)
{
shimmer->processSample(
fx.processSample(
inSamples[i],
inSamples[i],
outSamplesL[i],
@ -128,15 +124,13 @@ TEST(FXShimmerReverb, TransientNoise)
saveWaveFile(getResultFile(full_test_name + ".wav", true), outSamplesL, outSamplesR, size, SAMPLING_FREQUENCY, 16);
delete shimmer;
delete[] inSamples;
delete[] outSamplesL;
delete[] outSamplesR;
}
TEST(FXShimmerReverb, TransientMusic)
TEST(FXReverberator, TransientMusic)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
@ -151,17 +145,17 @@ TEST(FXShimmerReverb, TransientMusic)
memset(outSamplesL, 0, size * sizeof(float32_t));
memset(outSamplesR, 0, size * sizeof(float32_t));
ShimmerReverb* shimmer = new ShimmerReverb(SAMPLING_FREQUENCY);
Reverberator fx(SAMPLING_FREQUENCY);
shimmer->setInputGain(0.55f);
shimmer->setTime(0.75f);
shimmer->setDiffusion(0.8f);
shimmer->setLP(0.7f);
fx.setInputGain(0.55f);
fx.setTime(0.75f);
fx.setDiffusion(0.8f);
fx.setLP(0.7f);
shimmer->reset();
fx.reset();
for(size_t i = 0; i < size; ++i)
{
shimmer->processSample(
fx.processSample(
inSamples[0][i],
inSamples[1][i],
outSamplesL[i],
@ -171,8 +165,6 @@ TEST(FXShimmerReverb, TransientMusic)
saveWaveFile(getResultFile(full_test_name + ".wav", true), outSamplesL, outSamplesR, size, SAMPLING_FREQUENCY, 16);
delete shimmer;
delete[] inSamples[0];
delete[] inSamples[1];
delete[] inSamples;

@ -1,6 +1,5 @@
#include "test_fx_helper.h"
#include "../fx_dry.h"
#include "../fx_tube.h"
#include "../fx_chorus.h"
#include "../fx_flanger.h"
@ -8,17 +7,7 @@
#include "../fx_phaser.h"
#include "../fx_delay.h"
#include "../effect_platervbstereo.h"
#include "../fx_shimmer_reverb.h"
TEST(UnitFXTuning, Dry)
{
Dry fx(SAMPLING_FREQUENCY);
PREPARE_AUDIO_TEST(size, inSamples, outSamples, full_test_name);
SIMPLE_AUDIO_LOOP(inSamples, outSamples, size, inL, inR, outL, outR, fx);
SAVE_AUDIO_RESULTS(full_test_name, outSamples, size);
CLEANUP_AUDIO_TEST(inSamples, outSamples);
}
#include "../fx_reverberator.h"
TEST(UnitFXTuning, Tube)
{
@ -114,9 +103,9 @@ TEST(UnitFXTuning, PlateReverb)
CLEANUP_AUDIO_TEST(inSamples, outSamples);
}
TEST(UnitFXTuning, ShimmerReverb)
TEST(UnitFXTuning, Reverberator)
{
ShimmerReverb fx(SAMPLING_FREQUENCY);
Reverberator fx(SAMPLING_FREQUENCY);
fx.setInputGain(0.65f);
fx.setTime(0.89f);
fx.setDiffusion(0.75f);
@ -127,4 +116,3 @@ TEST(UnitFXTuning, ShimmerReverb)
SAVE_AUDIO_RESULTS(full_test_name, outSamples, size);
CLEANUP_AUDIO_TEST(inSamples, outSamples);
}

Loading…
Cancel
Save