2nd phase of debugging

pull/409/head
abscisys 2 years ago
parent fe340f2f99
commit 17030e8065
  1. 2
      .gitignore
  2. 2
      src/Makefile
  3. 5
      src/fx_chorus.cpp
  4. 94
      src/fx_components.cpp
  5. 28
      src/fx_components.h
  6. 2
      src/fx_flanger.cpp
  7. 2
      src/fx_flanger.h
  8. 8
      src/fx_phaser.cpp
  9. 4
      src/fx_rack.cpp
  10. 66
      src/fx_rack.h
  11. 3
      src/fx_shimmer_reverb.cpp
  12. 2
      src/fx_shimmer_reverb.h
  13. 116
      src/fx_shimmer_reverb2.cpp
  14. 67
      src/fx_shimmer_reverb2.h
  15. 28
      src/fx_tape_delay.cpp
  16. 33
      src/fx_tape_delay.h
  17. 42
      src/fx_tube.cpp
  18. 8
      src/fx_tube.h
  19. 99
      src/fx_unit.hpp
  20. 293
      src/minidexed.cpp
  21. 49
      src/minidexed.h
  22. 52
      src/performance.ini
  23. 60
      src/performanceconfig.cpp
  24. 24
      src/performanceconfig.h
  25. 83
      src/test/Makefile
  26. 136
      src/test/fxrack_test.cpp
  27. BIN
      src/test/test.wav
  28. 36
      src/test/wave.h
  29. 87
      src/test/wavein.cpp
  30. 84
      src/test/waveout.cpp
  31. 116
      src/test/waveplay.cpp
  32. 16
      src/uimenu.cpp

2
.gitignore vendored

@ -48,4 +48,4 @@ sdcard
.vscode/
# temporary tests
src/test/
src/test/fxrack_test

@ -12,7 +12,7 @@ OBJS = main.o kernel.o minidexed.o config.o userinterface.o uimenu.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_tape_delay.o fx_shimmer_reverb.o fx_rack.o \
fx_tape_delay.o fx_shimmer_reverb2.o fx_rack.o \
uibuttons.o midipin.o
OPTIMIZE = -O3

@ -4,11 +4,14 @@
#define CHORUS_BUFFER_SIZE 8192
#define LFO_MIN_FREQ 0.0f
#define LFO_MAX_FREQ 1.0f
Chorus::Chorus(float32_t sampling_rate, unsigned voices, float32_t rate, float32_t depth, float32_t feedback) :
FXElement(sampling_rate),
NumVoices(voices),
sample_position_ratio_(sampling_rate / 1000.0f),
lfo_(sampling_rate, LFO::Waveform::Sine, 0.01f, 1.0f)
lfo_(sampling_rate, LFO::Waveform::Sine, LFO_MIN_FREQ, LFO_MAX_FREQ)
{
this->delay_buffersL_ = new float32_t*[this->NumVoices];
this->delay_buffersR_ = new float32_t*[this->NumVoices];

@ -2,9 +2,15 @@
#include <cmath>
///////////////////////////////
// Constants implemlentation //
///////////////////////////////
const float32_t Constants::M2PI = 2.0f * PI;
const float32_t Constants::M1_PI = 1.0f / PI;
/////////////////////////
// LFO implemlentation //
/////////////////////////
LFO::LFO(float32_t sampling_rate, Waveform waveform, float32_t min_frequency, float32_t max_frequency) :
FXBase(sampling_rate),
min_frequency_(min_frequency),
@ -47,7 +53,7 @@ void LFO::setNormalizedFrequency(float32_t normalized_frequency)
float32_t LFO::getNormalizedFrequency() const
{
return this->frequency_;
return this->normalized_frequency_;
}
void LFO::setFrequency(float32_t frequency)
@ -62,6 +68,11 @@ void LFO::setFrequency(float32_t frequency)
}
}
float32_t LFO::getFrequency() const
{
return this->frequency_;
}
float32_t LFO::process()
{
float32_t out = 0.0f;
@ -106,3 +117,84 @@ float32_t LFO::process()
return out;
}
////////////////////////////////////
// JitterGenerator implementation //
////////////////////////////////////
JitterGenerator::JitterGenerator(float32_t sampling_rate) :
FXBase(sampling_rate),
rnd_generator_(rnd_device_()),
rnd_distribution_(-1.0f, 1.0f),
phase_(0.0f),
phase_increment_(0.0f)
{
this->setSpeed(1.0f);
this->setMagnitude(0.1f);
}
JitterGenerator::~JitterGenerator()
{
}
void JitterGenerator::setSpeed(float32_t speed)
{
if(this->speed_ != speed)
{
this->speed_ = speed;
this->phase_increment_ = Constants::M2PI * this->speed_ / this->getSamplingRate();
}
}
float32_t JitterGenerator::getSpeed() const
{
return this->speed_;
}
void JitterGenerator::setMagnitude(float32_t magnitude)
{
this->magnitude_ = magnitude;
}
float32_t JitterGenerator::getMagnitude() const
{
return this->magnitude_;
}
float32_t JitterGenerator::process()
{
float32_t out = std::sin(this->phase_);
this->phase_ += this->phase_increment_ * (1.0f + this->magnitude_ * this->rnd_distribution_(this->rnd_generator_));
if(this->phase_ > Constants::M2PI)
{
this->phase_ -= Constants::M2PI;
}
return out;
}
//////////////////////////////////
// softSaturate implemlentation //
//////////////////////////////////
float32_t softSaturate(float32_t in, float32_t threshold)
{
float32_t x = std::abs(in);
float32_t y = 0.0f;
if(x < threshold)
{
y = x;
}
else if(x > threshold)
{
y = threshold + (x - threshold) / (1.0f + std::pow((x - threshold) / (1.0f - threshold), 2.0f));
}
else if(x > 1.0f)
{
y = (threshold + 1.0f) / 2.0f;
}
float32_t g = 2.0f / (1.0f + threshold);
y *= g;
return (in < 0.0f) ? -y : y;
}

@ -107,3 +107,31 @@ private:
const unsigned size_;
T* values_;
};
class JitterGenerator : public FXBase
{
DISALLOW_COPY_AND_ASSIGN(JitterGenerator);
public:
JitterGenerator(float32_t sampling_rate);
virtual ~JitterGenerator();
void setSpeed(float32_t speed);
float32_t getSpeed() const;
void setMagnitude(float32_t magnitude);
float32_t getMagnitude() const;
float32_t process();
private:
std::random_device rnd_device_;
std::mt19937 rnd_generator_;
std::uniform_real_distribution<float32_t> rnd_distribution_;
float32_t speed_;
float32_t magnitude_;
float32_t phase_;
float32_t phase_increment_;
};
float32_t softSaturate(float32_t in, float32_t threshold);

@ -2,8 +2,6 @@
#include <cmath>
#define MAX_FLANGER_DELAY 20.0f
Flanger::Flanger(float32_t sampling_rate, float32_t delay_time, float32_t frequency, float32_t depth, float32_t feedback) :
FXElement(sampling_rate),
MaxDelayLineSize(static_cast<unsigned>(2.0f * MAX_FLANGER_DELAY * sampling_rate / 1000.0f)),

@ -20,6 +20,8 @@
#include "fx_components.h"
#define MAX_FLANGER_DELAY 20.0f
class Flanger : public FXElement
{
DISALLOW_COPY_AND_ASSIGN(Flanger);

@ -27,7 +27,7 @@ void PhaserParameter::computeCoefficients()
void PhaserParameter::setFrequency(float32_t frequency)
{
this->frequency_ = constrain(frequency, 0.1, 10.0);
this->frequency_ = frequency;
this->computeCoefficients();
}
@ -75,7 +75,7 @@ void PhaserStage::processSample(float32_t inL, float32_t inR, float32_t& outL, f
Phaser::Phaser(float32_t sampling_rate, float32_t frequency, float32_t q) :
FXElement(sampling_rate),
params_(sampling_rate, frequency, q),
lfo_(sampling_rate, LFO::Waveform::Sine, 0.1f, 10.0f)
lfo_(sampling_rate, LFO::Waveform::Sine, 0.01f, 1.0f)
{
for(unsigned i = 0; i < NUM_PHASER_STAGES; ++i)
{
@ -109,13 +109,13 @@ void Phaser::processSample(float32_t inL, float32_t inR, float32_t& outL, float3
void Phaser::setFrequency(float32_t frequency)
{
this->params_.setFrequency(frequency);
this->lfo_.setNormalizedFrequency(frequency);
this->params_.setFrequency(this->lfo_.getFrequency());
}
inline float32_t Phaser::getFrequency() const
{
return this->params_.getFrequency();
return this->lfo_.getNormalizedFrequency();
}
void Phaser::setResonance(float32_t q)

@ -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->fxTapeDelay_ = new FXUnit<TapeDelay>(sampling_rate);
this->fxShimmerReverb_ = new FXUnit<ShimmerReverb>(sampling_rate);
this->fxShimmerReverb_ = new ShimmerReverb2(sampling_rate);
this->registerFX(this->fxTube_);
this->registerFX(this->fxChorus_);
@ -144,7 +144,7 @@ FXUnit<TapeDelay>* FXRack::getTapeDelay()
return this->fxTapeDelay_;
}
FXUnit<ShimmerReverb>* FXRack::getShimmerReverb()
ShimmerReverb2* FXRack::getShimmerReverb()
{
return this->fxShimmerReverb_;
}

@ -19,75 +19,17 @@
#pragma once
#include "fx.h"
#include "fx_unit.hpp"
#include "fx_tube.h"
#include "fx_chorus.h"
#include "fx_flanger.h"
#include "fx_orbitone.h"
#include "fx_phaser.h"
#include "fx_tape_delay.h"
#include "fx_shimmer_reverb.h"
#include "fx_shimmer_reverb2.h"
#include <vector>
template<typename _FXElement>
class FXUnit : public virtual _FXElement
{
DISALLOW_COPY_AND_ASSIGN(FXUnit);
public:
FXUnit(float32_t sampling_rate, bool enable = true, float32_t wet_level = 0.5f) :
_FXElement(sampling_rate)
{
this->setEnable(enable);
this->setWetLevel(wet_level);
}
virtual ~FXUnit()
{
}
void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{
if(!this->isEnable() || this->getWetLevel() == 0.0f)
{
outL = inL;
outR = inR;
}
else
{
_FXElement::processSample(inL, inR, outL, outR);
float32_t dry = 1.0f - this->getWetLevel();
outL = this->getWetLevel() * outL + dry * inL;
outR = this->getWetLevel() * outR + dry * inR;
}
}
void setEnable(bool enable = true)
{
this->enable_ = enable;
}
inline bool isEnable() const
{
return this->enable_;
}
void setWetLevel(float32_t wet_level)
{
this->wet_level_ = constrain(wet_level, 0.0f, 1.0f);
}
inline float32_t getWetLevel() const
{
return this->wet_level_;
}
private:
bool enable_;
float32_t wet_level_; // How much the signal is affected by the inner FX (0.0 - 1.0)
};
typedef std::vector<FXElement*> FXChain;
class FXRack : virtual public FX, virtual public FXElement
@ -113,7 +55,7 @@ public:
FXUnit<Orbitone>* getOrbitone();
FXUnit<Phaser>* getPhaser();
FXUnit<TapeDelay>* getTapeDelay();
FXUnit<ShimmerReverb>* getShimmerReverb();
ShimmerReverb2* getShimmerReverb();
private:
void registerFX(FXElement* fx);
@ -128,5 +70,5 @@ private:
FXUnit<Orbitone>* fxOrbitone_;
FXUnit<Phaser>* fxPhaser_;
FXUnit<TapeDelay>* fxTapeDelay_;
FXUnit<ShimmerReverb>* fxShimmerReverb_;
ShimmerReverb2* fxShimmerReverb_;
};

@ -96,9 +96,8 @@ float32_t ShimmerReverb::getRightDelayTime() const
void ShimmerReverb::setShimmerFrequency(float32_t frequency)
{
const static float32_t M2PI = 2.0f * PI;
this->shimmer_frequency_ = constrain(frequency, 0.0f, 1.0f);
this->shimmer_phase_increment_ = M2PI * mapfloat(this->shimmer_frequency_, 0.0f, 1.0f, 20.0f, 20000.0f) / this->getSamplingRate();
this->shimmer_phase_increment_ = Constants::M2PI * mapfloat(this->shimmer_frequency_, 0.0f, 1.0f, 20.0f, 20000.0f) / this->getSamplingRate();
}
float32_t ShimmerReverb::getShimmerFrequency() const

@ -19,7 +19,7 @@
//
#pragma once
#include "fx.h"
#include "fx_components.h"
class ShimmerReverb : public FXElement
{

@ -0,0 +1,116 @@
#include "fx_shimmer_reverb2.h"
#include <cmath>
#include <algorithm>
ShimmerReverb2::ShimmerReverb2( float32_t sampling_rate,
float32_t decay,
float32_t diffusion,
float32_t pitch_shift) :
FXElement(sampling_rate),
FXUnitModule(),
reverb_buffer_index_(0)
{
this->setDecay(decay);
this->setDiffusion(diffusion);
this->setPitchShift(pitch_shift);
}
ShimmerReverb2::~ShimmerReverb2()
{
}
void ShimmerReverb2::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{
if(!this->isEnable())
{
outL = inL;
outR = inR;
return;
}
// Processing left channel
{
// Read the sample from the reverb buffer
float32_t reverb_sample = this->reverb_buffer_L_[this->reverb_buffer_index_];
// Calculate the pitch-shifted sample
float32_t pitch_shift_sample = reverb_sample * this->getPitchShift();
// Interpolate the pitch-shifted sample to the original pitch
float32_t pitch_shift_frac = pitch_shift_sample - std::floor(pitch_shift_sample);
unsigned pitch_shift_index = static_cast<unsigned>(SHIMMER_BUFFER_SIZE + std::floor(pitch_shift_sample)) % SHIMMER_BUFFER_SIZE;
float32_t pitch_shift_interp =
(1.0f - pitch_shift_frac) * this->reverb_buffer_L_[pitch_shift_index] +
pitch_shift_frac * this->reverb_buffer_L_[(pitch_shift_index + 1) % SHIMMER_BUFFER_SIZE];
// Calculate the wet (reverb) and dry (original) samples
float32_t dry_level = 1.0f - this->getWetLevel();
float32_t wet_sample = dry_level * inL + this->getWetLevel() * pitch_shift_interp;
float32_t dry_sample = this->getWetLevel() * inL + dry_level * pitch_shift_interp;
outL = dry_sample;
// Write the wet sample to the reverb buffer with the diffusion coefficient applied
this->reverb_buffer_L_[this->reverb_buffer_index_] = wet_sample + (reverb_sample * (1.0f - this->getDiffusion() / this->getSamplingRate() / this->getDecay()));
}
// Processing right channel
{
// Read the sample from the reverb buffer
float32_t reverb_sample = this->reverb_buffer_R_[this->reverb_buffer_index_];
// Calculate the pitch-shifted sample
float32_t pitch_shift_sample = reverb_sample * this->getPitchShift();
// Interpolate the pitch-shifted sample to the original pitch
float32_t pitch_shift_frac = pitch_shift_sample - std::floor(pitch_shift_sample);
unsigned pitch_shift_index = static_cast<unsigned>(SHIMMER_BUFFER_SIZE + std::floor(pitch_shift_sample)) % SHIMMER_BUFFER_SIZE;
float32_t pitch_shift_interp =
(1.0f - pitch_shift_frac) * this->reverb_buffer_R_[pitch_shift_index] +
pitch_shift_frac * this->reverb_buffer_R_[(pitch_shift_index + 1) % SHIMMER_BUFFER_SIZE];
// Calculate the wet (reverb) and dry (original) samples
float32_t dry_level = 1.0f - this->getWetLevel();
float32_t wet_sample = dry_level * inR + this->getWetLevel() * pitch_shift_interp;
float32_t dry_sample = this->getWetLevel() * inR + dry_level * pitch_shift_interp;
outR = dry_sample;
// Write the wet sample to the reverb buffer with the diffusion coefficient applied
this->reverb_buffer_R_[this->reverb_buffer_index_] = wet_sample + (reverb_sample * (1.0f - this->getDiffusion() / this->getSamplingRate() / this->getDecay()));
}
// Increment the buffer index and wrap around if necessary
this->reverb_buffer_index_ = (this->reverb_buffer_index_ + 1) % SHIMMER_BUFFER_SIZE;
}
void ShimmerReverb2::setDecay(float32_t decay)
{
this->decay_ = constrain(decay, SHIMMER_MIN_DECAY, SHIMMER_MAX_DECAY);
}
float32_t ShimmerReverb2::getDecay() const
{
return this->decay_;
}
void ShimmerReverb2::setDiffusion(float32_t diffusion)
{
this->diffusion_ = constrain(diffusion, 0.0f, 1.0f);
}
float32_t ShimmerReverb2::getDiffusion() const
{
return this->diffusion_;
}
void ShimmerReverb2::setPitchShift(float32_t pitch_shift)
{
this->pitch_shift_ = constrain(pitch_shift, SHIMMER_MIN_PITCH_RATIO, SHIMMER_MAX_PITCH_RATIO);
}
float32_t ShimmerReverb2::getPitchShift() const
{
return this->pitch_shift_;
}

@ -0,0 +1,67 @@
// 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_reverb2.h
//
// Stereo Shimmer reverb proposed in the context of the MiniDexed project
//
#pragma once
#include "fx_components.h"
#include "fx_unit.hpp"
#define SHIMMER_BUFFER_SIZE 1024
#define SHIMMER_MIN_DECAY 0.0f
#define SHIMMER_MAX_DECAY 10.0f
#define SHIMMER_MIN_PITCH_RATIO 0.5f
#define SHIMMER_MAX_PITCH_RATIO 2.0f
class ShimmerReverb2 :
public virtual FXElement,
public virtual FXUnitModule
{
DISALLOW_COPY_AND_ASSIGN(ShimmerReverb2);
public:
ShimmerReverb2( float32_t sampling_rate,
float32_t decay = 3.0f,
float32_t diffusion = 0.5f,
float32_t pitch_shift = 2.0f);
virtual ~ShimmerReverb2();
virtual void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) override;
void setDecay(float32_t delay_time_L);
float32_t getDecay() const;
void setDiffusion(float32_t delay_time_R);
float32_t getDiffusion() const;
void setPitchShift(float32_t frequency);
float32_t getPitchShift() const;
private:
float32_t reverb_buffer_L_[SHIMMER_BUFFER_SIZE];
float32_t reverb_buffer_R_[SHIMMER_BUFFER_SIZE];
unsigned reverb_buffer_index_;
// Current write position for left and right channel delay lines
float32_t decay_; // Reverb decay time in seconds (0 - 10)
float32_t diffusion_; // The degree to which the reverb is spread out over time (0 - 1)
float32_t pitch_shift_; // Determines the pitch shift ratio applied to the reverb (0.5 - 2.0)
};

@ -3,7 +3,7 @@
#include <cmath>
#define MAX_DELAY_TIME 1.0f
#define MAX_FLUTTER_DELAY_TIME 0.1f
#define MAX_FLUTTER_DELAY_TIME 0.01f
#define LPF_CUTOFF_REF 14000.0f
#define HPF_CUTOFF_REF 60.0f
@ -40,8 +40,7 @@ TapeDelay::TapeDelay(const float32_t sampling_rate, float32_t default_delay_time
read_pos_L_(0),
read_pos_R_(0),
filter_(sampling_rate),
rnd_generator_(rnd_device_()),
rnd_distribution_(-1.0f, 1.0f)
jitter_generator_(sampling_rate)
{
this->buffer_L_ = new float32_t[this->MaxSampleDelayTime];
this->buffer_R_ = new float32_t[this->MaxSampleDelayTime];
@ -52,7 +51,7 @@ TapeDelay::TapeDelay(const float32_t sampling_rate, float32_t default_delay_time
this->setLeftDelayTime(default_delay_time);
this->setRightDelayTime(default_delay_time);
this->setFlutterLevel(default_flutter_level);
this->setFeedbakLevel(default_feedback_level);
this->setFeedbak(default_feedback_level);
}
TapeDelay::~TapeDelay()
@ -63,28 +62,21 @@ TapeDelay::~TapeDelay()
void TapeDelay::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{
int step = 0;
cout << "Delay processing" << endl;
cout << "Processing #" << (++step) << ": Calculate the fluttered delay time" << endl;
// 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() + fluttered_delay_time) * this->getSamplingRate();
float32_t fluttered_delay_time_R = (MAX_DELAY_TIME * this->getRightDelayTime() + fluttered_delay_time) * this->getSamplingRate();
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();
cout << "Processing #" << (++step) << ": Calculate write positions" << endl;
// 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;
cout << "Processing #" << (++step) << ": Write input to delay buffers" << endl;
// Write input to delay buffers
this->buffer_L_[write_pos_L] = inL;
this->buffer_R_[write_pos_R] = inR;
cout << "Processing #" << (++step) << ": Read from delay buffers and apply feedback" << endl;
// Read from delay buffers and apply feedback
this->filter_.processSample(
this->buffer_L_[this->read_pos_L_],
@ -92,13 +84,10 @@ cout << "Processing #" << (++step) << ": Read from delay buffers and apply feedb
outL,
outR
);
// outL = this->buffer_L_[this->read_pos_L_];
// outR = this->buffer_R_[this->read_pos_R_];
this->buffer_L_[write_pos_L] += outL * this->getFeedbackLevel();
this->buffer_R_[write_pos_R] += outR * this->getFeedbackLevel();
cout << "Processing #" << (++step) << ": Increment read positions" << endl;
// Increment read positions
++this->read_pos_L_;
if(this->read_pos_L_ >= this->MaxSampleDelayTime)
@ -110,7 +99,6 @@ cout << "Processing #" << (++step) << ": Increment read positions" << endl;
{
this->read_pos_R_ -= this->MaxSampleDelayTime;
}
cout << "Processing #" << (++step) << ": Completed" << endl;
}
void TapeDelay::setLeftDelayTime(float32_t delay_time)
@ -136,6 +124,8 @@ float32_t TapeDelay::getRightDelayTime() const
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
@ -143,7 +133,7 @@ float32_t TapeDelay::getFlutterLevel() const
return this->flutter_level_;
}
void TapeDelay::setFeedbakLevel(float32_t feedback)
void TapeDelay::setFeedbak(float32_t feedback)
{
this->feedback_ = constrain(feedback, 0.0, 1.0);
}
@ -156,7 +146,7 @@ float32_t TapeDelay::getFeedbackLevel() const
float32_t TapeDelay::getFlutteredDelayTime()
{
// Genarate a random number in the range [-1.0 , 1.0]
float32_t r = this->rnd_distribution_(this->rnd_generator_);
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();

@ -19,7 +19,7 @@
//
#pragma once
#include "fx.h"
#include "fx_components.h"
#include "fx_svf.h"
#include <random>
@ -41,30 +41,6 @@ class TapeDelay : public FXElement
void setCutoffChangeRatio(float32_t ratio);
private:
// void processSampleLPF(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR);
// void processSampleHPF(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR);
// float32_t a0_lpf_;
// float32_t a1_lpf_;
// float32_t a2_lpf_;
// float32_t b1_lpf_;
// float32_t b2_lpf_;
// float32_t x1_lpf_[2];
// float32_t x2_lpf_[2];
// float32_t y1_lpf_[2];
// float32_t y2_lpf_[2];
// float32_t a0_hpf_;
// float32_t a1_hpf_;
// float32_t a2_hpf_;
// float32_t b1_hpf_;
// float32_t b2_hpf_;
// float32_t x1_hpf_[2];
// float32_t x2_hpf_[2];
// float32_t y1_hpf_[2];
// float32_t y2_hpf_[2];
StateVariableFilter lpf_;
StateVariableFilter hpf_;
};
@ -85,7 +61,7 @@ public:
void setFlutterLevel(float32_t flutter_level);
float32_t getFlutterLevel() const;
void setFeedbakLevel(float32_t feedback);
void setFeedbak(float32_t feedback);
float32_t getFeedbackLevel() const;
private:
@ -103,8 +79,5 @@ private:
float32_t feedback_; // Feedback (0.0 - 1.0)
LowHighPassFilter filter_;
std::random_device rnd_device_;
std::mt19937 rnd_generator_;
std::uniform_real_distribution<float32_t> rnd_distribution_;
JitterGenerator jitter_generator_;
};

@ -2,11 +2,10 @@
#include <cmath>
Tube::Tube(float32_t samplingRate, float32_t curve, float32_t bias) :
FXElement(samplingRate),
TubeCurve(curve),
TubeBias(bias)
Tube::Tube(float32_t samplingRate) :
FXElement(samplingRate)
{
this->setOverdrive(0.0f);
}
Tube::~Tube()
@ -15,43 +14,14 @@ Tube::~Tube()
void Tube::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{
float32_t absInL = abs(inL);
float32_t coeff = this->TubeCurve + this->getOverdrive();
if(absInL > this->TubeBias)
{
outL = coeff * (absInL - this->TubeBias) / (1.0f - this->TubeBias);
}
else
{
outL = coeff * absInL / (1.0f + this->TubeBias * absInL);
}
if(inL < 0.0f)
{
outL = -outL;
}
float32_t absInR = abs(inR);
if(absInR > this->TubeBias)
{
outR = coeff * (absInR - this->TubeBias) / (1.0f - this->TubeBias);
}
else
{
outR = coeff * absInR / (1.0f + this->TubeBias * absInR);
}
if(inR < 0.0f)
{
outR = -outR;
}
outL = softSaturate(inL, this->threshold_);
outR = softSaturate(inR, this->threshold_);
}
void Tube::setOverdrive(float32_t overdrive)
{
this->overdrive_ = constrain(overdrive, 0.0f, 1.0f);
this->threshold_ = 1.0f - this->overdrive_;
}
float32_t Tube::getOverdrive() const

@ -18,14 +18,14 @@
//
#pragma once
#include "fx.h"
#include "fx_components.h"
class Tube : public FXElement
{
DISALLOW_COPY_AND_ASSIGN(Tube);
public:
Tube(float32_t sampling_rate, float32_t curve = 2.0f, float32_t bias = 0.7f);
Tube(float32_t sampling_rate);
virtual ~Tube();
virtual void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) override;
@ -34,8 +34,6 @@ public:
float32_t getOverdrive() const;
private:
const float32_t TubeCurve;
const float32_t TubeBias;
float32_t overdrive_;
float32_t threshold_;
};

@ -0,0 +1,99 @@
// 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_unit.h
//
// Unit of FX that handle enable and wet parameters
//
#pragma once
#include "fx_components.h"
class FXUnitModule
{
DISALLOW_COPY_AND_ASSIGN(FXUnitModule);
public:
FXUnitModule(bool enable = true, float32_t wet_level = 0.5f)
{
this->setEnable(enable);
this->setWetLevel(wet_level);
}
virtual ~FXUnitModule()
{
}
virtual void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) = 0;
void setEnable(bool enable = true)
{
this->enable_ = enable;
}
inline bool isEnable() const
{
return this->enable_;
}
void setWetLevel(float32_t wet_level)
{
this->wet_level_ = constrain(wet_level, 0.0f, 1.0f);
}
inline float32_t getWetLevel() const
{
return this->wet_level_;
}
protected:
bool enable_;
float32_t wet_level_; // How much the signal is affected by the inner FX (0.0 - 1.0)
};
template<typename _FXElement>
class FXUnit : public virtual FXUnitModule, public virtual _FXElement
{
DISALLOW_COPY_AND_ASSIGN(FXUnit);
public:
FXUnit(float32_t sampling_rate, bool enable = true, float32_t wet_level = 0.5f) :
FXUnitModule(),
_FXElement(sampling_rate)
{
this->setEnable(enable);
this->setWetLevel(wet_level);
}
virtual ~FXUnit()
{
}
void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{
if(!this->isEnable() || this->getWetLevel() == 0.0f)
{
outL = inL;
outR = inR;
}
else
{
_FXElement::processSample(inL, inR, outL, outR);
float32_t dry = 1.0f - this->getWetLevel();
outL = this->getWetLevel() * outL + dry * inL;
outR = this->getWetLevel() * outR + dry * inR;
}
}
};

@ -208,11 +208,9 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
// FXChain > ShimmerReverb parameters
this->SetParameter(ParameterFXChainShimmerReverbEnable, 1);
this->SetParameter(ParameterFXChainShimmerReverbWet, 70);
this->SetParameter(ParameterFXChainShimmerReverbDelayTimeLeft, 15);
this->SetParameter(ParameterFXChainShimmerReverbDelayTimeRight, 22);
this->SetParameter(ParameterFXChainShimmerReverbFrequency, 20);
this->SetParameter(ParameterFXChainShimmerReverbAmplitude, 15);
this->SetParameter(ParameterFXChainShimmerReverbDecayTime, 65);
this->SetParameter(ParameterFXChainShimmerReverbDecay, 30);
this->SetParameter(ParameterFXChainShimmerReverbDiffusion, 80);
this->SetParameter(ParameterFXChainShimmerReverbPitchShift, 99);
#endif
// END setup FXRack
};
@ -749,13 +747,13 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue)
case ParameterFXChainEnable:
nValue = constrain((int)nValue, 0, 1);
this->m_FXSpinLock.Acquire();
this->setFXChainEnable(!!nValue);
this->fx_rack->setEnable(!!nValue);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainWet:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainWet(nValue / 99.0f);
this->fx_rack->setWetLevel(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
@ -763,19 +761,19 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue)
case ParameterFXChainTubeEnable:
nValue = constrain((int)nValue, 0, 1);
this->m_FXSpinLock.Acquire();
this->setFXChainTubeEnable(!!nValue);
this->fx_rack->getTube()->setEnable(!!nValue);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainTubeWet:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainTubeWet(nValue / 99.0f);
this->fx_rack->getTube()->setWetLevel(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainTubeOverdrive:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainTubeOverdrive(nValue / 99.0f);
this->fx_rack->getTube()->setOverdrive(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
@ -783,31 +781,31 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue)
case ParameterFXChainChorusEnable:
nValue = constrain((int)nValue, 0, 1);
this->m_FXSpinLock.Acquire();
this->setFXChainChorusEnable(!!nValue);
this->fx_rack->getChorus()->setEnable(!!nValue);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainChorusWet:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainChorusWet(nValue / 99.0f);
this->fx_rack->getChorus()->setWetLevel(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainChorusRate:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainChorusRate(mapfloat(nValue, 0, 99, 0.1f, 1.0f));
this->fx_rack->getChorus()->setRate(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainChorusDepth:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainChorusDepth(nValue / 9.9f);
this->fx_rack->getChorus()->setDepth(nValue / 9.9f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainChorusFeedback:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainChorusFeedback(nValue / 99.0f);
this->fx_rack->getChorus()->setFeedback(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
@ -815,37 +813,37 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue)
case ParameterFXChainFlangerEnable:
nValue = constrain((int)nValue, 0, 1);
this->m_FXSpinLock.Acquire();
this->setFXChainFlangerEnable(!!nValue);
this->fx_rack->getFlanger()->setEnable(!!nValue);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainFlangerWet:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainFlangerWet(nValue / 99.0f);
this->fx_rack->getFlanger()->setWetLevel(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainFlangerDelayTime:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainFlangerDelayTime(nValue / 9.9f);
this->fx_rack->getFlanger()->setDelayTime(mapfloat(nValue, 0, 99, 1.0f, MAX_FLANGER_DELAY));
this->m_FXSpinLock.Release();
break;
case ParameterFXChainFlangerRate:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainFlangerRate(0.1f + nValue / 9.8f);
this->fx_rack->getFlanger()->setFrequency(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainFlangerDepth:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainFlangerDepth(nValue / 9.9f);
this->fx_rack->getFlanger()->setDepth(mapfloat(nValue, 0, 99, 0.0f, MAX_FLANGER_DELAY));
this->m_FXSpinLock.Release();
break;
case ParameterFXChainFlangerFeedback:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainFlangerFeedback(nValue / 99.0f);
this->fx_rack->getFlanger()->setFeedback(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
@ -853,19 +851,19 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue)
case ParameterFXChainOrbitoneEnable:
nValue = constrain((int)nValue, 0, 1);
this->m_FXSpinLock.Acquire();
this->setFXChainOrbitoneEnable(!!nValue);
this->fx_rack->getOrbitone()->setEnable(!!nValue);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainOrbitoneWet:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainOrbitoneWet(nValue / 99.0f);
this->fx_rack->getOrbitone()->setWetLevel(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainOrbitoneFeedback:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainOrbitoneFeedback(nValue / 99.0f);
this->fx_rack->getOrbitone()->setFeedback(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
@ -873,25 +871,25 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue)
case ParameterFXChainPhaserEnable:
nValue = constrain((int)nValue, 0, 1);
this->m_FXSpinLock.Acquire();
this->setFXChainPhaserEnable(!!nValue);
this->fx_rack->getPhaser()->setEnable(!!nValue);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainPhaserWet:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainPhaserWet(nValue / 99.0f);
this->fx_rack->getPhaser()->setWetLevel(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainPhaserRate:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainPhaserRate(mapfloat(nValue, 0, 99, 0.01f, 5.0f));
this->fx_rack->getPhaser()->setFrequency(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainPhaserResonance:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainPhaserResonance(mapfloat(nValue, 0, 99, 0.5f, 10.0f));
this->fx_rack->getPhaser()->setResonance(mapfloat(nValue, 0, 99, 0.5f, 10.0f));
this->m_FXSpinLock.Release();
break;
@ -899,37 +897,37 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue)
case ParameterFXChainTapeDelayEnable:
nValue = constrain((int)nValue, 0, 1);
this->m_FXSpinLock.Acquire();
this->setFXChainTapeDelayEnable(!!nValue);
this->fx_rack->getTapeDelay()->setEnable(!!nValue);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainTapeDelayWet:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainTapeDelayWet(nValue / 99.0f);
this->fx_rack->getTapeDelay()->setWetLevel(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainTapeDelayLeftDelayTime:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainTapeDelayLeftDelayTime(nValue / 99.0f);
this->fx_rack->getTapeDelay()->setLeftDelayTime(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainTapeDelayRightDelayTime:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainTapeDelayRightDelayTime(nValue / 99.0f);
this->fx_rack->getTapeDelay()->setRightDelayTime(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainTapeDelayFlutter:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainTapeDelayFlutter(nValue / 99.0f);
this->fx_rack->getTapeDelay()->setFlutterLevel(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainTapeDelayFeedback:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainTapeDelayFeedback(nValue / 99.0f);
this->fx_rack->getTapeDelay()->setFeedbak(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
@ -937,43 +935,31 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue)
case ParameterFXChainShimmerReverbEnable:
nValue = constrain((int)nValue, 0, 1);
this->m_FXSpinLock.Acquire();
this->setFXChainShimmerReverbEnable(!!nValue);
this->fx_rack->getShimmerReverb()->setEnable(!!nValue);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainShimmerReverbWet:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainShimmerReverbWet(nValue / 99.0f);
this->fx_rack->getShimmerReverb()->setWetLevel(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainShimmerReverbDelayTimeLeft:
case ParameterFXChainShimmerReverbDecay:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainShimmerReverbDelayTimeLeft(nValue / 99.0f);
this->fx_rack->getShimmerReverb()->setDecay(mapfloat(nValue, 0, 99, SHIMMER_MIN_DECAY, SHIMMER_MAX_DECAY));
this->m_FXSpinLock.Release();
break;
case ParameterFXChainShimmerReverbDelayTimeRight:
case ParameterFXChainShimmerReverbDiffusion:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainShimmerReverbDelayTimeRight(nValue / 99.0f);
this->fx_rack->getShimmerReverb()->setDiffusion(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainShimmerReverbFrequency:
case ParameterFXChainShimmerReverbPitchShift:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainShimmerReverbFrequency(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainShimmerReverbAmplitude:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainShimmerReverbAmplitude(nValue / 99.0f);
this->m_FXSpinLock.Release();
break;
case ParameterFXChainShimmerReverbDecayTime:
nValue = constrain((int)nValue, 0, 99);
this->m_FXSpinLock.Acquire();
this->setFXChainShimmerReverbDecayTime(nValue / 99.0f);
this->fx_rack->getShimmerReverb()->setPitchShift(mapfloat(nValue, 0, 99, SHIMMER_MIN_PITCH_RATIO, SHIMMER_MAX_PITCH_RATIO));
this->m_FXSpinLock.Release();
break;
#endif
@ -1429,11 +1415,9 @@ bool CMiniDexed::DoSavePerformance (void)
this->m_PerformanceConfig.SetFXChainTapeDelayFeedback(this->m_nParameter[ParameterFXChainTapeDelayFeedback]);
this->m_PerformanceConfig.SetFXChainShimmerReverbEnable(!!this->m_nParameter[ParameterFXChainShimmerReverbEnable]);
this->m_PerformanceConfig.SetFXChainShimmerReverbWet(this->m_nParameter[ParameterFXChainShimmerReverbWet]);
this->m_PerformanceConfig.SetFXChainShimmerReverbDelayTimeLeft(this->m_nParameter[ParameterFXChainShimmerReverbDelayTimeLeft]);
this->m_PerformanceConfig.SetFXChainShimmerReverbDelayTimeRight(this->m_nParameter[ParameterFXChainShimmerReverbDelayTimeRight]);
this->m_PerformanceConfig.SetFXChainShimmerReverbFrequency(this->m_nParameter[ParameterFXChainShimmerReverbFrequency]);
this->m_PerformanceConfig.SetFXChainShimmerReverbAmplitude(this->m_nParameter[ParameterFXChainShimmerReverbAmplitude]);
this->m_PerformanceConfig.SetFXChainShimmerReverbDecayTime(this->m_nParameter[ParameterFXChainShimmerReverbDecayTime]);
this->m_PerformanceConfig.SetFXChainShimmerReverbDecay(this->m_nParameter[ParameterFXChainShimmerReverbDecay]);
this->m_PerformanceConfig.SetFXChainShimmerReverbDiffusion(this->m_nParameter[ParameterFXChainShimmerReverbDiffusion]);
this->m_PerformanceConfig.SetFXChainShimmerReverbPitchShift(this->m_nParameter[ParameterFXChainShimmerReverbPitchShift]);
#endif
// END FXRack parameters
@ -1858,11 +1842,9 @@ void CMiniDexed::LoadPerformanceParameters(void)
this->SetParameter(ParameterFXChainTapeDelayFeedback, this->m_PerformanceConfig.GetFXChainTapeDelayFeedback());
this->SetParameter(ParameterFXChainShimmerReverbEnable, this->m_PerformanceConfig.GetFXChainShimmerReverbEnable());
this->SetParameter(ParameterFXChainShimmerReverbWet, this->m_PerformanceConfig.GetFXChainShimmerReverbWet());
this->SetParameter(ParameterFXChainShimmerReverbDelayTimeLeft, this->m_PerformanceConfig.GetFXChainShimmerReverbDelayTimeLeft());
this->SetParameter(ParameterFXChainShimmerReverbDelayTimeRight, this->m_PerformanceConfig.GetFXChainShimmerReverbDelayTimeRight());
this->SetParameter(ParameterFXChainShimmerReverbFrequency, this->m_PerformanceConfig.GetFXChainShimmerReverbFrequency());
this->SetParameter(ParameterFXChainShimmerReverbAmplitude, this->m_PerformanceConfig.GetFXChainShimmerReverbAmplitude());
this->SetParameter(ParameterFXChainShimmerReverbDecayTime, this->m_PerformanceConfig.GetFXChainShimmerReverbDecayTime());
this->SetParameter(ParameterFXChainShimmerReverbDecay, this->m_PerformanceConfig.GetFXChainShimmerReverbDecay());
this->SetParameter(ParameterFXChainShimmerReverbDiffusion, this->m_PerformanceConfig.GetFXChainShimmerReverbDiffusion());
this->SetParameter(ParameterFXChainShimmerReverbPitchShift, this->m_PerformanceConfig.GetFXChainShimmerReverbPitchShift());
#endif
}
@ -2047,186 +2029,3 @@ unsigned CMiniDexed::getModController (unsigned controller, unsigned parameter,
}
}
#ifdef FXRACK_ENABLE
void CMiniDexed::setFXChainEnable(bool value)
{
this->fx_rack->setEnable(value);
}
void CMiniDexed::setFXChainWet(float32_t value)
{
this->fx_rack->setWetLevel(value);
}
void CMiniDexed::setFXChainTubeEnable(bool value)
{
this->fx_rack->getTube()->setEnable(value);
}
void CMiniDexed::setFXChainTubeWet(float32_t value)
{
this->fx_rack->getTube()->setWetLevel(value);
}
void CMiniDexed::setFXChainTubeOverdrive(float32_t value)
{
this->fx_rack->getTube()->setOverdrive(value);
}
void CMiniDexed::setFXChainChorusEnable(bool value)
{
this->fx_rack->getChorus()->setEnable(value);
}
void CMiniDexed::setFXChainChorusWet(float32_t value)
{
this->fx_rack->getChorus()->setWetLevel(value);
}
void CMiniDexed::setFXChainChorusRate(float32_t value)
{
this->fx_rack->getChorus()->setRate(value);
}
void CMiniDexed::setFXChainChorusDepth(float32_t value)
{
this->fx_rack->getChorus()->setDepth(value);
}
void CMiniDexed::setFXChainChorusFeedback(float32_t value)
{
this->fx_rack->getChorus()->setFeedback(value);
}
void CMiniDexed::setFXChainFlangerEnable(bool value)
{
this->fx_rack->getFlanger()->setEnable(value);
}
void CMiniDexed::setFXChainFlangerWet(float32_t value)
{
this->fx_rack->getFlanger()->setWetLevel(value);
}
void CMiniDexed::setFXChainFlangerDelayTime(float32_t value)
{
this->fx_rack->getFlanger()->setDelayTime(value);
}
void CMiniDexed::setFXChainFlangerRate(float32_t value)
{
this->fx_rack->getFlanger()->setFrequency(value);
}
void CMiniDexed::setFXChainFlangerDepth(float32_t value)
{
this->fx_rack->getFlanger()->setDepth(value);
}
void CMiniDexed::setFXChainFlangerFeedback(float32_t value)
{
this->fx_rack->getFlanger()->setFeedback(value);
}
void CMiniDexed::setFXChainOrbitoneEnable(bool value)
{
this->fx_rack->getOrbitone()->setEnable(value);
}
void CMiniDexed::setFXChainOrbitoneWet(float32_t value)
{
this->fx_rack->getOrbitone()->setWetLevel(value);
}
void CMiniDexed::setFXChainOrbitoneFeedback(float32_t value)
{
this->fx_rack->getOrbitone()->setFeedback(value);
}
void CMiniDexed::setFXChainPhaserEnable(bool value)
{
this->fx_rack->getPhaser()->setEnable(value);
}
void CMiniDexed::setFXChainPhaserWet(float32_t value)
{
this->fx_rack->getPhaser()->setWetLevel(value);
}
void CMiniDexed::setFXChainPhaserRate(float32_t value)
{
this->fx_rack->getPhaser()->setFrequency(value);
}
void CMiniDexed::setFXChainPhaserResonance(float32_t value)
{
this->fx_rack->getPhaser()->setResonance(value);
}
void CMiniDexed::setFXChainTapeDelayEnable(bool value)
{
this->fx_rack->getTapeDelay()->setEnable(value);
}
void CMiniDexed::setFXChainTapeDelayWet(float32_t value)
{
this->fx_rack->getTapeDelay()->setWetLevel(value);
}
void CMiniDexed::setFXChainTapeDelayLeftDelayTime(float32_t value)
{
this->fx_rack->getTapeDelay()->setLeftDelayTime(value);
}
void CMiniDexed::setFXChainTapeDelayRightDelayTime(float32_t value)
{
this->fx_rack->getTapeDelay()->setRightDelayTime(value);
}
void CMiniDexed::setFXChainTapeDelayFlutter(float32_t value)
{
this->fx_rack->getTapeDelay()->setFlutterLevel(value);
}
void CMiniDexed::setFXChainTapeDelayFeedback(float32_t value)
{
this->fx_rack->getTapeDelay()->setFeedbakLevel(value);
}
void CMiniDexed::setFXChainShimmerReverbEnable(bool value)
{
this->fx_rack->getShimmerReverb()->setEnable(value);
}
void CMiniDexed::setFXChainShimmerReverbWet(float32_t value)
{
this->fx_rack->getShimmerReverb()->setWetLevel(value);
}
void CMiniDexed::setFXChainShimmerReverbDelayTimeLeft(float32_t value)
{
this->fx_rack->getShimmerReverb()->setLeftDelayTime(value);
}
void CMiniDexed::setFXChainShimmerReverbDelayTimeRight(float32_t value)
{
this->fx_rack->getShimmerReverb()->setRightDelayTime(value);
}
void CMiniDexed::setFXChainShimmerReverbFrequency(float32_t value)
{
this->fx_rack->getShimmerReverb()->setShimmerFrequency(value);
}
void CMiniDexed::setFXChainShimmerReverbAmplitude(float32_t value)
{
this->fx_rack->getShimmerReverb()->setShimmerAmplitude(value);
}
void CMiniDexed::setFXChainShimmerReverbDecayTime(float32_t value)
{
this->fx_rack->getShimmerReverb()->setDecayTime(value);
}
#endif

@ -188,11 +188,9 @@ public:
// FXChain > ShimmerReverb parameters
ParameterFXChainShimmerReverbEnable,
ParameterFXChainShimmerReverbWet,
ParameterFXChainShimmerReverbDelayTimeLeft,
ParameterFXChainShimmerReverbDelayTimeRight,
ParameterFXChainShimmerReverbFrequency,
ParameterFXChainShimmerReverbAmplitude,
ParameterFXChainShimmerReverbDecayTime,
ParameterFXChainShimmerReverbDecay,
ParameterFXChainShimmerReverbDiffusion,
ParameterFXChainShimmerReverbPitchShift,
#endif
// END FXRack global parameters definition
@ -264,47 +262,6 @@ public:
void setMasterVolume (float32_t vol);
// BEGIN FXRack parameters setters
#ifdef FXRACK_ENABLE
void setFXChainEnable(bool value);
void setFXChainWet(float32_t value);
void setFXChainTubeEnable(bool value);
void setFXChainTubeWet(float32_t value);
void setFXChainTubeOverdrive(float32_t value);
void setFXChainChorusEnable(bool value);
void setFXChainChorusWet(float32_t value);
void setFXChainChorusRate(float32_t value);
void setFXChainChorusDepth(float32_t value);
void setFXChainChorusFeedback(float32_t value);
void setFXChainFlangerEnable(bool value);
void setFXChainFlangerWet(float32_t value);
void setFXChainFlangerDelayTime(float32_t value);
void setFXChainFlangerRate(float32_t value);
void setFXChainFlangerDepth(float32_t value);
void setFXChainFlangerFeedback(float32_t value);
void setFXChainOrbitoneEnable(bool value);
void setFXChainOrbitoneWet(float32_t value);
void setFXChainOrbitoneFeedback(float32_t value);
void setFXChainPhaserEnable(bool value);
void setFXChainPhaserWet(float32_t value);
void setFXChainPhaserRate(float32_t value);
void setFXChainPhaserResonance(float32_t value);
void setFXChainTapeDelayEnable(bool value);
void setFXChainTapeDelayWet(float32_t value);
void setFXChainTapeDelayLeftDelayTime(float32_t value);
void setFXChainTapeDelayRightDelayTime(float32_t value);
void setFXChainTapeDelayFlutter(float32_t value);
void setFXChainTapeDelayFeedback(float32_t value);
void setFXChainShimmerReverbEnable(bool value);
void setFXChainShimmerReverbWet(float32_t value);
void setFXChainShimmerReverbDelayTimeLeft(float32_t value);
void setFXChainShimmerReverbDelayTimeRight(float32_t value);
void setFXChainShimmerReverbFrequency(float32_t value);
void setFXChainShimmerReverbAmplitude(float32_t value);
void setFXChainShimmerReverbDecayTime(float32_t value);
#endif
// END FXRack parameters setters
private:
int16_t ApplyNoteLimits (int16_t pitch, unsigned nTG); // returns < 0 to ignore note
uint8_t m_uchOPMask[CConfig::ToneGenerators];

@ -36,7 +36,7 @@ BankNumber1=0
VoiceNumber1=1
MIDIChannel1=255
Volume1=100
Pan1=0
Pan1=64
Detune1=-11
Cutoff1=99
Resonance1=0
@ -64,7 +64,7 @@ AftertouchTarget1=0
BankNumber2=0
VoiceNumber2=1
MIDIChannel2=255
Volume2=100
Volume2=0
Pan2=127
Detune2=11
Cutoff2=99
@ -93,7 +93,7 @@ AftertouchTarget2=0
BankNumber3=0
VoiceNumber3=1
MIDIChannel3=255
Volume3=100
Volume3=0
Pan3=48
Detune3=-7
Cutoff3=99
@ -122,7 +122,7 @@ AftertouchTarget3=0
BankNumber4=0
VoiceNumber4=1
MIDIChannel4=255
Volume4=100
Volume4=0
Pan4=80
Detune4=7
Cutoff4=99
@ -151,7 +151,7 @@ AftertouchTarget4=0
BankNumber5=0
VoiceNumber5=1
MIDIChannel5=0
Volume5=100
Volume5=0
Pan5=64
Detune5=0
Cutoff5=99
@ -180,7 +180,7 @@ AftertouchTarget5=0
BankNumber6=0
VoiceNumber6=1
MIDIChannel6=0
Volume6=100
Volume6=0
Pan6=64
Detune6=0
Cutoff6=99
@ -209,7 +209,7 @@ AftertouchTarget6=0
BankNumber7=0
VoiceNumber7=1
MIDIChannel7=0
Volume7=100
Volume7=0
Pan7=64
Detune7=0
Cutoff7=99
@ -238,7 +238,7 @@ AftertouchTarget7=0
BankNumber8=0
VoiceNumber8=1
MIDIChannel8=0
Volume8=100
Volume8=0
Pan8=64
Detune8=0
Cutoff8=99
@ -282,3 +282,39 @@ ReverbLowDamp=50
ReverbLowPass=30
ReverbDiffusion=65
ReverbLevel=99
# FXRack
FXChainEnable=1
FXChainWet=99
FXChainTubeEnable=0
FXChainTubeWet=50
FXChainTubeOverdrive=10
FXChainChorusEnable=0
FXChainChorusWet=50
FXChainChorusRate=15
FXChainChorusDepth=10
FXChainChorusFeedback=20
FXChainFlangerEnable=0
FXChainFlangerWet=50
FXChainFlangerDelayTime=10
FXChainFlangerRate=15
FXChainFlangerDepth=10
FXChainFlangerFeedback=20
FXChainOrbitoneEnable=0
FXChainOrbitoneWet=50
FXChainOrbitoneFeedback=65
FXChainPhaserEnable=0
FXChainPhaserWet=50
FXChainPhaserRate=5
FXChainPhaserResonance=45
FXChainTapeDelayEnable=1
FXChainTapeDelayWet=50
FXChainTapeDelayLeftDelayTime=15
FXChainTapeDelayRightDelayTime=22
FXChainTapeDelayFlutter=0
FXChainTapeDelayFeedback=35
FXChainShimmerReverbEnable=0
FXChainShimmerReverbWet=70
FXChainShimmerReverbDecay=30
FXChainShimmerReverbDiffusion=80
FXChainShimmerReverbPitchShift=99

@ -191,11 +191,9 @@ bool CPerformanceConfig::Load (void)
this->m_nFXChainTapeDelayFeedback = this->m_Properties.GetNumber("FXChainTapeDelayFeedback", 35);
this->m_bFXChainShimmerReverbEnable = this->m_Properties.GetNumber("FXChainShimmerReverbEnable", 1);
this->m_nFXChainShimmerReverbWet = this->m_Properties.GetNumber("FXChainShimmerReverbWet", 70);
this->m_nFXChainShimmerReverbDelayTimeLeft = this->m_Properties.GetNumber("FXChainShimmerReverbDelayTimeLeft", 15);
this->m_nFXChainShimmerReverbDelayTimeRight = this->m_Properties.GetNumber("FXChainShimmerReverbDelayTimeRight", 22);
this->m_nFXChainShimmerReverbFrequency = this->m_Properties.GetNumber("FXChainShimmerReverbFrequency", 20);
this->m_nFXChainShimmerReverbAmplitude = this->m_Properties.GetNumber("FXChainShimmerReverbAmplitude", 15);
this->m_nFXChainShimmerReverbDecayTime = this->m_Properties.GetNumber("FXChainShimmerReverbDecayTime", 65);
this->m_nFXChainShimmerReverbDecay = this->m_Properties.GetNumber("FXChainShimmerReverbDecay", 30);
this->m_nFXChainShimmerReverbDiffusion = this->m_Properties.GetNumber("FXChainShimmerReverbDiffusion", 30);
this->m_nFXChainShimmerReverbPitchShift = this->m_Properties.GetNumber("FXChainShimmerReverbPitchShift", 99);
#endif
return bResult;
@ -348,11 +346,9 @@ bool CPerformanceConfig::Save (void)
this->m_Properties.SetNumber("FXChainTapeDelayFeedback", m_nFXChainTapeDelayFeedback);
this->m_Properties.SetNumber("FXChainShimmerReverbEnable", m_bFXChainShimmerReverbEnable ? 1 : 0);
this->m_Properties.SetNumber("FXChainShimmerReverbWet", m_nFXChainShimmerReverbWet);
this->m_Properties.SetNumber("FXChainShimmerReverbDelayTimeLeft", m_nFXChainShimmerReverbDelayTimeLeft);
this->m_Properties.SetNumber("FXChainShimmerReverbDelayTimeRight", m_nFXChainShimmerReverbDelayTimeRight);
this->m_Properties.SetNumber("FXChainShimmerReverbFrequency", m_nFXChainShimmerReverbFrequency);
this->m_Properties.SetNumber("FXChainShimmerReverbAmplitude", m_nFXChainShimmerReverbAmplitude);
this->m_Properties.SetNumber("FXChainShimmerReverbDecayTime", m_nFXChainShimmerReverbDecayTime);
this->m_Properties.SetNumber("FXChainShimmerReverbDecay", m_nFXChainShimmerReverbDecay);
this->m_Properties.SetNumber("FXChainShimmerReverbDiffusion", m_nFXChainShimmerReverbDiffusion);
this->m_Properties.SetNumber("FXChainShimmerReverbPitchShift", m_nFXChainShimmerReverbPitchShift);
#endif
return m_Properties.Save ();
@ -1158,29 +1154,19 @@ unsigned CPerformanceConfig::GetFXChainShimmerReverbWet(void) const
return this->m_nFXChainShimmerReverbWet;
}
unsigned CPerformanceConfig::GetFXChainShimmerReverbDelayTimeLeft(void) const
unsigned CPerformanceConfig::GetFXChainShimmerReverbDecay(void) const
{
return this->m_nFXChainShimmerReverbDelayTimeLeft;
return this->m_nFXChainShimmerReverbDecay;
}
unsigned CPerformanceConfig::GetFXChainShimmerReverbDelayTimeRight(void) const
unsigned CPerformanceConfig::GetFXChainShimmerReverbDiffusion(void) const
{
return this->m_nFXChainShimmerReverbDelayTimeRight;
return this->m_nFXChainShimmerReverbDiffusion;
}
unsigned CPerformanceConfig::GetFXChainShimmerReverbFrequency(void) const
unsigned CPerformanceConfig::GetFXChainShimmerReverbPitchShift(void) const
{
return this->m_nFXChainShimmerReverbFrequency;
}
unsigned CPerformanceConfig::GetFXChainShimmerReverbAmplitude(void) const
{
return this->m_nFXChainShimmerReverbAmplitude;
}
unsigned CPerformanceConfig::GetFXChainShimmerReverbDecayTime(void) const
{
return this->m_nFXChainShimmerReverbDecayTime;
return this->m_nFXChainShimmerReverbPitchShift;
}
void CPerformanceConfig::SetFXChainEnable(bool bValue)
@ -1338,29 +1324,19 @@ void CPerformanceConfig::SetFXChainShimmerReverbWet(unsigned nValue)
this->m_nFXChainShimmerReverbWet = nValue;
}
void CPerformanceConfig::SetFXChainShimmerReverbDelayTimeLeft(unsigned nValue)
{
this->m_nFXChainShimmerReverbDelayTimeLeft = nValue;
}
void CPerformanceConfig::SetFXChainShimmerReverbDelayTimeRight(unsigned nValue)
{
this->m_nFXChainShimmerReverbDelayTimeRight = nValue;
}
void CPerformanceConfig::SetFXChainShimmerReverbFrequency(unsigned nValue)
void CPerformanceConfig::SetFXChainShimmerReverbDecay(unsigned nValue)
{
this->m_nFXChainShimmerReverbFrequency = nValue;
this->m_nFXChainShimmerReverbDecay = nValue;
}
void CPerformanceConfig::SetFXChainShimmerReverbAmplitude(unsigned nValue)
void CPerformanceConfig::SetFXChainShimmerReverbDiffusion(unsigned nValue)
{
this->m_nFXChainShimmerReverbAmplitude = nValue;
this->m_nFXChainShimmerReverbDiffusion = nValue;
}
void CPerformanceConfig::SetFXChainShimmerReverbDecayTime(unsigned nValue)
void CPerformanceConfig::SetFXChainShimmerReverbPitchShift(unsigned nValue)
{
this->m_nFXChainShimmerReverbDecayTime = nValue;
this->m_nFXChainShimmerReverbPitchShift = nValue;
}
#endif

@ -149,11 +149,9 @@ public:
unsigned GetFXChainTapeDelayFeedback(void) const;
bool GetFXChainShimmerReverbEnable(void) const;
unsigned GetFXChainShimmerReverbWet(void) const;
unsigned GetFXChainShimmerReverbDelayTimeLeft(void) const;
unsigned GetFXChainShimmerReverbDelayTimeRight(void) const;
unsigned GetFXChainShimmerReverbFrequency(void) const;
unsigned GetFXChainShimmerReverbAmplitude(void) const;
unsigned GetFXChainShimmerReverbDecayTime(void) const;
unsigned GetFXChainShimmerReverbDecay(void) const;
unsigned GetFXChainShimmerReverbDiffusion(void) const;
unsigned GetFXChainShimmerReverbPitchShift(void) const;
void SetFXChainEnable(bool bValue);
void SetFXChainWet(unsigned nValue);
@ -186,11 +184,9 @@ public:
void SetFXChainTapeDelayFeedback(unsigned nValue);
void SetFXChainShimmerReverbEnable(unsigned nValue);
void SetFXChainShimmerReverbWet(unsigned nValue);
void SetFXChainShimmerReverbDelayTimeLeft(unsigned nValue);
void SetFXChainShimmerReverbDelayTimeRight(unsigned nValue);
void SetFXChainShimmerReverbFrequency(unsigned nValue);
void SetFXChainShimmerReverbAmplitude(unsigned nValue);
void SetFXChainShimmerReverbDecayTime(unsigned nValue);
void SetFXChainShimmerReverbDecay(unsigned nValue);
void SetFXChainShimmerReverbDiffusion(unsigned nValue);
void SetFXChainShimmerReverbPitchShift(unsigned nValue);
#endif
bool VoiceDataFilled(unsigned nTG);
@ -292,11 +288,9 @@ private:
unsigned m_nFXChainTapeDelayFeedback;
bool m_bFXChainShimmerReverbEnable;
unsigned m_nFXChainShimmerReverbWet;
unsigned m_nFXChainShimmerReverbDelayTimeLeft;
unsigned m_nFXChainShimmerReverbDelayTimeRight;
unsigned m_nFXChainShimmerReverbFrequency;
unsigned m_nFXChainShimmerReverbAmplitude;
unsigned m_nFXChainShimmerReverbDecayTime;
unsigned m_nFXChainShimmerReverbDecay;
unsigned m_nFXChainShimmerReverbDiffusion;
unsigned m_nFXChainShimmerReverbPitchShift;
#endif
};

@ -0,0 +1,83 @@
CXX := gcc
CXXFLAGS := -g -O2
DEFINES :=
INCLUDES := -I../../CMSIS_5/CMSIS/DSP/Include/ -I../../CMSIS_5/CMSIS/Core/Include/
GCC := $(CXX) $(INCLUDES) $(CXXFLAGS)
LD := gcc
LIBS := -lm -lstdc++
OBJS := \
wavein.o \
waveout.o \
waveplay.o \
fx.o \
fx_components.o \
fx_svf.o \
fx_tube.o \
fx_chorus.o \
fx_phaser.o \
fx_orbitone.o \
fx_flanger.o \
fx_tape_delay.o \
fx_shimmer_reverb2.o \
fx_rack.o \
fxrack_test.o
test: fxrack_test
./fxrack_test
# %.o: ../%.cpp
# $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
wavein.o: wavein.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
waveout.o: waveout.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
waveplay.o: waveplay.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx.o: ../fx.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx_components.o: ../fx_components.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx_svf.o: ../fx_svf.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx_tube.o: ../fx_tube.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx_chorus.o: ../fx_chorus.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx_phaser.o: ../fx_phaser.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx_orbitone.o: ../fx_orbitone.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx_flanger.o: ../fx_flanger.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx_tape_delay.o: ../fx_tape_delay.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx_shimmer_reverb2.o: ../fx_shimmer_reverb2.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fx_rack.o: ../fx_rack.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fxrack_test.o: fxrack_test.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fxrack_test: $(OBJS)
$(LD) $(OBJS) -o fxrack_test $(LIBS)
clean:
rm -f *.o fxrack_test

@ -0,0 +1,136 @@
#include "../fx_rack.h"
#include <iostream>
#include <ctime>
#include <random>
#include "wave.h"
using namespace std;
#define MAX_SVF_SAMPLES 10000000
#define MAX_NB_ERRORS 100
void testFlutter()
{
JitterGenerator jg(44100.0f);
jg.setSpeed(1.0f);
jg.setMagnitude(0.1f);
for(unsigned i = 0; i < 1000; ++i)
{
cout << jg.process() << endl;
}
}
int main()
{
// testFlutter();
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<float32_t> dist(-1.0f, 1.0f);
unsigned step = 0;
float32_t inL, inR;
float32_t outL, outR;
StateVariableFilter svf(44100.0f, StateVariableFilter::Type::LPF, 12000.0f);
cout << "Step #" << (++step) << ": Testing SVF in LPF mode" << endl;
{
svf.setFilterType(StateVariableFilter::Type::LPF);
svf.setCutoff(12000.0f);
svf.setResonance(0.0f);
unsigned nbSamples = 0;
unsigned nbErrors = 0;
while(nbErrors < MAX_NB_ERRORS && nbSamples < MAX_SVF_SAMPLES)
{
nbSamples++;
inL = dist(gen);
inR = dist(gen);
svf.processSample(inL, inR, outL, outR);
if(std::abs(outL) > 1.0f) nbErrors++;
if(std::abs(outR) > 1.0f) nbErrors++;
}
cout << "nbSamples: " << nbSamples << " -- nbErrors: " << nbErrors << endl;
}
cout << "Step #" << (++step) << ": Testing SVF in HPF mode" << endl;
{
svf.setFilterType(StateVariableFilter::Type::LPF);
svf.setCutoff(60.0f);
svf.setResonance(0.0f);
unsigned nbSamples = 0;
unsigned nbErrors = 0;
while(nbErrors < MAX_NB_ERRORS && nbSamples < MAX_SVF_SAMPLES)
{
nbSamples++;
inL = dist(gen);
inR = dist(gen);
svf.processSample(inL, inR, outL, outR);
if(std::abs(outL) > 1.0f) nbErrors++;
if(std::abs(outR) > 1.0f) nbErrors++;
}
cout << "nbSamples: " << nbSamples << " -- nbErrors: " << nbErrors << endl;
}
cout << "Step #" << (++step) << ": Intanciation FXRack" << endl;
FXRack* rack = new FXRack(44100.0f);
cout << "Step #" << (++step) << ": Test preparation" << endl;
rack->setEnable(true);
rack->setWetLevel(1.0f);
rack->getTube()->setEnable(false);
rack->getChorus()->setEnable(false);
rack->getPhaser()->setEnable(false);
rack->getOrbitone()->setEnable(true);
rack->getFlanger()->setEnable(false);
rack->getTapeDelay()->setEnable(false);
// rack->getTapeDelay()->setWetLevel(0.6f);
// rack->getTapeDelay()->setLeftDelayTime(0.1f);
// rack->getTapeDelay()->setLeftDelayTime(0.05f);
// rack->getTapeDelay()->setFlutterLevel(0.25f);
// rack->getTapeDelay()->setFeedbak(0.5f);
rack->getShimmerReverb()->setEnable(true);
rack->getShimmerReverb()->setWetLevel(60);
rack->getShimmerReverb()->setDecay(30);
rack->getShimmerReverb()->setDiffusion(80);
rack->getShimmerReverb()->setPitchShift(99);
const unsigned nSamples = 3000;
float32_t inSamples[2][nSamples];
float32_t outSamples[2][nSamples];
for(unsigned i = 0; i < nSamples; ++i)
{
inSamples[0][i] = dist(gen);
inSamples[1][i] = dist(gen);
}
memset(outSamples[0], 0, nSamples * sizeof(float32_t));
memset(outSamples[1], 0, nSamples * sizeof(float32_t));
cout << "Step #" << (++step) << ": Run test" << endl;
rack->process(inSamples[0], inSamples[1], outSamples[0], outSamples[1], nSamples);
cout << "Step #" << (++step) << ": Render results" << endl;
for(unsigned i = 0; i < nSamples; ++i)
{
std::cout << "#" << i << " " << inSamples[0][i] << " --> " << outSamples[0][i] << " = " << ((outSamples[0][i] - inSamples[0][i]) * 100.0f / inSamples[0][i]) << "%" << std::endl;
}
unsigned size;
float32_t** samples = readWaveFile("test.wav", size);
float32_t* sampleOutL = new float32_t[size];
float32_t* sampleOutR = new float32_t[size];
rack->process(samples[0], samples[1], sampleOutL, sampleOutR, size);
playSound(sampleOutL, sampleOutR, size, 44100, 16);
cout << "Step #" << (++step) << ": Test cleanup" << endl;
delete rack;
return 0;
}

Binary file not shown.

@ -0,0 +1,36 @@
#pragma once
#include <stdint.h>
#include <arm_math.h>
#include <string>
struct WaveHeader {
char chunkId[4];
uint32_t chunkSize;
char format[4];
char subchunk1Id[4];
uint32_t subchunk1Size;
uint16_t audioFormat;
uint16_t numChannels;
uint32_t sampleRate;
uint32_t byteRate;
uint16_t blockAlign;
uint16_t bitsPerSample;
char subchunk2Id[4];
uint32_t subchunk2Size;
};
float32_t** readWaveFile(const std::string& fileName, unsigned& size);
void saveWaveFile(const std::string& fileName,
float32_t* LChannel,
float32_t* RChannel,
unsigned size,
int sampleRate,
int bitsPerSample);
void playSound(float32_t* LChannel,
float32_t* RChannel,
unsigned size,
int sampleRate,
int bitsPerSample);

@ -0,0 +1,87 @@
#include "wave.h"
#include <fstream>
#include <iostream>
float32_t** readWaveFile(const std::string& fileName, unsigned& size)
{
std::ifstream file(fileName, std::ios::binary);
if(!file)
{
std::cerr << "Error opening file: " << fileName << std::endl;
return nullptr;
}
WaveHeader header;
file.read((char*)&header, sizeof(header));
if(strncmp(header.chunkId, "RIFF", 4) != 0 || strncmp(header.format, "WAVE", 4) != 0)
{
std::cerr << "Error: not a WAVE file" << std::endl;
return nullptr;
}
if(header.audioFormat != 1)
{
std::cerr << "Error: only support PCM format" << std::endl;
return nullptr;
}
size = header.subchunk2Size / (header.bitsPerSample / 8);
float32_t* LChannel = new float32_t[size];
float32_t* RChannel = new float32_t[size];
unsigned i = 0;
while(!file.eof())
{
if(header.bitsPerSample == 8)
{
uint8_t LSample;
uint8_t RSample;
file.read((char*)&LSample, 1);
file.read((char*)&RSample, 1);
LChannel[i] = LSample / 128.0f - 1.0f;
RChannel[i] = RSample / 128.0f - 1.0f;
}
else if (header.bitsPerSample == 16)
{
int16_t LSample;
int16_t RSample;
file.read((char*)&LSample, 2);
file.read((char*)&RSample, 2);
LChannel[i] = LSample / 32768.0f;
RChannel[i] = RSample / 32768.0f;
}
else if (header.bitsPerSample == 24)
{
int32_t LSample;
int32_t RSample;
file.read((char*)&LSample, 3);
file.read((char*)&RSample, 3);
LChannel[i] = LSample / 8388608.0f;
RChannel[i] = RSample / 8388608.0f;
}
else if (header.bitsPerSample == 32)
{
int32_t LSample;
int32_t RSample;
file.read((char*)&LSample, 4);
file.read((char*)&RSample, 4);
LChannel[i] = LSample / 2147483648.0f;
RChannel[i] = RSample / 2147483648.0f;
}
else
{
std::cerr << "Error: unsupported bit depth: " << header.bitsPerSample << std::endl;
return nullptr;
}
++i;
}
float32_t** result = new float32_t*[2];
result[0] = LChannel;
result[1] = RChannel;
return result;
}

@ -0,0 +1,84 @@
#include "wave.h"
#include <fstream>
#include <iostream>
#include <cstring>
void saveWaveFile(const std::string& fileName,
float32_t* LChannel,
float32_t* RChannel,
unsigned size,
int sampleRate,
int bitsPerSample)
{
std::ofstream file(fileName, std::ios::binary);
if(!file)
{
std::cerr << "Error opening file: " << fileName << std::endl;
return;
}
WaveHeader header;
std::memset(&header, 0, sizeof(header));
header.sampleRate = sampleRate;
header.numChannels = 2;
header.bitsPerSample = bitsPerSample;
header.byteRate = header.sampleRate * header.numChannels * header.bitsPerSample / 8;
header.blockAlign = header.numChannels * header.bitsPerSample / 8;
header.subchunk2Size = size * header.blockAlign;
header.chunkSize = 36 + header.subchunk2Size;
header.subchunk1Size = 16;
std::strncpy(header.chunkId, "RIFF", 4);
std::strncpy(header.format, "WAVE", 4);
std::strncpy(header.subchunk1Id, "fmt ", 4);
std::strncpy(header.subchunk2Id, "data", 4);
file.write((char*)&header, sizeof(header));
if(bitsPerSample == 8)
{
for (size_t i = 0; i < size; i++)
{
int8_t leftSample = (int8_t)(LChannel[i] * 128.0f + 128.0f);
int8_t rightSample = (int8_t)(RChannel[i] * 128.0f + 128.0f);
file.write((char*)&leftSample, 1);
file.write((char*)&rightSample, 1);
}
}
else if(bitsPerSample == 16)
{
for (size_t i = 0; i < size; i++)
{
int16_t leftSample = (int16_t)(LChannel[i] * 32768.0f);
int16_t rightSample = (int16_t)(RChannel[i] * 32768.0f);
file.write((char*)&leftSample, 2);
file.write((char*)&rightSample, 2);
}
}
else if(bitsPerSample == 24)
{
for(size_t i = 0; i < size; i++)
{
int32_t leftSample = (int32_t)(LChannel[i] * 8388608.0f);
int32_t rightSample = (int32_t)(RChannel[i] * 8388608.0f);
file.write((char*)&leftSample, 3);
file.write((char*)&rightSample, 3);
}
}
else if(bitsPerSample == 32)
{
for (size_t i = 0; i < size; i++)
{
int32_t leftSample = (int32_t)(LChannel[i] * 2147483648.0f);
int32_t rightSample = (int32_t)(RChannel[i] * 2147483648.0f);
file.write((char*)&leftSample, 4);
file.write((char*)&rightSample, 4);
}
}
else
{
std::cerr << "Error: unsupported bit depth: " << bitsPerSample << std::endl;
return;
}
}

@ -0,0 +1,116 @@
#include "wave.h"
#include <Windows.h>
#include <mmsystem.h>
#include <iostream>
void playSound(float32_t* LChannel,
float32_t* RChannel,
unsigned size,
int sampleRate,
int bitsPerSample)
{
// Calculate the number of samples and the size of the audio buffer
int numSamples = size;
int bufferSize = numSamples * bitsPerSample / 8 * 2;
// Create an audio buffer
std::vector<uint8_t> buffer(bufferSize);
// Fill the audio buffer with the sample data
for(int i = 0; i < numSamples; i++)
{
if(bitsPerSample == 8)
{
// 8-bit samples are unsigned and range from 0 to 255
uint8_t leftSample = (uint8_t)(LChannel[i] * 128.0f + 128.0f);
uint8_t rightSample = (uint8_t)(RChannel[i] * 128.0f + 128.0f);
buffer[i * 2 + 0] = leftSample;
buffer[i * 2 + 1] = rightSample;
}
else if(bitsPerSample == 16)
{
// 16-bit samples are signed and range from -32768 to 32767
int16_t leftSample = (int16_t)(LChannel[i] * 32768.0f);
int16_t rightSample = (int16_t)(RChannel[i] * 32768.0f);
buffer[i * 2 + 0] = (uint8_t)leftSample;
buffer[i * 2 + 1] = (uint8_t)(leftSample >> 8);
buffer[i * 2 + 2] = (uint8_t)rightSample;
buffer[i * 2 + 3] = (uint8_t)(rightSample >> 8);
}
else if(bitsPerSample == 24)
{
// 24-bit samples are signed and range from -32768 to 32767
int32_t leftSample = (int16_t)(LChannel[i] * 8388608.0f);
int32_t rightSample = (int16_t)(RChannel[i] * 8388608.0f);
buffer[i * 3 + 0] = (uint8_t)leftSample;
buffer[i * 3 + 1] = (uint8_t)(leftSample >> 8);
buffer[i * 3 + 2] = (uint8_t)(leftSample >> 16);
buffer[i * 3 + 3] = (uint8_t)rightSample;
buffer[i * 3 + 4] = (uint8_t)(rightSample >> 8);
buffer[i * 3 + 5] = (uint8_t)(rightSample >> 16);
}
else if (bitsPerSample == 32)
{
// 32-bit samples are signed and range from -32768 to 32767
int32_t leftSample = (int16_t)(LChannel[i] * 2147483648.0f);
int32_t rightSample = (int16_t)(RChannel[i] * 2147483648.0f);
buffer[i * 3 + 0] = (uint8_t)leftSample;
buffer[i * 3 + 1] = (uint8_t)(leftSample >> 8);
buffer[i * 3 + 2] = (uint8_t)(leftSample >> 16);
buffer[i * 3 + 3] = (uint8_t)(leftSample >> 24);
buffer[i * 3 + 4] = (uint8_t)rightSample;
buffer[i * 3 + 5] = (uint8_t)(rightSample >> 8);
buffer[i * 3 + 6] = (uint8_t)(rightSample >> 16);
buffer[i * 3 + 7] = (uint8_t)(rightSample >> 24);
}
else
{
std::cerr << "Error: unsupported bit depth: " << bitsPerSample << std::endl;
return;
}
}
// Set up the WAVEFORMATEX structure
WAVEFORMATEX waveFormat;
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
waveFormat.nChannels = 2;
waveFormat.nSamplesPerSec = sampleRate;
waveFormat.nAvgBytesPerSec = sampleRate * bitsPerSample / 8 * 2;
waveFormat.nBlockAlign = bitsPerSample / 8 * 2;
waveFormat.wBitsPerSample = bitsPerSample;
waveFormat.cbSize = 0;
// Set up the WAVEHDR structure
WAVEHDR waveHeader;
waveHeader.lpData = (LPSTR)buffer.data();
waveHeader.dwBufferLength = bufferSize;
waveHeader.dwBytesRecorded = 0;
waveHeader.dwUser = 0;
waveHeader.dwFlags = 0;
waveHeader.dwLoops = 0;
waveHeader.lpNext = nullptr;
waveHeader.reserved = 0;
// Open the audio device
HWAVEOUT audioDevice;
MMRESULT result = waveOutOpen(&audioDevice, WAVE_MAPPER, &waveFormat, 0, 0, WAVE_FORMAT_QUERY);
if (result != MMSYSERR_NOERROR) {
std::cerr << "Error opening audio device" << std::endl;
return;
}
// Prepare the audio buffer for playback
result = waveOutPrepareHeader(audioDevice, &waveHeader, sizeof(WAVEHDR));
if (result != MMSYSERR_NOERROR) {
std::cerr << "Error preparing audio buffer" << std::endl;
return;
}
// Play the audio
waveOutWrite(audioDevice, &waveHeader, sizeof(WAVEHDR));
// Cleanup
waveOutUnprepareHeader(audioDevice, &waveHeader, sizeof(WAVEHDR));
waveOutClose(audioDevice);
}

@ -217,11 +217,9 @@ const CUIMenu::TMenuItem CUIMenu::s_FXChainShimmerReverb[] =
{
{"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbEnable},
{"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbWet},
{"L Delay", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbDelayTimeLeft},
{"R Delay", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbDelayTimeRight},
{"Freq", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbFrequency},
{"Amp", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbAmplitude},
{"Decay", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbDecayTime},
{"Decay", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbDecay},
{"Diffus", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbDiffusion},
{"PtchShft", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbPitchShift},
{0}
};
@ -355,11 +353,9 @@ const CUIMenu::TParameter CUIMenu::s_GlobalParameter[CMiniDexed::ParameterUnknow
// FXChain > ShimmerReverb parameters
{0, 1, 1, ToOnOff}, // ParameterFXChainShimmerReverbEnable
{0, 99, 1}, // ParameterFXChainShimmerReverbWet
{0, 99, 1}, // ParameterFXChainShimmerReverbDelayTimeLeft
{0, 99, 1}, // ParameterFXChainShimmerReverbDelayTimeRight
{0, 99, 1}, // ParameterFXChainShimmerReverbFrequency
{0, 99, 1}, // ParameterFXChainShimmerReverbAmplitude
{0, 99, 1}, // ParameterFXChainShimmerReverbDecayTime
{0, 99, 1}, // ParameterFXChainShimmerReverbDecay
{0, 99, 1}, // ParameterFXChainShimmerReverbDiffusion
{0, 99, 1}, // ParameterFXChainShimmerReverbPitchShift
#endif
// END FXRack global parameters mapping definition

Loading…
Cancel
Save