Replacement of the FXRack with MixingConsole

This commit include all the audio fixes and modification
- FXEngine support computation on float32_t instead of intergers only
- Migration of the PlateReverb to the FXElement structure
- Fixing shimmer to be stereo (was missing an LFO)
- Fixing delay to be stereo
- Adding flutter rate and amount params to delay to simulate Tape Delay
- Fixing Tube so it goes beyond than just warming a little bit the sound
pull/495/head
abscisys 2 years ago
parent 374ec013e4
commit 6c1dfb5ee6
  1. 2
      .gitignore
  2. 2
      src/Makefile
  3. 7
      src/extra_features.h
  4. 2
      src/fx.h
  5. 2
      src/fx_chorus.h
  6. 126
      src/fx_components.cpp
  7. 190
      src/fx_components.h
  8. 75
      src/fx_delay.cpp
  9. 13
      src/fx_delay.h
  10. 87
      src/fx_engine.hpp
  11. 2
      src/fx_orbitone.h
  12. 29
      src/fx_shimmer_reverb.cpp
  13. 2
      src/fx_shimmer_reverb.h
  14. 176
      src/fx_svf.cpp
  15. 28
      src/fx_svf.h
  16. 16
      src/fx_tube.cpp
  17. 2
      src/fx_tube.h
  18. 101
      src/fx_unit2.hpp
  19. 19
      src/mididevice.cpp
  20. 808
      src/minidexed.cpp
  21. 209
      src/minidexed.h
  22. 354
      src/mixing_console.cpp
  23. 96
      src/mixing_console.h
  24. 59
      src/mixing_console_constants.h
  25. 475
      src/performanceconfig.cpp
  26. 197
      src/performanceconfig.h
  27. 49
      src/test/Makefile
  28. 101
      src/test/MixerOutputTest.hpp
  29. 12
      src/test/UIMenuTest.hpp
  30. 8
      src/test/all_tests.cpp
  31. 46
      src/test/arm_functions.cpp
  32. 4
      src/test/desktop.ini
  33. 211
      src/test/fxrack_test.cpp
  34. 417
      src/uimenu.cpp
  35. 25
      src/uimenu.h
  36. 62
      src/userinterface.cpp
  37. 10
      src/userinterface.h

2
.gitignore vendored

@ -49,5 +49,7 @@ sdcard
# temporary tests # temporary tests
src/test/fxrack_test src/test/fxrack_test
src/test/all_tests
src/test/waves/
src/test/result*.wav src/test/result*.wav
src/test/*.csv src/test/*.csv

@ -12,7 +12,7 @@ OBJS = main.o kernel.o minidexed.o config.o userinterface.o uimenu.o \
effect_compressor.o effect_platervbstereo.o \ effect_compressor.o effect_platervbstereo.o \
fx.o fx_components.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_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 \ fx_delay.o fx_shimmer_reverb.o fx_dry.o \
uibuttons.o midipin.o uibuttons.o midipin.o
OPTIMIZE = -O3 OPTIMIZE = -O3

@ -20,6 +20,11 @@
#if defined(ARM_ALLOW_MULTI_CORE) #if defined(ARM_ALLOW_MULTI_CORE)
#define FXRACK_ENABLE //Add support for the FXRack #define MIXING_CONSOLE_ENABLE //Add support for the MixingConsole
#endif #endif
#ifdef DEBUG
#include <iostream>
#include <iomanip>
#endif

@ -22,6 +22,8 @@
#include <arm_math.h> #include <arm_math.h>
#include "common.h" #include "common.h"
#include "extra_features.h"
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \ TypeName(const TypeName&) = delete; \
void operator=(const TypeName&) = delete void operator=(const TypeName&) = delete

@ -48,7 +48,7 @@ public:
float32_t getRate() const; float32_t getRate() const;
private: private:
typedef FxEngine<2048, FORMAT_16_BIT, false> Engine; typedef FxEngine<2048, Format::FORMAT_FLOAT32, false> Engine;
Engine engine_; Engine engine_;
float32_t rate_; // Normalized frequency for the 2 LFOs frequencies (0.0 - 10.0) float32_t rate_; // Normalized frequency for the 2 LFOs frequencies (0.0 - 10.0)

@ -7,6 +7,8 @@
/////////////////////////////// ///////////////////////////////
const float32_t Constants::M2PI = 2.0f * PI; const float32_t Constants::M2PI = 2.0f * PI;
const float32_t Constants::MPI_2 = PI / 2.0f; const float32_t Constants::MPI_2 = PI / 2.0f;
const float32_t Constants::MPI_3 = PI / 3.0f;
const float32_t Constants::MPI_4 = PI / 4.0f;
const float32_t Constants::M1_PI = 1.0f / PI; const float32_t Constants::M1_PI = 1.0f / PI;
///////////////////////// /////////////////////////
@ -198,6 +200,116 @@ float32_t JitterGenerator::process()
return out; return out;
} }
//////////////////////////////////////////
// PerlinNoiseGenerator implemlentation //
//////////////////////////////////////////
#define MAX_FREQUENCY_PERLIN_NOISE_GENERATOR 0.5f
const float32_t PerlinNoiseGenerator::Gradients[] =
{
-1.0f, +1.0f,
-1.0f, -1.0f,
+1.0f, -1.0f,
+1.0f, +1.0f
};
PerlinNoiseGenerator::PerlinNoiseGenerator(float32_t sampling_rate, float32_t rate) :
FXBase(sampling_rate),
rate_(0.0f),
phase_(0.0f),
phase_increment_(0.0f),
current_(0.0f)
{
this->setRate(rate);
this->reset();
}
PerlinNoiseGenerator::~PerlinNoiseGenerator()
{
}
void PerlinNoiseGenerator::setRate(float32_t rate)
{
rate = constrain(rate, 0.0f, 1.0f);
if(rate != this->rate_)
{
this->rate_ = rate;
this->phase_increment_ = Constants::M2PI * rate / this->getSamplingRate();
}
}
float32_t PerlinNoiseGenerator::getRate() const
{
return this->rate_;
}
float32_t PerlinNoiseGenerator::getCurrent() const
{
return this->current_;
}
void PerlinNoiseGenerator::reset()
{
this->phase_ = 0.0f;
this->current_ = 0.0f;
}
float32_t PerlinNoiseGenerator::process()
{
if(this->rate_ == 0.0f)
{
return this->current_ = 0.0f;
}
this->current_ = PerlinNoiseGenerator::perlin(this->phase_);
this->phase_ += this->phase_increment_;
if(this->phase_ >= Constants::M2PI)
{
this->phase_ -= Constants::M2PI;
}
return this->current_;
}
int PerlinNoiseGenerator::hash(int x)
{
x = ((x << 13) ^ x);
return (x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff;
}
float32_t PerlinNoiseGenerator::interpolate(float32_t a, float32_t b, float32_t x)
{
float32_t ft = x * PI;
float32_t f = (1.0f - arm_cos_f32(ft)) * 0.5;
return a * (1.0f - f) + b * f;
}
float32_t PerlinNoiseGenerator::perlin(float32_t x)
{
// Find the unit square that contains x
int squareX = (int)x;
// Find the relative x of x within that square
double relX = x - squareX;
// Calculate the hashes for the square's four corners
int h1 = PerlinNoiseGenerator::hash(squareX);
int h2 = PerlinNoiseGenerator::hash(squareX + 1);
// Calculate the gradients for each corner
double grad1 = PerlinNoiseGenerator::Gradients[h1 & 3];
double grad2 = PerlinNoiseGenerator::Gradients[h2 & 3];
// Calculate the dot products between the gradient vectors and the distance vectors
double dot1 = grad1 * relX;
double dot2 = grad2 * (relX - 1);
// Interpolate the dot products and return the final noise value
return PerlinNoiseGenerator::interpolate(dot1, dot2, relX);
}
////////////////////////////////// //////////////////////////////////
// softSaturate implemlentation // // softSaturate implemlentation //
////////////////////////////////// //////////////////////////////////
@ -259,6 +371,20 @@ float32_t softSaturator2(float32_t input, float32_t saturation)
return output; return output;
} }
float32_t softSaturator3(float32_t input, float32_t overdrive)
{
const float32_t w = (1.0f + overdrive) * Constants::MPI_4;
return constrain(std::tan(w * input), -1.0f, 1.0f);
}
float32_t softSaturator4(float32_t input, float32_t saturator_factor)
{
float32_t x = input * (saturator_factor);
float32_t abs_x = std::fabs(x);
float32_t sat_x = std::log(1.0 + abs_x) / std::log(1.0f + saturator_factor);
return x > 0 ? sat_x : -sat_x;
}
float32_t waveFolder(float32_t input, float32_t bias) float32_t waveFolder(float32_t input, float32_t bias)
{ {
bias = 0.5 + (2.0f - bias) / 4.0f; bias = 0.5 + (2.0f - bias) / 4.0f;

@ -28,6 +28,8 @@ struct Constants
{ {
const static float32_t M2PI; // 2 * PI const static float32_t M2PI; // 2 * PI
const static float32_t MPI_2; // PI / 2 const static float32_t MPI_2; // PI / 2
const static float32_t MPI_3; // PI / 3
const static float32_t MPI_4; // PI / 4
const static float32_t M1_PI; // 1 / PI const static float32_t M1_PI; // 1 / PI
}; };
@ -76,162 +78,6 @@ private:
std::uniform_real_distribution<float32_t> rnd_distribution_; std::uniform_real_distribution<float32_t> rnd_distribution_;
}; };
template<typename T, unsigned size, unsigned nb_channels = 2, bool circular_buffer = true>
class Buffer
{
DISALLOW_COPY_AND_ASSIGN(Buffer);
public:
Buffer() :
index_(0)
{
this->values_ = new T*[nb_channels];
for(unsigned i = 0; i < nb_channels; ++i)
{
this->values_[i] = new T[size];
}
this->reset();
}
virtual ~Buffer()
{
for(unsigned i = 0; i < nb_channels; ++i)
{
delete[] this->values_[i];
}
delete[] this->values_;
}
void reset(bool reset_index = true)
{
this->zero();
if(reset_index)
{
this->index_ = 0;
}
}
T& operator[](unsigned channel)
{
assert(channel < nb_channels);
return *(this->values_[channel] + this->index_);
}
bool operator++()
{
this->index_++;
if(this->index_ >= size)
{
if(circular_buffer)
{
this->index_ = 0;
return true;
}
else
{
this->index_ = size - 1;
return false;
}
}
return true;
}
bool operator--()
{
if(this->index_ > 0)
{
this->index_--;
return true;
}
else
{
if(circular_buffer)
{
this->index_ = size - 1;
return true;
}
else
{
this->index_ = 0;
return false;
}
}
}
void copy(T* buffer, unsigned channel, unsigned nb, bool from_start = true)
{
assert(channel < nb_channels);
unsigned start = from_start ? 0 : this->index_;
unsigned _nb = std::min(nb, size - start);
memcpy(this->values_[channel] + start, buffer, _nb);
}
void zero()
{
for(unsigned c = 0; c < nb_channels; ++c)
{
memset(this->values_[c], 0, size * sizeof(T));
}
}
void scale(T scale)
{
for(unsigned c = 0; c < nb_channels; ++c)
{
for(unsigned i = 0; i < size; ++i)
{
this->values_[c][i] *= scale;
}
}
}
unsigned index() const
{
return this->index_;
}
unsigned nbChannels() const
{
return nb_channels;
}
unsigned bufferSize() const
{
return size;
}
bool isCircularBuffer() const
{
return circular_buffer;
}
private:
unsigned index_;
T** values_;
};
template<unsigned size, unsigned nb_channels, bool circular_buffer>
class Buffer<float32_t, size, nb_channels, circular_buffer>
{
void scale(float32_t scale)
{
for(unsigned c = 0; c < nb_channels; ++c)
{
arm_scale_f32(this->values_[c], scale, this->values_[c], size);
}
}
void copy(float32_t* buffer, unsigned channel, unsigned nb, bool from_start = true)
{
assert(channel < nb_channels);
unsigned start = from_start ? 0 : this->index_;
unsigned _nb = std::min(nb, size - start);
arm_copy_f32(buffer, this->values_[channel] + start, _nb);
}
};
class JitterGenerator : public FXBase class JitterGenerator : public FXBase
{ {
@ -260,7 +106,39 @@ private:
float32_t phase_increment_; float32_t phase_increment_;
}; };
class PerlinNoiseGenerator : public FXBase
{
DISALLOW_COPY_AND_ASSIGN(PerlinNoiseGenerator);
public:
PerlinNoiseGenerator(float32_t sampling_rate, float32_t rate = 0.2f);
virtual ~PerlinNoiseGenerator();
void setRate(float32_t rate);
float32_t getRate() const;
float32_t getCurrent() const;
virtual void reset() override;
float32_t process();
private:
static int hash(int x);
static float32_t interpolate(float32_t a, float32_t b, float32_t x);
static float32_t perlin(float32_t x);
float32_t rate_;
float32_t phase_;
float32_t phase_increment_;
float32_t current_;
static const float32_t Gradients[];
};
float32_t softSaturator1(float32_t in, float32_t threshold); float32_t softSaturator1(float32_t in, float32_t threshold);
float32_t softSaturator2(float32_t in, float32_t saturation); 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);

@ -2,18 +2,21 @@
#include <cmath> #include <cmath>
#define MAX_DELAY_TIME 1.0f #define MAX_DELAY_TIME 2.0f
#define MAX_FLUTTER_DELAY_TIME 0.01f #define MAX_FLUTTER_DELAY_TIME 0.001f
#define LPF_CUTOFF_REF 14000.0f #define LPF_CUTOFF_REF 12000.0f
#define HPF_CUTOFF_REF 60.0f #define HPF_CUTOFF_REF 80.0f
Delay::LowHighPassFilter::LowHighPassFilter(float32_t sampling_rate) : Delay::LowHighPassFilter::LowHighPassFilter(float32_t sampling_rate) :
FXElement(sampling_rate), FXElement(sampling_rate),
lpf_(sampling_rate, StateVariableFilter::Type::LPF, LPF_CUTOFF_REF), lpf_(sampling_rate, StateVariableFilter::Type::LPF, LPF_CUTOFF_REF),
hpf_(sampling_rate, StateVariableFilter::Type::HPF, HPF_CUTOFF_REF) hpf_(sampling_rate, StateVariableFilter::Type::HPF, HPF_CUTOFF_REF),
ratio_(1.0f)
{ {
this->setCutoffChangeRatio(0.0f); this->setCutoffChangeRatio(0.0f);
this->lpf_.setGainDB(0.82f);
this->hpf_.setGainDB(0.82f);
} }
Delay::LowHighPassFilter::~LowHighPassFilter() Delay::LowHighPassFilter::~LowHighPassFilter()
@ -22,10 +25,16 @@ Delay::LowHighPassFilter::~LowHighPassFilter()
void Delay::LowHighPassFilter::setCutoffChangeRatio(float32_t ratio) void Delay::LowHighPassFilter::setCutoffChangeRatio(float32_t ratio)
{ {
ratio += 1.0f; static const float32_t weight = 4.0f;
this->lpf_.setCutoff(LPF_CUTOFF_REF * ratio); ratio = constrain(ratio, -1.0f, 1.0f);
this->hpf_.setCutoff(HPF_CUTOFF_REF * ratio); if(ratio != this->ratio_)
{
this->ratio_ = ratio;
ratio /= 10.0f;
this->lpf_.setCutoff(LPF_CUTOFF_REF * (1.0f - ratio / weight));
this->hpf_.setCutoff(HPF_CUTOFF_REF * (1.0f + ratio * weight));
}
} }
void Delay::LowHighPassFilter::reset() void Delay::LowHighPassFilter::reset()
@ -45,14 +54,17 @@ Delay::Delay(const float32_t sampling_rate, float32_t default_delay_time, float3
MaxSampleDelayTime((MAX_DELAY_TIME + MAX_FLUTTER_DELAY_TIME) * sampling_rate * MAX_DELAY_TIME), MaxSampleDelayTime((MAX_DELAY_TIME + MAX_FLUTTER_DELAY_TIME) * sampling_rate * MAX_DELAY_TIME),
read_pos_L_(0), read_pos_L_(0),
read_pos_R_(0), read_pos_R_(0),
filter_(sampling_rate) filter_(sampling_rate),
jitter_generator_(sampling_rate)
{ {
this->buffer_L_ = new float32_t[this->MaxSampleDelayTime]; this->buffer_L_ = new float32_t[this->MaxSampleDelayTime];
this->buffer_R_ = new float32_t[this->MaxSampleDelayTime]; this->buffer_R_ = new float32_t[this->MaxSampleDelayTime];
this->setLeftDelayTime(default_delay_time); this->setLeftDelayTime(default_delay_time);
this->setRightDelayTime(default_delay_time); this->setRightDelayTime(default_delay_time);
this->setFeedbak(default_feedback_level); this->setFeedback(default_feedback_level);
this->setFlutterRate(0.2f);
this->setFlutterAmount(0.05f);
this->reset(); this->reset();
} }
@ -70,12 +82,23 @@ void Delay::reset()
this->read_pos_L_ = 0; this->read_pos_L_ = 0;
this->read_pos_R_ = 0; this->read_pos_R_ = 0;
this->filter_.reset(); this->filter_.reset();
this->jitter_generator_.reset();
} }
void Delay::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) void Delay::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{ {
float32_t delay_time_L = (MAX_DELAY_TIME * this->getLeftDelayTime() ) * this->getSamplingRate(); static const float32_t max_delay_time = MAX_DELAY_TIME * this->getSamplingRate();
float32_t delay_time_R = (MAX_DELAY_TIME * this->getRightDelayTime()) * this->getSamplingRate(); float32_t jitter_ratio = this->jitter_generator_.process();
float32_t jitter_delay_time = 0.0f;
if(jitter_ratio != 0.0f)
{
jitter_ratio *= this->jitter_amount_;
jitter_delay_time = MAX_FLUTTER_DELAY_TIME * jitter_ratio * this->getSamplingRate();
}
// this->filter_.setCutoffChangeRatio(jitter_ratio);
float32_t delay_time_L = jitter_delay_time + max_delay_time * this->getLeftDelayTime();
float32_t delay_time_R = jitter_delay_time + max_delay_time * this->getRightDelayTime();
// Calculate write positions // Calculate write positions
unsigned write_pos_L = static_cast<unsigned>(this->MaxSampleDelayTime + this->read_pos_L_ + delay_time_L) % this->MaxSampleDelayTime; unsigned write_pos_L = static_cast<unsigned>(this->MaxSampleDelayTime + this->read_pos_L_ + delay_time_L) % this->MaxSampleDelayTime;
@ -93,8 +116,8 @@ void Delay::processSample(float32_t inL, float32_t inR, float32_t& outL, float32
outR outR
); );
this->buffer_L_[write_pos_L] += outL * this->getFeedbackLevel(); this->buffer_L_[write_pos_L] += outL * this->getFeedback();
this->buffer_R_[write_pos_R] += outR * this->getFeedbackLevel(); this->buffer_R_[write_pos_R] += outR * this->getFeedback();
// Increment read positions // Increment read positions
++this->read_pos_L_; ++this->read_pos_L_;
@ -129,12 +152,32 @@ float32_t Delay::getRightDelayTime() const
return this->delay_time_R_; return this->delay_time_R_;
} }
void Delay::setFeedbak(float32_t feedback) void Delay::setFeedback(float32_t feedback)
{ {
this->feedback_ = constrain(feedback, 0.0, 1.0); this->feedback_ = constrain(feedback, 0.0, 1.0);
} }
float32_t Delay::getFeedbackLevel() const float32_t Delay::getFeedback() const
{ {
return this->feedback_; return this->feedback_;
} }
void Delay::setFlutterRate(float32_t rate)
{
this->jitter_generator_.setRate(rate);
}
float32_t Delay::getFlutterRate() const
{
return this->jitter_generator_.getRate();
}
void Delay::setFlutterAmount(float32_t amount)
{
this->jitter_amount_ = constrain(amount, 0.0f, 1.0f);
}
float32_t Delay::getFlutterAmount() const
{
return this->jitter_amount_;
}

@ -44,6 +44,7 @@ class Delay : public FXElement
private: private:
StateVariableFilter lpf_; StateVariableFilter lpf_;
StateVariableFilter hpf_; StateVariableFilter hpf_;
float32_t ratio_;
}; };
@ -60,8 +61,14 @@ public:
void setRightDelayTime(float32_t delay_time); void setRightDelayTime(float32_t delay_time);
float32_t getRightDelayTime() const; float32_t getRightDelayTime() const;
void setFeedbak(float32_t feedback); void setFeedback(float32_t feedback);
float32_t getFeedbackLevel() const; float32_t getFeedback() const;
void setFlutterRate(float32_t rate);
float32_t getFlutterRate() const;
void setFlutterAmount(float32_t amount);
float32_t getFlutterAmount() const;
private: private:
const size_t MaxSampleDelayTime; const size_t MaxSampleDelayTime;
@ -72,6 +79,8 @@ private:
float32_t delay_time_L_; // Left delay time in seconds (0.0 - 2.0) float32_t delay_time_L_; // Left delay time in seconds (0.0 - 2.0)
float32_t delay_time_R_; // Right delay time in seconds (0.0 - 2.0) float32_t delay_time_R_; // Right delay time in seconds (0.0 - 2.0)
float32_t feedback_; // Feedback (0.0 - 1.0) float32_t feedback_; // Feedback (0.0 - 1.0)
float32_t jitter_amount_;
LowHighPassFilter filter_; LowHighPassFilter filter_;
PerlinNoiseGenerator jitter_generator_;
}; };

@ -8,10 +8,11 @@
#define MAKE_INTEGRAL_FRACTIONAL(x) \ #define MAKE_INTEGRAL_FRACTIONAL(x) \
int32_t x ## _integral = static_cast<int32_t>(x); \ int32_t x ## _integral = static_cast<int32_t>(x); \
float x ## _fractional = x - static_cast<float>(x ## _integral); float32_t x ## _fractional = x - static_cast<float32_t>(x ## _integral);
enum Format enum Format
{ {
FORMAT_FLOAT32,
FORMAT_12_BIT, FORMAT_12_BIT,
FORMAT_16_BIT, FORMAT_16_BIT,
FORMAT_32_BIT FORMAT_32_BIT
@ -38,7 +39,23 @@ inline int16_t clip16(int32_t x)
} }
template <> template <>
struct DataType<FORMAT_16_BIT> struct DataType<Format::FORMAT_FLOAT32>
{
typedef float32_t T;
static inline float32_t decompress(T value)
{
return value;
}
static inline T compress(float32_t value)
{
return constrain(value, -1.0f, 1.0f);
}
};
template <>
struct DataType<Format::FORMAT_12_BIT>
{ {
typedef uint16_t T; typedef uint16_t T;
@ -53,9 +70,41 @@ struct DataType<FORMAT_16_BIT>
} }
}; };
template <>
struct DataType<Format::FORMAT_16_BIT>
{
typedef uint32_t T;
static inline float32_t decompress(T value)
{
return static_cast<float32_t>(static_cast<int16_t>(value)) / 65536.0f;
}
static inline T compress(float32_t value)
{
return clip16(static_cast<int32_t>(value * 65536.0f));
}
};
template <>
struct DataType<Format::FORMAT_32_BIT>
{
typedef uint32_t T;
static inline float32_t decompress(T value)
{
return static_cast<float32_t>(static_cast<int64_t>(value)) / static_cast<float32_t>(UINT32_MAX);
}
static inline T compress(float32_t value)
{
return value * static_cast<float32_t>(INT32_MAX);
}
};
template < template <
size_t size, size_t size,
Format format = FORMAT_16_BIT, Format format,
bool enable_lfo = true> bool enable_lfo = true>
class FxEngine : public FXBase class FxEngine : public FXBase
{ {
@ -67,15 +116,15 @@ public:
enum LFOIndex enum LFOIndex
{ {
LFO_1 = 0, LFO_1 = 0,
LFO_2 LFO_2,
kLFOCount
}; };
FxEngine(float32_t sampling_rate, float32_t max_lfo1_frequency = 1.0f, float32_t max_lfo2_frequency = 1.0f) : FxEngine(float32_t sampling_rate, float32_t max_lfo1_frequency = 1.0f, float32_t max_lfo2_frequency = 1.0f) :
FXBase(sampling_rate) FXBase(sampling_rate)
{ {
this->buffer_ = new uint16_t[size]; this->buffer_ = new T[size];
this->lfo_[LFOIndex::LFO_1] = enable_lfo ? new LFO(sampling_rate, LFO::Waveform::Sine, 0.0f, max_lfo1_frequency) : nullptr; for(unsigned i = 0; i < LFOIndex::kLFOCount; ++i) this->lfo_[i] = enable_lfo ? new LFO(sampling_rate, LFO::Waveform::Sine, 0.0f, max_lfo1_frequency) : nullptr;
this->lfo_[LFOIndex::LFO_2] = enable_lfo ? new LFO(sampling_rate, LFO::Waveform::Sine, 0.0f, max_lfo2_frequency) : nullptr;
this->clear(); this->clear();
} }
@ -84,14 +133,13 @@ public:
delete[] this->buffer_; delete[] this->buffer_;
if(enable_lfo) if(enable_lfo)
{ {
delete this->lfo_[LFO_1]; for(unsigned i = 0; i < LFOIndex::kLFOCount; ++i) delete this->lfo_[i];
delete this->lfo_[LFO_2];
} }
} }
void clear() void clear()
{ {
memset(this->buffer_, 0, size * sizeof(uint16_t)); memset(this->buffer_, 0, size * sizeof(T));
this->write_ptr_ = 0; this->write_ptr_ = 0;
} }
@ -100,8 +148,7 @@ public:
this->clear(); this->clear();
if(enable_lfo) if(enable_lfo)
{ {
this->lfo_[LFOIndex::LFO_1]->reset(); for(unsigned i = 0; i < LFOIndex::kLFOCount; ++i) this->lfo_[i]->reset();
this->lfo_[LFOIndex::LFO_2]->reset();
} }
} }
@ -151,7 +198,7 @@ public:
buffer_(nullptr), buffer_(nullptr),
write_ptr_(0) write_ptr_(0)
{ {
memset(this->lfo_value_, 0, 2 * sizeof(float32_t)); memset(this->lfo_value_, 0, LFOIndex::kLFOCount * sizeof(T));
} }
~Context() ~Context()
@ -271,6 +318,7 @@ public:
inline void interpolate(D& d, float32_t offset, LFOIndex index, float32_t amplitude, float32_t scale) inline void interpolate(D& d, float32_t offset, LFOIndex index, float32_t amplitude, float32_t scale)
{ {
assert(D::base + D::length <= size); assert(D::base + D::length <= size);
assert(index < LFOIndex::kLFOCount);
offset += amplitude * this->lfo_value_[index]; offset += amplitude * this->lfo_value_[index];
MAKE_INTEGRAL_FRACTIONAL(offset); MAKE_INTEGRAL_FRACTIONAL(offset);
float32_t a = DataType<format>::decompress(this->buffer_[(this->write_ptr_ + offset_integral + D::base) & MASK]); float32_t a = DataType<format>::decompress(this->buffer_[(this->write_ptr_ + offset_integral + D::base) & MASK]);
@ -283,13 +331,14 @@ public:
private: private:
float32_t accumulator_; float32_t accumulator_;
float32_t previous_read_; float32_t previous_read_;
float32_t lfo_value_[2]; float32_t lfo_value_[LFOIndex::kLFOCount];
T* buffer_; T* buffer_;
int32_t write_ptr_; int32_t write_ptr_;
}; };
inline void setLFOFrequency(LFOIndex index, float32_t frequency) inline void setLFOFrequency(LFOIndex index, float32_t frequency)
{ {
assert(index < LFOIndex::kLFOCount);
if(enable_lfo) if(enable_lfo)
{ {
this->lfo_[index]->setFrequency(frequency); this->lfo_[index]->setFrequency(frequency);
@ -298,6 +347,7 @@ public:
inline void setLFONormalizedFrequency(LFOIndex index, float32_t normalized_frequency) inline void setLFONormalizedFrequency(LFOIndex index, float32_t normalized_frequency)
{ {
assert(index < LFOIndex::kLFOCount);
if(enable_lfo) if(enable_lfo)
{ {
this->lfo_[index]->setNormalizedFrequency(normalized_frequency); this->lfo_[index]->setNormalizedFrequency(normalized_frequency);
@ -317,8 +367,7 @@ public:
c->write_ptr_ = write_ptr_; c->write_ptr_ = write_ptr_;
if(enable_lfo) if(enable_lfo)
{ {
c->lfo_value_[LFO_1] = this->lfo_[LFO_1]->process(); for(unsigned i = 0; i < LFOIndex::kLFOCount; ++i) c->lfo_value_[i] = this->lfo_[i]->process();
c->lfo_value_[LFO_2] = this->lfo_[LFO_2]->process();
} }
} }
@ -328,8 +377,8 @@ private:
MASK = size - 1 MASK = size - 1
}; };
uint16_t* buffer_; T* buffer_;
unsigned write_ptr_; int32_t write_ptr_;
LFO* lfo_[2]; LFO* lfo_[LFOIndex::kLFOCount];
}; };

@ -50,7 +50,7 @@ public:
float32_t getDepth() const; float32_t getDepth() const;
private: private:
typedef FxEngine<4096, FORMAT_16_BIT, false> Engine; typedef FxEngine<4096, Format::FORMAT_FLOAT32, false> Engine;
Engine engine_; Engine engine_;
float32_t depth_; float32_t depth_;

@ -35,16 +35,16 @@ void ShimmerReverb::processSample(float32_t inL, float32_t inR, float32_t& outL,
// (4 AP diffusers on the input, then a loop of 2x 2AP+1Delay). // (4 AP diffusers on the input, then a loop of 2x 2AP+1Delay).
// Modulation is applied in the loop of the first diffuser AP for additional // Modulation is applied in the loop of the first diffuser AP for additional
// smearing; and to the two long delays for a slow shimmer/chorus effect. // smearing; and to the two long delays for a slow shimmer/chorus effect.
typedef Engine::Reserve<113, typedef Engine::Reserve< 113,
Engine::Reserve<162, Engine::Reserve< 162,
Engine::Reserve<241, Engine::Reserve< 241,
Engine::Reserve<399, Engine::Reserve< 399,
Engine::Reserve<1653, Engine::Reserve<1653,
Engine::Reserve<2038, Engine::Reserve<2038,
Engine::Reserve<3411, Engine::Reserve<3411,
Engine::Reserve<1913, Engine::Reserve<1913,
Engine::Reserve<1663, Engine::Reserve<1663,
Engine::Reserve<4782> > > > > > > > > > Memory; Engine::Reserve<4782> > > > > > > > > > Memory;
Engine::DelayLine<Memory, 0> ap1; Engine::DelayLine<Memory, 0> ap1;
Engine::DelayLine<Memory, 1> ap2; Engine::DelayLine<Memory, 1> ap2;
Engine::DelayLine<Memory, 2> ap3; Engine::DelayLine<Memory, 2> ap3;
@ -65,14 +65,13 @@ void ShimmerReverb::processSample(float32_t inL, float32_t inR, float32_t& outL,
float32_t lp_1 = this->lp_decay_1_; float32_t lp_1 = this->lp_decay_1_;
float32_t lp_2 = this->lp_decay_2_; float32_t lp_2 = this->lp_decay_2_;
float32_t wet; float32_t wet = 0.0f;
float32_t apout = 0.0f; float32_t apout = 0.0f;
engine_.start(&c); engine_.start(&c);
// Smear AP1 inside the loop. // Smear AP1 inside the loop.
c.interpolate(ap1, 10.0f, Engine::LFOIndex::LFO_1, 60.0f, 1.0f); c.interpolate(ap1, 10.0f, Engine::LFOIndex::LFO_1, 60.0f, 1.0f);
c.write(ap1, 100, 0.0f); c.write(ap1, 100, 0.0f);
c.read(inL + inR, gain); c.read(inL + inR, gain);
// Diffuse through 4 allpasses. // Diffuse through 4 allpasses.
@ -97,10 +96,10 @@ void ShimmerReverb::processSample(float32_t inL, float32_t inR, float32_t& outL,
c.write(del1, 2.0f); c.write(del1, 2.0f);
c.write(wet, 0.0f); c.write(wet, 0.0f);
outR += wet; outR = wet;
c.load(apout); c.load(apout);
// c.Interpolate(del1, 4450.0f, LFO_1, 50.0f, krt); c.interpolate(del1, 4450.0f, Engine::LFOIndex::LFO_1, 50.0f, krt);
c.read(del1 TAIL, krt); c.read(del1 TAIL, krt);
c.lp(lp_2, klp); c.lp(lp_2, klp);
c.read(dap2a TAIL, kap); c.read(dap2a TAIL, kap);
@ -110,7 +109,7 @@ void ShimmerReverb::processSample(float32_t inL, float32_t inR, float32_t& outL,
c.write(del2, 2.0f); c.write(del2, 2.0f);
c.write(wet, 0.0f); c.write(wet, 0.0f);
outR += wet; outR = wet;
this->lp_decay_1_ = lp_1; this->lp_decay_1_ = lp_1;
this->lp_decay_2_ = lp_2; this->lp_decay_2_ = lp_2;

@ -47,7 +47,7 @@ public:
float32_t getLP() const; float32_t getLP() const;
private: private:
typedef FxEngine<16384, FORMAT_16_BIT, true> Engine; typedef FxEngine<16384, Format::FORMAT_FLOAT32, true> Engine;
Engine engine_; Engine engine_;
float32_t input_gain_; float32_t input_gain_;

@ -5,13 +5,13 @@
StateVariableFilter::StateVariableFilter(float32_t sampling_rate, Type type, float32_t cutoff) : StateVariableFilter::StateVariableFilter(float32_t sampling_rate, Type type, float32_t cutoff) :
FXElement(sampling_rate), FXElement(sampling_rate),
type_(type), type_(type),
cutoff_(0.0f), gain_(-1.0f),
resonance_(0.0f), cutoff_(cutoff),
peak_gain_(0.0f) resonance_(0.0f)
{ {
this->setPeakGainDB(1.0f);
this->setCutoff(cutoff); this->setCutoff(cutoff);
this->setResonance(0.0f); this->setResonance(0.0f);
this->setGainDB(0.0f);
this->reset(); this->reset();
} }
@ -49,11 +49,13 @@ void StateVariableFilter::setResonance(float32_t resonance)
} }
} }
void StateVariableFilter::setPeakGainDB(float32_t gain) void StateVariableFilter::setGainDB(float32_t gainDB)
{ {
if(this->peak_gain_ != gain) gainDB = constrain(gainDB, -1.0f, 1.0f);
if(this->gain_ != gainDB)
{ {
this->peak_gain_ = gain; this->gain_ = gainDB;
this->g_ = std::pow(10.0f, 1.2f * this->gain_);
this->updateCoefficients(); this->updateCoefficients();
} }
} }
@ -61,130 +63,88 @@ void StateVariableFilter::setPeakGainDB(float32_t gain)
void StateVariableFilter::updateCoefficients() void StateVariableFilter::updateCoefficients()
{ {
// Compute the filter coefficients based on the current parameter values // Compute the filter coefficients based on the current parameter values
float32_t w0 = PI * this->cutoff_ / this->getSamplingRate(); this->w_ = 2.0f * std::tan(PI * this->cutoff_ / this->getSamplingRate());
float32_t V = pow(10, fabs(this->peak_gain_) / 20.0f); this->a_ = this->w_ / this->resonance_;
float32_t K = std::tan(w0); this->b_ = this->w_ * this->w_;
float32_t K2 = K * K; float32_t a_b = this->a_ + this->b_;
float32_t norm; 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->type_)
{ {
case Type::LPF: case Type::LPF:
norm = 1.0f / (1.0f + K / this->resonance_ + K2); this->d1_ = 0.0f;
this->a0_ = K2 * norm; this->d0_ = 0.25f * this->c1_ * this->c2_;
this->a1_ = 2.0f * this->a0_;
this->a2_ = this->a0_;
this->b1_ = 2.0f * (K2 - 1.0f) * norm;
this->b2_ = (1.0f - K / this->resonance_ + K2) * norm;
break; break;
case Type::HPF: case Type::HPF:
norm = 1.0f / (1.0f + K / this->resonance_ + K2); this->d1_ = 0.0f;
this->a0_ = norm; this->d0_ = 1.0f - 0.5f * this->c1_ + 0.25f * this->c1_ * this->c2_;
this->a1_ = -2.0f * this->a0_;
this->a2_ = this->a0_;
this->b1_ = 2.0f * (K2 - 1.0f) * norm;
this->b2_ = (1.0f - K / this->resonance_ + K2) * norm;
break; break;
case Type::BPF: case Type::BPF:
norm = 1.0f / (1.0f + K / this->resonance_ + K2); this->d1_ = 1.0f - this->c2_;
this->a0_ = K / this->resonance_ * norm; this->d0_ = this->d1_ * this->c1_ * 0.5f;
this->a1_ = 0.0f;
this->a2_ = -this->a0_;
this->b1_ = 2.0f * (K2 - 1.0f) * norm;
this->b2_ = (1.0f - K / this->resonance_ + K2) * norm;
break;
case Type::NOTCH:
norm = 1.0f / (1.0f + K / this->resonance_ + K2);
this->a0_ = (1.0f + K2) * norm;
this->a1_ = 2.0f * (K2 - 1.0f) * norm;
this->a2_ = this->a0_;
this->b1_ = 2.0f * (K2 - 1.0f) * norm;
this->b2_ = (1.0f - K / this->resonance_ + K2) * norm;
break; break;
case Type::PEQ: }
if(this->peak_gain_ >= 0)
this->reset();
}
void StateVariableFilter::reset()
{
memset(this->z1_, 0, StereoChannels::kNumChannels * sizeof(float32_t));
memset(this->z2_, 0, StereoChannels::kNumChannels * sizeof(float32_t));
}
void StateVariableFilter::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{
const float32_t gain = this->g_;
switch(this->type_)
{
case Type::LPF:
{ {
// boost const float32_t x = inL - this->z1_[StereoChannels::Left] - this->z2_[StereoChannels::Left] + 1e-20f;
norm = 1.0f / (1.0f + 1.0f / this->resonance_ * K + K2); this->z2_[StereoChannels::Left] += this->c2_ * this->z1_[StereoChannels::Left];
this->a0_ = (1.0f + V / this->resonance_ * K + K2) * norm; outL = gain * (this->d0_ * x + this->z2_[StereoChannels::Left]);
this->a1_ = 2.0f * (K2 - 1) * norm; this->z1_[StereoChannels::Left] += this->c1_ * x;
this->a2_ = (1.0f - V / this->resonance_ * K + K2) * norm;
this->b1_ = this->a1_;
this->b2_ = (1.0f - 1.0f / this->resonance_ * K + K2) * norm;
} }
else
{ {
// cut const float32_t x = inR - this->z1_[StereoChannels::Right] - this->z2_[StereoChannels::Right] + 1e-20f;
norm = 1.0f / (1 + V / this->resonance_ * K + K2); this->z2_[StereoChannels::Right] += this->c2_ * this->z1_[StereoChannels::Right];
this->a0_ = (1.0f + 1.0f / this->resonance_ * K + K2) * norm; outR = gain * (this->d0_ * x + this->z2_[StereoChannels::Right]);
this->a1_ = 2.0f * (K2 - 1) * norm; this->z1_[StereoChannels::Right] += this->c1_ * x;
this->a2_ = (1.0f - 1.0f / this->resonance_ * K + K2) * norm;
this->b1_ = this->a1_;
this->b2_ = (1.0f - V / this->resonance_ * K + K2) * norm;
} }
break; break;
case Type::LSH:
if(this->peak_gain_ >= 0) case Type::HPF:
{ {
// boost const float32_t x = inL - this->z1_[StereoChannels::Left] - this->z2_[StereoChannels::Left] + 1e-20f;
norm = 1 / (1 + std::sqrt(2) * K + K2); outL = gain * this->d0_ * x;
this->a0_ = (1.0f + std::sqrt(2.0f * V) * K + V * K2) * norm; this->z2_[StereoChannels::Left] += this->c2_ * this->z1_[StereoChannels::Left];
this->a1_ = 2.0f * (V * K2 - 1.0f) * norm; this->z1_[StereoChannels::Left] += this->c1_ * x;
this->a2_ = (1.0f - std::sqrt(2.0f * V) * K + V * K2) * norm;
this->b1_ = 2.0f * (K2 - 1.0f) * norm;
this->b2_ = (1.0f - std::sqrt(2.0f) * K + K2) * norm;
} }
else
{ {
// cutK * K const float32_t x = inR - this->z1_[StereoChannels::Right] - this->z2_[StereoChannels::Right] + 1e-20f;
norm = 1.0f / (1.0f + std::sqrt(2.0f * V) * K + V * K2); outR = gain * this->d0_ * x;
this->a0_ = (1.0f + std::sqrt(2.0f) * K + K2) * norm; this->z2_[StereoChannels::Right] += this->c2_ * this->z1_[StereoChannels::Right];
this->a1_ = 2.0f * (K2 - 1.0f) * norm; this->z1_[StereoChannels::Right] += this->c1_ * x;
this->a2_ = (1.0f - std::sqrt(2.0f) * K + K2) * norm;
this->b1_ = 2.0f * (V * K2 - 1.0f) * norm;
this->b2_ = (1.0f - std::sqrt(2.0f * V) * K + V * K2) * norm;
} }
break; break;
case Type::HSH:
if(this->peak_gain_ >= 0) case Type::BPF:
{ {
// boost const float32_t x = inL - this->z1_[StereoChannels::Left] - this->z2_[StereoChannels::Left] + 1e-20f;
norm = 1.0f / (1.0f + std::sqrt(2.0f) * K + K2); outL = gain * (this->d0_ * x) + this->d1_ * this->z1_[StereoChannels::Left];
this->a0_ = (V + std::sqrt(2.0f * V) * K + K2) * norm; this->z2_[StereoChannels::Left] += this->c2_ * this->z1_[StereoChannels::Left];
this->a1_ = 2.0f * (K2 - V) * norm; this->z1_[StereoChannels::Left] += this->c1_ * x;
this->a2_ = (V - std::sqrt(2.0f * V) * K + K2) * norm;
this->b1_ = 2.0f * (K2 - 1.0f) * norm;
this->b2_ = (1.0f - std::sqrt(2.0f) * K + K2) * norm;
} }
else
{ {
// cut const float32_t x = inR - this->z1_[StereoChannels::Right] - this->z2_[StereoChannels::Right] + 1e-20f;
norm = 1.0f / (V + std::sqrt(2.0f * V) * K + K2); outL = gain * (this->d0_ * x) + this->d1_ * this->z1_[StereoChannels::Right];
this->a0_ = (1.0f + std::sqrt(2.0f) * K + K2) * norm; this->z2_[StereoChannels::Right] += this->c2_ * this->z1_[StereoChannels::Right];
this->a1_ = 2.0f * (K2 - 1.0f) * norm; this->z1_[StereoChannels::Right] += this->c1_ * x;
this->a2_ = (1.0f - std::sqrt(2.0f) * K + K2) * norm;
this->b1_ = 2.0f * (K2 - V) * norm;
this->b2_ = (V - std::sqrt(2.0f * V) * K + K2) * norm;
} }
break; break;
} }
} }
void StateVariableFilter::reset()
{
memset(this->z1_, 0, 2 * sizeof(float32_t));
memset(this->z2_, 0, 2 * sizeof(float32_t));
}
void StateVariableFilter::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{
const float32_t gain = 10.0f;
outL = (inL * this->a0_ + this->z1_[0]) * gain;
this->z1_[0] = inL * this->a1_ + this->z2_[0] - this->b1_ * outL;
this->z2_[0] = inL * this->a2_ - this->b2_ * outL;
outR = (inR * this->a0_ + this->z1_[1]) * gain;
this->z1_[0] = inR * this->a1_ + this->z2_[1] - this->b1_ * outR;
this->z2_[0] = inR * this->a2_ - this->b2_ * outR;
}

@ -19,6 +19,7 @@
// //
#include "fx.h" #include "fx.h"
#include "mixing_console_constants.h"
class StateVariableFilter : public FXElement class StateVariableFilter : public FXElement
{ {
@ -29,20 +30,16 @@ public:
{ {
LPF, // Low pass filter LPF, // Low pass filter
HPF, // High pass filter HPF, // High pass filter
BPF, // Band pass filter BPF // Band pass filter
NOTCH, // Notch Filter
PEQ, // Peaking band EQ filter
LSH, // Low shelf filter
HSH // High shelf filter
} Type; } Type;
StateVariableFilter(float32_t sampling_rate, Type type, float32_t cutoff); StateVariableFilter(float32_t sampling_rate, Type type, float32_t cutoff);
virtual ~StateVariableFilter(); virtual ~StateVariableFilter();
void setFilterType(Type type); void setFilterType(Type type);
void setGainDB(float32_t gainDB);
void setCutoff(float32_t cutoff); void setCutoff(float32_t cutoff);
void setResonance(float32_t resonance); void setResonance(float32_t resonance);
void setPeakGainDB(float32_t gainDB);
virtual void reset() override; virtual void reset() override;
virtual void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) override; virtual void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) override;
@ -51,14 +48,17 @@ private:
void updateCoefficients(); void updateCoefficients();
Type type_; Type type_;
float32_t gain_;
float32_t cutoff_; float32_t cutoff_;
float32_t resonance_; float32_t resonance_;
float32_t peak_gain_; float32_t g_;
float32_t a0_; float32_t w_;
float32_t a1_; float32_t a_;
float32_t a2_; float32_t b_;
float32_t b1_; float32_t c1_;
float32_t b2_; float32_t c2_;
float32_t z1_[2]; float32_t d0_;
float32_t z2_[2]; float32_t d1_;
float32_t z1_[StereoChannels::kNumChannels];
float32_t z2_[StereoChannels::kNumChannels];
}; };

@ -5,7 +5,7 @@
Tube::Tube(float32_t samplingRate) : Tube::Tube(float32_t samplingRate) :
FXElement(samplingRate), FXElement(samplingRate),
overdrive_(0.0f), overdrive_(0.0f),
saturation_(0.0f) saturator_factor_(0.0f)
{ {
this->setOverdrive(0.0f); this->setOverdrive(0.0f);
} }
@ -21,14 +21,20 @@ void Tube::reset()
void Tube::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) void Tube::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{ {
outL = softSaturator2(inL, this->saturation_); outL = softSaturator4(inL, this->saturator_factor_);
outR = softSaturator2(inR, this->saturation_); outR = softSaturator4(inR, this->saturator_factor_);
} }
void Tube::setOverdrive(float32_t overdrive) void Tube::setOverdrive(float32_t overdrive)
{ {
this->overdrive_ = constrain(overdrive, 0.0f, 1.0f); static const float32_t N = 200.0f;
this->saturation_ = 2.0f * this->overdrive_;
overdrive = constrain(overdrive, 0.0f, 1.0f);
if(this->overdrive_ != overdrive)
{
this->overdrive_ = overdrive;
this->saturator_factor_ = 1.0f + N * overdrive;
}
} }
float32_t Tube::getOverdrive() const float32_t Tube::getOverdrive() const

@ -36,5 +36,5 @@ public:
private: private:
float32_t overdrive_; float32_t overdrive_;
float32_t saturation_; float32_t saturator_factor_;
}; };

@ -0,0 +1,101 @@
// 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_unit2.h
//
// Unit of FX that handle the mute parameter
//
#pragma once
#include "fx_components.h"
#include <iostream>
using namespace std;
class FXUnitModule2
{
DISALLOW_COPY_AND_ASSIGN(FXUnitModule2);
public:
FXUnitModule2(bool mute = false)
{
this->setMute(mute);
}
virtual ~FXUnitModule2()
{
}
virtual void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) = 0;
void setMute(bool mute = false)
{
this->mute_ = mute;
}
inline bool isMute() const
{
return this->mute_;
}
protected:
bool mute_;
};
template<typename _FXElement>
class FXUnit2 : public virtual FXUnitModule2, public virtual _FXElement
{
DISALLOW_COPY_AND_ASSIGN(FXUnit2);
public:
FXUnit2(float32_t sampling_rate, bool mute = false) :
FXUnitModule2(mute),
_FXElement(sampling_rate),
is_reset_(false)
{
this->setMute(mute);
}
virtual ~FXUnit2()
{
}
void reset()
{
if(!this->is_reset_)
{
_FXElement::reset();
this->is_reset_ = true;
}
}
void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{
if(this->isMute())
{
this->reset();
outL = 0.0f;
outR = 0.0f;
}
else
{
this->is_reset_ = false;
_FXElement::processSample(inL, inR, outL, outR);
}
}
private:
bool is_reset_;
};

@ -47,7 +47,10 @@ LOGMODULE ("mididevice");
#define MIDI_CC_RESONANCE 71 #define MIDI_CC_RESONANCE 71
#define MIDI_CC_FREQUENCY_CUTOFF 74 #define MIDI_CC_FREQUENCY_CUTOFF 74
#define MIDI_CC_REVERB_LEVEL 91 #define MIDI_CC_REVERB_LEVEL 91
#define MIDI_CC_ORBITONE_LEVEL 92 // added with mixing console
#define MIDI_CC_CHORUS_LEVEL 93 // added with mixing console
#define MIDI_CC_DETUNE_LEVEL 94 #define MIDI_CC_DETUNE_LEVEL 94
#define MIDI_CC_PHASER_LEVEL 95 // added with mixing console
#define MIDI_CC_ALL_SOUND_OFF 120 #define MIDI_CC_ALL_SOUND_OFF 120
#define MIDI_CC_ALL_NOTES_OFF 123 #define MIDI_CC_ALL_NOTES_OFF 123
#define MIDI_PROGRAM_CHANGE 0b1100 #define MIDI_PROGRAM_CHANGE 0b1100
@ -300,9 +303,25 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
break; break;
case MIDI_CC_REVERB_LEVEL: case MIDI_CC_REVERB_LEVEL:
#ifdef MIXING_CONSOLE_ENABLE
this->m_pSynthesizer->setMixingConsoleSendLevel(nTG, MixerOutput::FX_PlateReverb, maplong(pMessage[2], 0, 127, 0, 99));
#else
m_pSynthesizer->SetReverbSend (maplong (pMessage[2], 0, 127, 0, 99), nTG); m_pSynthesizer->SetReverbSend (maplong (pMessage[2], 0, 127, 0, 99), nTG);
#endif
break; break;
#ifdef MIXING_CONSOLE_ENABLE
case MIDI_CC_ORBITONE_LEVEL:
this->m_pSynthesizer->setMixingConsoleSendLevel(nTG, MixerOutput::FX_Orbitone, maplong(pMessage[2], 0, 127, 0, 99));
break;
case MIDI_CC_CHORUS_LEVEL:
this->m_pSynthesizer->setMixingConsoleSendLevel(nTG, MixerOutput::FX_Chorus, maplong(pMessage[2], 0, 127, 0, 99));
break;
case MIDI_CC_PHASER_LEVEL:
this->m_pSynthesizer->setMixingConsoleSendLevel(nTG, MixerOutput::FX_Phaser, maplong(pMessage[2], 0, 127, 0, 99));
break;
#endif
case MIDI_CC_DETUNE_LEVEL: case MIDI_CC_DETUNE_LEVEL:
if (pMessage[2] == 0) if (pMessage[2] == 0)
{ {

File diff suppressed because it is too large Load Diff

@ -45,8 +45,10 @@
#include "effect_platervbstereo.h" #include "effect_platervbstereo.h"
#include "effect_compressor.h" #include "effect_compressor.h"
#ifdef FXRACK_ENABLE #ifdef MIXING_CONSOLE_ENABLE
#include "fx_rack.h" #include "mixing_console.h"
typedef MixingConsole<CConfig::ToneGenerators> Mixer;
#endif #endif
class CMiniDexed class CMiniDexed
@ -91,7 +93,12 @@ public:
void setBreathController (uint8_t value, unsigned nTG); void setBreathController (uint8_t value, unsigned nTG);
void setAftertouch (uint8_t value, unsigned nTG); void setAftertouch (uint8_t value, unsigned nTG);
#ifdef MIXING_CONSOLE_ENABLE
void setMixingConsoleSendLevel(unsigned nTG, MixerOutput fx, unsigned nFXSend);
void setMixingConsoleReturnLevel(MixerOutput ret, MixerOutput fx, unsigned nFXReturn);
#else
void SetReverbSend (unsigned nReverbSend, unsigned nTG); // 0 .. 127 void SetReverbSend (unsigned nReverbSend, unsigned nTG); // 0 .. 127
#endif
void setMonoMode(uint8_t mono, uint8_t nTG); void setMonoMode(uint8_t mono, uint8_t nTG);
void setPitchbendRange(uint8_t range, uint8_t nTG); void setPitchbendRange(uint8_t range, uint8_t nTG);
@ -140,60 +147,124 @@ public:
ParameterReverbDiffusion, ParameterReverbDiffusion,
ParameterReverbLevel, ParameterReverbLevel,
// BEGIN FXRack global parameters definition #ifdef MIXING_CONSOLE_ENABLE
#ifdef FXRACK_ENABLE // BEGIN FX global parameters definition
// FXChain parameters // Tube parameters
ParameterFXChainEnable, ParameterFXTubeEnable,
ParameterFXChainWet, ParameterFXTubeOverdrive,
// FXChain > Tube parameters // Chorus parameters
ParameterFXChainTubeEnable, ParameterFXChorusEnable,
ParameterFXChainTubeWet, ParameterFXChorusRate,
ParameterFXChainTubeOverdrive, ParameterFXChorusDepth,
// FXChain > Chorus parameters // Flanger parameters
ParameterFXChainChorusEnable, ParameterFXFlangerEnable,
ParameterFXChainChorusWet, ParameterFXFlangerRate,
ParameterFXChainChorusRate, ParameterFXFlangerDepth,
ParameterFXChainChorusDepth, ParameterFXFlangerFeedback,
// FXChain > Flanger parameters // Orbitone parameters
ParameterFXChainFlangerEnable, ParameterFXOrbitoneEnable,
ParameterFXChainFlangerWet, ParameterFXOrbitoneRate,
ParameterFXChainFlangerRate, ParameterFXOrbitoneDepth,
ParameterFXChainFlangerDepth,
ParameterFXChainFlangerFeedback, // Phaser parameters
ParameterFXPhaserEnable,
// FXChain > Orbitone parameters ParameterFXPhaserRate,
ParameterFXChainOrbitoneEnable, ParameterFXPhaserDepth,
ParameterFXChainOrbitoneWet, ParameterFXPhaserFeedback,
ParameterFXChainOrbitoneRate, ParameterFXPhaserNbStages,
ParameterFXChainOrbitoneDepth,
// Delay parameters
// FXChain > Phaser parameters ParameterFXDelayEnable,
ParameterFXChainPhaserEnable, ParameterFXDelayLeftDelayTime,
ParameterFXChainPhaserWet, ParameterFXDelayRightDelayTime,
ParameterFXChainPhaserRate, ParameterFXDelayFeedback,
ParameterFXChainPhaserDepth, ParameterFXDelayFlutterRate,
ParameterFXChainPhaserFeedback, ParameterFXDelayFlutterAmount,
ParameterFXChainPhaserNbStages,
// ShimmerReverb parameters
// FXChain > Delay parameters ParameterFXShimmerReverbEnable,
ParameterFXChainDelayEnable, ParameterFXShimmerReverbInputGain,
ParameterFXChainDelayWet, ParameterFXShimmerReverbTime,
ParameterFXChainDelayLeftDelayTime, ParameterFXShimmerReverbDiffusion,
ParameterFXChainDelayRightDelayTime, ParameterFXShimmerReverbLP,
ParameterFXChainDelayFeedback,
// Tube Return parameters
// FXChain > ShimmerReverb parameters ParameterFXTube_ChorusReturn,
ParameterFXChainShimmerReverbEnable, ParameterFXTube_FlangerReturn,
ParameterFXChainShimmerReverbWet, ParameterFXTube_OrbitoneReturn,
ParameterFXChainShimmerReverbInputGain, ParameterFXTube_PhaserReturn,
ParameterFXChainShimmerReverbTime, ParameterFXTube_DelayReturn,
ParameterFXChainShimmerReverbDiffusion, ParameterFXTube_ReverbReturn,
ParameterFXChainShimmerReverbLP, ParameterFXTube_ShimmerReturn,
#endif
// END FXRack global parameters definition // Chorus Return parameters
ParameterFXChorus_TubeReturn,
ParameterFXChorus_FlangerReturn,
ParameterFXChorus_OrbitoneReturn,
ParameterFXChorus_PhaserReturn,
ParameterFXChorus_DelayReturn,
ParameterFXChorus_ReverbReturn,
ParameterFXChorus_ShimmerReturn,
// Flanger Return parameters
ParameterFXFlanger_TubeReturn,
ParameterFXFlanger_ChorusReturn,
ParameterFXFlanger_OrbitoneReturn,
ParameterFXFlanger_PhaserReturn,
ParameterFXFlanger_DelayReturn,
ParameterFXFlanger_ReverbReturn,
ParameterFXFlanger_ShimmerReturn,
// Orbitone Return parameters
ParameterFXOrbitone_TubeReturn,
ParameterFXOrbitone_ChorusReturn,
ParameterFXOrbitone_FlangerReturn,
ParameterFXOrbitone_PhaserReturn,
ParameterFXOrbitone_DelayReturn,
ParameterFXOrbitone_ReverbReturn,
ParameterFXOrbitone_ShimmerReturn,
// Phaser Return parameters
ParameterFXPhaser_TubeReturn,
ParameterFXPhaser_ChorusReturn,
ParameterFXPhaser_FlangerReturn,
ParameterFXPhaser_OrbitoneReturn,
ParameterFXPhaser_DelayReturn,
ParameterFXPhaser_ReverbReturn,
ParameterFXPhaser_ShimmerReturn,
// Delay Return parameters
ParameterFXDelay_TubeReturn,
ParameterFXDelay_ChorusReturn,
ParameterFXDelay_FlangerReturn,
ParameterFXDelay_OrbitoneReturn,
ParameterFXDelay_PhaserReturn,
ParameterFXDelay_ReverbReturn,
ParameterFXDelay_ShimmerReturn,
// Reverb Return parameters
ParameterFXReverb_TubeReturn,
ParameterFXReverb_ChorusReturn,
ParameterFXReverb_FlangerReturn,
ParameterFXReverb_OrbitoneReturn,
ParameterFXReverb_PhaserReturn,
ParameterFXReverb_DelayReturn,
ParameterFXReverb_ShimmerReturn,
// Shimmer Return parameters
ParameterFXShimmer_TubeReturn,
ParameterFXShimmer_ChorusReturn,
ParameterFXShimmer_FlangerReturn,
ParameterFXShimmer_OrbitoneReturn,
ParameterFXShimmer_PhaserReturn,
ParameterFXShimmer_DelayReturn,
ParameterFXShimmer_ReverbReturn,
// END FX global parameters definition
#endif
ParameterUnknown ParameterUnknown
}; };
@ -217,7 +288,9 @@ public:
TGParameterCutoff, TGParameterCutoff,
TGParameterResonance, TGParameterResonance,
TGParameterMIDIChannel, TGParameterMIDIChannel,
#ifndef MIXING_CONSOLE_ENABLE
TGParameterReverbSend, TGParameterReverbSend,
#endif // undef MIXING_CONSOLE_ENABLE
TGParameterPitchBendRange, TGParameterPitchBendRange,
TGParameterPitchBendStep, TGParameterPitchBendStep,
TGParameterPortamentoMode, TGParameterPortamentoMode,
@ -245,6 +318,18 @@ public:
TGParameterATAmplitude, TGParameterATAmplitude,
TGParameterATEGBias, TGParameterATEGBias,
#ifdef MIXING_CONSOLE_ENABLE
TGParameterMixingSendFXTube,
TGParameterMixingSendFXChorus,
TGParameterMixingSendFXFlanger,
TGParameterMixingSendFXOrbittone,
TGParameterMixingSendFXPhaser,
TGParameterMixingSendFXDelay,
TGParameterMixingSendFXPlateReverb,
TGParameterMixingSendFXShimmerReverb,
TGParameterMixingSendFXMainOutput,
#endif // MIXING_CONSOLE_ENABLE
TGParameterUnknown TGParameterUnknown
}; };
@ -315,7 +400,12 @@ private:
unsigned m_nNoteLimitHigh[CConfig::ToneGenerators]; unsigned m_nNoteLimitHigh[CConfig::ToneGenerators];
int m_nNoteShift[CConfig::ToneGenerators]; int m_nNoteShift[CConfig::ToneGenerators];
#ifdef MIXING_CONSOLE_ENABLE
unsigned m_nFXSendLevel[CConfig::ToneGenerators][MixerOutput::kFXCount];
unsigned m_nFXReturnLevel[MixerOutput::kFXCount - 1][MixerOutput::kFXCount];
#else
unsigned m_nReverbSend[CConfig::ToneGenerators]; unsigned m_nReverbSend[CConfig::ToneGenerators];
#endif
uint8_t m_nRawVoiceData[156]; uint8_t m_nRawVoiceData[156];
@ -345,15 +435,16 @@ private:
CPerformanceTimer m_GetChunkTimer; CPerformanceTimer m_GetChunkTimer;
bool m_bProfileEnabled; bool m_bProfileEnabled;
#ifdef MIXING_CONSOLE_ENABLE
Mixer* mixing_console_;
#else
AudioEffectPlateReverb* reverb; AudioEffectPlateReverb* reverb;
AudioStereoMixer<CConfig::ToneGenerators>* tg_mixer; AudioStereoMixer<CConfig::ToneGenerators>* tg_mixer;
AudioStereoMixer<CConfig::ToneGenerators>* reverb_send_mixer; AudioStereoMixer<CConfig::ToneGenerators>* reverb_send_mixer;
#endif
CSpinLock m_FXSpinLock; CSpinLock m_FXSpinLock;
#ifdef FXRACK_ENABLE
FXRack* fx_rack;
#endif
bool m_bSavePerformance; bool m_bSavePerformance;
bool m_bSavePerformanceNewFile; bool m_bSavePerformanceNewFile;

@ -0,0 +1,354 @@
//
// mixing_console.hpp
//
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
// Copyright (C) 2022 The MiniDexed Team
//
// 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/>.
//
// Implementation of the MixingConsole class defined in mixing_console.h
#include "mixing_console.h"
template<size_t nb_inputs>
MixingConsole<nb_inputs>::MixingConsole(float32_t sampling_rate, size_t buffer_size) :
FXBase(sampling_rate),
BufferSize(buffer_size)
{
for(size_t i = 0; i < nb_inputs; ++i)
{
this->input_sample_buffer_[StereoChannels::Left ][i] = new float32_t[this->BufferSize];
this->input_sample_buffer_[StereoChannels::Right][i] = new float32_t[this->BufferSize];
memset(this->input_sample_buffer_[StereoChannels::Left ][i], 0, this->BufferSize);
memset(this->input_sample_buffer_[StereoChannels::Right][i], 0, this->BufferSize);
}
memset(this->fx_, 0, MixerOutput::kFXCount * sizeof(FXElement*));
this->fx_[MixerOutput::FX_Tube] = this->tube_ = new FXUnit2<Tube>(sampling_rate);
this->fx_[MixerOutput::FX_Chorus] = this->chorus_ = new FXUnit2<Chorus>(sampling_rate);
this->fx_[MixerOutput::FX_Flanger] = this->flanger_ = new FXUnit2<Flanger>(sampling_rate);
this->fx_[MixerOutput::FX_Orbitone] = this->orbitone_ = new FXUnit2<Orbitone>(sampling_rate);
this->fx_[MixerOutput::FX_Phaser] = this->phaser_ = new FXUnit2<Phaser>(sampling_rate);
this->fx_[MixerOutput::FX_Delay] = this->delay_ = new FXUnit2<Delay>(sampling_rate);
this->fx_[MixerOutput::FX_PlateReverb] = this->plate_reverb_ = new FXUnit2<AudioEffectPlateReverb>(sampling_rate);
this->fx_[MixerOutput::FX_ShimmerReverb] = this->shimmer_reverb_ = new FXUnit2<ShimmerReverb>(sampling_rate);
this->fx_[MixerOutput::MainOutput] = this->dry_ = new FXUnit2<Dry>(sampling_rate);
this->init();
}
template<size_t nb_inputs>
MixingConsole<nb_inputs>::~MixingConsole()
{
for(size_t i = 0; i < nb_inputs; ++i)
{
delete this->input_sample_buffer_[StereoChannels::Left ][i];
delete this->input_sample_buffer_[StereoChannels::Right][i];
}
for(size_t i = 0; i < MixerOutput::kFXCount; ++i)
{
delete this->fx_[i];
}
}
// Send section
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setChannelLevel(size_t in, float32_t lvl)
{
assert(in < nb_inputs);
lvl = constrain(lvl, 0.0f, 1.0f);
if(lvl == this->channel_level_[in]) return;
this->channel_level_[in] = lvl;
this->updatePan();
}
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setPan(size_t in, float32_t pan)
{
assert(in < nb_inputs);
pan = constrain(pan, 0.0f, 1.0f);
if(pan == this->pan_[StereoChannels::kNumChannels][in]) return;
this->pan_[StereoChannels::kNumChannels][in] = pan;
this->updatePan(in);
}
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::updatePan(size_t in)
{
float32_t pan = mapfloat(this->pan_[StereoChannels::kNumChannels][in], 0.0f, 1.0f, 0.0, Constants::MPI_2);
this->pan_[StereoChannels::Left ][in] = arm_sin_f32(pan) * this->channel_level_[in];
this->pan_[StereoChannels::Right][in] = arm_cos_f32(pan) * this->channel_level_[in];
}
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setSendLevel(size_t in, MixerOutput fx, float32_t lvl)
{
assert(in < nb_inputs);
assert(fx < kFXCount);
this->setLevel(in, fx, lvl);
}
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setInputSample(size_t in, float32_t sampleL, float32_t sampleR)
{
assert(in < nb_inputs);
this->setSample(in, sampleL, sampleR);
}
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setInputSampleBuffer(size_t in, float32_t* samples)
{
assert(in < nb_inputs);
if(samples != nullptr)
{
arm_scale_f32(samples, this->pan_[StereoChannels::Left ][in], this->input_sample_buffer_[StereoChannels::Left ][in], this->BufferSize);
arm_scale_f32(samples, this->pan_[StereoChannels::Right][in], this->input_sample_buffer_[StereoChannels::Right][in], this->BufferSize);
}
else
{
memset(this->input_sample_buffer_[StereoChannels::Left ][in], 0, this->BufferSize * sizeof(float32_t));
memset(this->input_sample_buffer_[StereoChannels::Right][in], 0, this->BufferSize * sizeof(float32_t));
}
}
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setInputSampleBuffer(size_t in, float32_t* samplesL, float32_t* samplesR)
{
assert(in < nb_inputs);
if(samplesL != nullptr)
{
memcpy(this->input_sample_buffer_[StereoChannels::Left ][in], samplesL, this->BufferSize * sizeof(float32_t));
}
else
{
memset(this->input_sample_buffer_[StereoChannels::Left ][in], 0, this->BufferSize * sizeof(float32_t));
}
if(samplesR != nullptr)
{
memcpy(this->input_sample_buffer_[StereoChannels::Right][in], samplesR, this->BufferSize * sizeof(float32_t));
}
else
{
memset(this->input_sample_buffer_[StereoChannels::Right][in], 0, this->BufferSize * sizeof(float32_t));
}
}
// Return section
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setReturnLevel(MixerOutput ret, MixerOutput dest, float32_t lvl)
{
assert(ret < (kFXCount - 1));
assert(dest < kFXCount);
if(ret == dest)
{
// An FX cannot feedback on itself
return;
}
this->setLevel(nb_inputs + ret, dest, lvl);
}
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setReturnSample(MixerOutput ret, float32_t sampleL, float32_t sampleR)
{
assert(ret < (kFXCount - 1));
this->setSample(nb_inputs + ret, sampleL, sampleR);
}
// Global section
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setLevel(size_t in, MixerOutput fx, float32_t lvl)
{
assert(in < (nb_inputs + MixerOutput::kFXCount - 1));
assert(fx < MixerOutput::kFXCount);
this->levels_[fx][in] = constrain(lvl, 0.0f, 1.0f);
}
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setSample(size_t in, float32_t sampleL, float32_t sampleR)
{
assert(in < (nb_inputs + MixerOutput::kFXCount - 1));
this->input_samples_[StereoChannels::Left ][in] = sampleL;
this->input_samples_[StereoChannels::Right][in] = sampleR;
}
// Get FX
template<size_t nb_inputs>
FXElement* MixingConsole<nb_inputs>::getFX(size_t fx)
{
assert(fx < MixerOutput::kFXCount);
return this->fx_[fx];
}
template<size_t nb_inputs>
FXUnit2<Tube>* MixingConsole<nb_inputs>::getTube()
{
return this->tube_;
}
template<size_t nb_inputs>
FXUnit2<Chorus>* MixingConsole<nb_inputs>::getChorus()
{
return this->chorus_;
}
template<size_t nb_inputs>
FXUnit2<Flanger>* MixingConsole<nb_inputs>::getFlanger()
{
return this->flanger_;
}
template<size_t nb_inputs>
FXUnit2<Orbitone>* MixingConsole<nb_inputs>::getOrbitone()
{
return this->orbitone_;
}
template<size_t nb_inputs>
FXUnit2<Phaser>* MixingConsole<nb_inputs>::getPhaser()
{
return this->phaser_;
}
template<size_t nb_inputs>
FXUnit2<Delay>* MixingConsole<nb_inputs>::getDelay()
{
return this->delay_;
}
template<size_t nb_inputs>
FXUnit2<AudioEffectPlateReverb>* MixingConsole<nb_inputs>::getPlateReverb()
{
return this->plate_reverb_;
}
template<size_t nb_inputs>
FXUnit2<ShimmerReverb>* MixingConsole<nb_inputs>::getShimmerReverb()
{
return this->shimmer_reverb_;
}
template<size_t nb_inputs>
FXUnit2<Dry>* MixingConsole<nb_inputs>::getDry()
{
return this->dry_;
}
// Processing
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::init()
{
for(size_t i = 0; i < MixerOutput::kFXCount; ++i)
memset(this->levels_[i], 0, (nb_inputs + MixerOutput::kFXCount - 1) * sizeof(float32_t));
for(size_t i = 0; i < StereoChannels::kNumChannels; ++i)
memset(this->input_samples_[i], 0, (nb_inputs + MixerOutput::kFXCount - 1) * sizeof(float32_t));
this->reset();
}
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::reset()
{
for(size_t i = 0; i < nb_inputs; ++i)
{
memset(this->input_sample_buffer_[StereoChannels::Left ][i], 0, this->BufferSize);
memset(this->input_sample_buffer_[StereoChannels::Right][i], 0, this->BufferSize);
}
for(size_t i = 0; i < MixerOutput::kFXCount; ++i)
{
this->fx_[i]->reset();
}
for(size_t i = 0; i < MixerOutput::MainOutput; ++i)
{
this->setReturnSample(static_cast<MixerOutput>(i), 0.0f, 0.0f);
}
}
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::processSample(float32_t& outL, float32_t& outR)
{
float32_t fx_inputs_[MixerOutput::kFXCount][StereoChannels::kNumChannels];
float32_t fx_outputs_[MixerOutput::kFXCount][StereoChannels::kNumChannels];
for(size_t i = 0; i < MixerOutput::kFXCount; ++i)
{
// Compute the samples that will feed the MixerOutput and process MixerOutput
fx_inputs_[i][StereoChannels::Left ] = arm_weighted_sum_f32(this->input_samples_[StereoChannels::Left ], this->levels_[i], nb_inputs + MixerOutput::kFXCount - 1);
fx_inputs_[i][StereoChannels::Right] = arm_weighted_sum_f32(this->input_samples_[StereoChannels::Right], this->levels_[i], nb_inputs + MixerOutput::kFXCount - 1);
// Process the FX
this->fx_[i]->processSample(
fx_inputs_[i][StereoChannels::Left],
fx_inputs_[i][StereoChannels::Right],
fx_outputs_[i][StereoChannels::Left],
fx_outputs_[i][StereoChannels::Right]
);
if(i != MixerOutput::MainOutput)
{
// Feedback the resulting samples except for the main output
this->setReturnSample(
static_cast<MixerOutput>(i),
fx_outputs_[i][StereoChannels::Left],
fx_outputs_[i][StereoChannels::Right]
);
}
}
// Return this main output sample
outL = fx_inputs_[MixerOutput::MainOutput][StereoChannels::Left];
outR = fx_inputs_[MixerOutput::MainOutput][StereoChannels::Right];
}
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::process(float32_t* outL, float32_t* outR)
{
for(size_t s = 0; s < this->BufferSize; ++s)
{
for(size_t in = 0; in < nb_inputs; ++in)
{
this->setSample(
in,
this->input_sample_buffer_[StereoChannels::Left ][in][s],
this->input_sample_buffer_[StereoChannels::Right][in][s]
);
}
this->processSample(*outL, *outR);
++outL;
++outR;
}
}

@ -0,0 +1,96 @@
//
// mixing_console.h
//
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
// Copyright (C) 2022 The MiniDexed Team
//
// 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/>.
//
#pragma once
#include "mixing_console_constants.h"
#include "fx.h"
#include "fx_tube.h"
#include "fx_chorus.h"
#include "fx_flanger.h"
#include "fx_orbitone.h"
#include "fx_phaser.h"
#include "fx_delay.h"
#include "effect_platervbstereo.h"
#include "fx_shimmer_reverb.h"
#include "fx_dry.h"
#include "fx_unit2.hpp"
template<size_t nb_inputs = 8>
class MixingConsole : public FXBase
{
DISALLOW_COPY_AND_ASSIGN(MixingConsole);
public:
MixingConsole(float32_t sampling_rate, size_t buffer_size);
~MixingConsole();
void setChannelLevel(size_t in, float32_t lvl);
void setPan(size_t in, float32_t pan);
void setSendLevel(size_t in, MixerOutput fx, float32_t lvl);
void setInputSample(size_t in, float32_t sampleL, float32_t sampleR);
void setInputSampleBuffer(size_t in, float32_t* samples);
void setInputSampleBuffer(size_t in, float32_t* samplesL, float32_t* samplesR);
void setReturnLevel(MixerOutput ret, MixerOutput dest, float32_t lvl);
void setReturnSample(MixerOutput ret, float32_t _sampleL, float32_t _sampleR);
FXElement* getFX(size_t fx);
FXUnit2<Tube>* getTube();
FXUnit2<Chorus>* getChorus();
FXUnit2<Flanger>* getFlanger();
FXUnit2<Orbitone>* getOrbitone();
FXUnit2<Phaser>* getPhaser();
FXUnit2<Delay>* getDelay();
FXUnit2<AudioEffectPlateReverb>* getPlateReverb();
FXUnit2<ShimmerReverb>* getShimmerReverb();
FXUnit2<Dry>* getDry();
void init();
virtual void reset() override;
void processSample(float32_t& outL, float32_t& outR);
void process(float32_t* outL, float32_t* outR);
protected:
void updatePan(size_t in);
void setLevel(size_t in, MixerOutput fx, float32_t lvl);
void setSample(size_t in, float32_t sampleL, float32_t sampleR);
private:
const size_t BufferSize;
float32_t channel_level_[nb_inputs];
float32_t pan_[StereoChannels::kNumChannels + 1][nb_inputs];
float32_t* input_sample_buffer_[StereoChannels::kNumChannels][nb_inputs];
float32_t input_samples_[StereoChannels::kNumChannels][nb_inputs + MixerOutput::kFXCount - 1];
float32_t levels_[MixerOutput::kFXCount][nb_inputs + MixerOutput::kFXCount - 1];
FXElement* fx_[MixerOutput::kFXCount];
FXUnit2<Tube>* tube_;
FXUnit2<Chorus>* chorus_;
FXUnit2<Flanger>* flanger_;
FXUnit2<Orbitone>* orbitone_;
FXUnit2<Phaser>* phaser_;
FXUnit2<Delay>* delay_;
FXUnit2<AudioEffectPlateReverb>* plate_reverb_;
FXUnit2<ShimmerReverb>* shimmer_reverb_;
FXUnit2<Dry>* dry_;
};
#include "mixing_console.cpp"

@ -0,0 +1,59 @@
#pragma once
#include "extra_features.h"
enum StereoChannels
{
Left = 0,
Right,
kNumChannels
};
enum class MixerOutput
{
OutputStart = 0,
FX_Tube = 0,
FX_Chorus,
FX_Flanger,
FX_Orbitone,
FX_Phaser,
FX_Delay,
FX_PlateReverb,
FX_ShimmerReverb,
MainOutput,
kFXCount
};
template<typename T>
std::string_view getMixerOutputString(T enum_val)
{
static constexpr std::array<std::string_view, static_cast<size_t>(T::kFXCount)> names
{
"Tube",
"Chorus",
"Flanger",
"Orbitone",
"Phaser",
"Delay",
"PlateReverb",
"ShimmerReverb",
"MainOutput"
};
static_assert(names.size() == static_cast<size_t>(T::kFXCount),"Enum class and string array size mismatch");
return names[static_cast<size_t>(enum_val)];
}
MixerOutput getMixerOutputFromString(std::string str)
{
if(str == "Tube") return MixerOutput::FX_Tube;
if(str == "Chorus") return MixerOutput::FX_Chorus;
if(str == "Flanger") return MixerOutput::FX_Flanger;
if(str == "Orbitone") return MixerOutput::FX_Orbitone;
if(str == "Phaser") return MixerOutput::FX_Phaser;
if(str == "Delay") return MixerOutput::FX_Delay;
if(str == "PlateReverb") return MixerOutput::FX_PlateReverb;
if(str == "ShimmerReverb") return MixerOutput::FX_ShimmerReverb;
if(str == "MainOutput") return MixerOutput::MainOutput;
throw std::invalid_argument("Invalid MixerOutput string");
}

@ -24,6 +24,7 @@
#include "mididevice.h" #include "mididevice.h"
#include <cstring> #include <cstring>
#include <algorithm> #include <algorithm>
#include <sstream>
CPerformanceConfig::CPerformanceConfig (FATFS *pFileSystem) CPerformanceConfig::CPerformanceConfig (FATFS *pFileSystem)
: m_Properties ("performance.ini", pFileSystem) : m_Properties ("performance.ini", pFileSystem)
@ -159,42 +160,58 @@ bool CPerformanceConfig::Load (void)
m_nReverbDiffusion = m_Properties.GetNumber ("ReverbDiffusion", 65); m_nReverbDiffusion = m_Properties.GetNumber ("ReverbDiffusion", 65);
m_nReverbLevel = m_Properties.GetNumber ("ReverbLevel", 99); m_nReverbLevel = m_Properties.GetNumber ("ReverbLevel", 99);
#ifdef ARM_ALLOW_MULTI_CORE #ifdef MIXING_CONSOLE_ENABLE
this->m_bFXChainEnable = this->m_Properties.GetNumber("FXChainEnable", 1); this->m_bFXTubeEnable = this->m_Properties.GetNumber("FXTubeEnable", 1);
this->m_nFXChainWet = this->m_Properties.GetNumber("FXChainWet", 99); this->m_nFXTubeOverdrive = this->m_Properties.GetNumber("FXTubeOverdrive", 10);
this->m_bFXChainTubeEnable = this->m_Properties.GetNumber("FXChainTubeEnable", 1); this->m_bFXChorusEnable = this->m_Properties.GetNumber("FXChorusEnable", 1);
this->m_nFXChainTubeWet = this->m_Properties.GetNumber("FXChainTubeWet", 50); this->m_nFXChorusRate = this->m_Properties.GetNumber("FXChorusRate", 50);
this->m_nFXChainTubeOverdrive = this->m_Properties.GetNumber("FXChainTubeOverdrive", 10); this->m_nFXChorusDepth = this->m_Properties.GetNumber("FXChorusDepth", 50);
this->m_bFXChainChorusEnable = this->m_Properties.GetNumber("FXChainChorusEnable", 1); this->m_bFXFlangerEnable = this->m_Properties.GetNumber("FXFlangerEnable", 1);
this->m_nFXChainChorusWet = this->m_Properties.GetNumber("FXChainChorusWet", 50); this->m_nFXFlangerRate = this->m_Properties.GetNumber("FXFlangerRate", 15);
this->m_nFXChainChorusRate = this->m_Properties.GetNumber("FXChainChorusRate", 50); this->m_nFXFlangerDepth = this->m_Properties.GetNumber("FXFlangerDepth", 10);
this->m_nFXChainChorusDepth = this->m_Properties.GetNumber("FXChainChorusDepth", 50); this->m_nFXFlangerFeedback = this->m_Properties.GetNumber("FXFlangerFeedback", 20);
this->m_bFXChainFlangerEnable = this->m_Properties.GetNumber("FXChainFlangerEnable", 1); this->m_bFXOrbitoneEnable = this->m_Properties.GetNumber("FXOrbitoneEnable", 1);
this->m_nFXChainFlangerWet = this->m_Properties.GetNumber("FXChainFlangerWet", 50); this->m_nFXOrbitoneRate = this->m_Properties.GetNumber("FXOrbitoneRate", 40);
this->m_nFXChainFlangerRate = this->m_Properties.GetNumber("FXChainFlangerRate", 15); this->m_nFXOrbitoneDepth = this->m_Properties.GetNumber("FXOrbitoneDepth", 50);
this->m_nFXChainFlangerDepth = this->m_Properties.GetNumber("FXChainFlangerDepth", 10); this->m_bFXPhaserEnable = this->m_Properties.GetNumber("FXPhaserEnable", 1);
this->m_nFXChainFlangerFeedback = this->m_Properties.GetNumber("FXChainFlangerFeedback", 20); this->m_nFXPhaserRate = this->m_Properties.GetNumber("FXPhaserRate", 5);
this->m_bFXChainOrbitoneEnable = this->m_Properties.GetNumber("FXChainOrbitoneEnable", 1); this->m_nFXPhaserDepth = this->m_Properties.GetNumber("FXPhaserDepth", 99);
this->m_nFXChainOrbitoneWet = this->m_Properties.GetNumber("FXChainOrbitoneWet", 80); this->m_nFXPhaserFeedback = this->m_Properties.GetNumber("FXPhaserFeedback", 50);
this->m_nFXChainOrbitoneRate = this->m_Properties.GetNumber("FXChainOrbitoneRate", 40); this->m_nFXPhaserNbStages = this->m_Properties.GetNumber("FXPhaserNbStages", 12);
this->m_nFXChainOrbitoneDepth = this->m_Properties.GetNumber("FXChainOrbitoneDepth", 50); this->m_bFXDelayEnable = this->m_Properties.GetNumber("FXDelayEnable", 1);
this->m_bFXChainPhaserEnable = this->m_Properties.GetNumber("FXChainPhaserEnable", 1); this->m_nFXDelayLeftDelayTime = this->m_Properties.GetNumber("FXDelayLeftDelayTime", 15);
this->m_nFXChainPhaserWet = this->m_Properties.GetNumber("FXChainPhaserWet", 50); this->m_nFXDelayRightDelayTime = this->m_Properties.GetNumber("FXDelayRightDelayTime", 22);
this->m_nFXChainPhaserRate = this->m_Properties.GetNumber("FXChainPhaserRate", 5); this->m_nFXDelayFeedback = this->m_Properties.GetNumber("FXDelayFeedback", 35);
this->m_nFXChainPhaserDepth = this->m_Properties.GetNumber("FXChainPhaserDepth", 99); this->m_bFXShimmerReverbEnable = this->m_Properties.GetNumber("FXShimmerReverbEnable", 1);
this->m_nFXChainPhaserFeedback = this->m_Properties.GetNumber("FXChainPhaserFeedback", 50); this->m_nFXShimmerReverbInputGain = this->m_Properties.GetNumber("FXShimmerReverbInputGain", 30);
this->m_nFXChainPhaserNbStages = this->m_Properties.GetNumber("FXChainPhaserNbStages", 12); this->m_nFXShimmerReverbTime = this->m_Properties.GetNumber("FXShimmerReverbTime", 30);
this->m_bFXChainDelayEnable = this->m_Properties.GetNumber("FXChainDelayEnable", 1); this->m_nFXShimmerReverbDiffusion = this->m_Properties.GetNumber("FXShimmerReverbDiffusion", 30);
this->m_nFXChainDelayWet = this->m_Properties.GetNumber("FXChainDelayWet", 50); this->m_nFXShimmerReverbLP = this->m_Properties.GetNumber("FXShimmerReverbLP", 99);
this->m_nFXChainDelayLeftDelayTime = this->m_Properties.GetNumber("FXChainDelayLeftDelayTime", 15);
this->m_nFXChainDelayRightDelayTime = this->m_Properties.GetNumber("FXChainDelayRightDelayTime", 22); for(unsigned in = 0; in < CConfig::ToneGenerators; ++in)
this->m_nFXChainDelayFeedback = this->m_Properties.GetNumber("FXChainDelayFeedback", 35); {
this->m_bFXChainShimmerReverbEnable = this->m_Properties.GetNumber("FXChainShimmerReverbEnable", 1); for(unsigned fx = 0; fx < MixerOutput::kFXCount; ++fx)
this->m_nFXChainShimmerReverbWet = this->m_Properties.GetNumber("FXChainShimmerReverbWet", 70); {
this->m_nFXChainShimmerReverbInputGain = this->m_Properties.GetNumber("FXChainShimmerReverbInputGain", 30); std::ostringstream oss("FXSendLevel_");
this->m_nFXChainShimmerReverbTime = this->m_Properties.GetNumber("FXChainShimmerReverbTime", 30); oss << in << "_x_" << fx;
this->m_nFXChainShimmerReverbDiffusion = this->m_Properties.GetNumber("FXChainShimmerReverbDiffusion", 30); unsigned defaultLevel = 0;
this->m_nFXChainShimmerReverbLP = this->m_Properties.GetNumber("FXChainShimmerReverbLP", 99); if(fx == MixerOutput::MainOutput) defaultLevel = 50;
else if(fx == MixerOutput::FX_PlateReverb) defaultLevel = 50;
this->m_nFXSendLevel[in][fx] = this->m_Properties.GetNumber(oss.str().c_str(), defaultLevel);
}
}
for(unsigned ret = 0; ret < (MixerOutput::kFXCount - 1); ++ret)
{
for(unsigned fx = 0; fx < MixerOutput::kFXCount; ++fx)
{
std::ostringstream oss("FXReturnLevel_");
oss << ret << "_x_" << fx;
unsigned defaultLevel = 0;
if(ret == MixerOutput::FX_PlateReverb && fx == MixerOutput::MainOutput) defaultLevel = 50;
this->m_nFXReturnLevel[ret][fx] = this->m_Properties.GetNumber(oss.str().c_str(), defaultLevel);
}
}
#endif #endif
return bResult; return bResult;
@ -315,42 +332,53 @@ bool CPerformanceConfig::Save (void)
m_Properties.SetNumber ("ReverbDiffusion", m_nReverbDiffusion); m_Properties.SetNumber ("ReverbDiffusion", m_nReverbDiffusion);
m_Properties.SetNumber ("ReverbLevel", m_nReverbLevel); m_Properties.SetNumber ("ReverbLevel", m_nReverbLevel);
#ifdef ARM_ALLOW_MULTI_CORE #ifdef MIXING_CONSOLE_ENABLE
this->m_Properties.SetNumber("FXChainEnable", m_bFXChainEnable ? 1 : 0); this->m_Properties.SetNumber("FXTubeEnable", m_bFXTubeEnable ? 1 : 0);
this->m_Properties.SetNumber("FXChainWet", m_nFXChainWet); this->m_Properties.SetNumber("FXTubeOverdrive", m_nFXTubeOverdrive);
this->m_Properties.SetNumber("FXChainTubeEnable", m_bFXChainTubeEnable ? 1 : 0); this->m_Properties.SetNumber("FXChorusEnable", m_bFXChorusEnable ? 1 : 0);
this->m_Properties.SetNumber("FXChainTubeWet", m_nFXChainTubeWet); this->m_Properties.SetNumber("FXChorusRate", m_nFXChorusRate);
this->m_Properties.SetNumber("FXChainTubeOverdrive", m_nFXChainTubeOverdrive); this->m_Properties.SetNumber("FXChorusDepth", m_nFXChorusDepth);
this->m_Properties.SetNumber("FXChainChorusEnable", m_bFXChainChorusEnable ? 1 : 0); this->m_Properties.SetNumber("FXFlangerEnable", m_bFXFlangerEnable ? 1 : 0);
this->m_Properties.SetNumber("FXChainChorusWet", m_nFXChainChorusWet); this->m_Properties.SetNumber("FXFlangerRate", m_nFXFlangerRate);
this->m_Properties.SetNumber("FXChainChorusRate", m_nFXChainChorusRate); this->m_Properties.SetNumber("FXFlangerDepth", m_nFXFlangerDepth);
this->m_Properties.SetNumber("FXChainChorusDepth", m_nFXChainChorusDepth); this->m_Properties.SetNumber("FXFlangerFeedback", m_nFXFlangerFeedback);
this->m_Properties.SetNumber("FXChainFlangerEnable", m_bFXChainFlangerEnable ? 1 : 0); this->m_Properties.SetNumber("FXOrbitoneEnable", m_bFXOrbitoneEnable ? 1 : 0);
this->m_Properties.SetNumber("FXChainFlangerWet", m_nFXChainFlangerWet); this->m_Properties.SetNumber("FXOrbitoneRate", m_nFXOrbitoneRate);
this->m_Properties.SetNumber("FXChainFlangerRate", m_nFXChainFlangerRate); this->m_Properties.SetNumber("FXOrbitoneDepth", m_nFXOrbitoneDepth);
this->m_Properties.SetNumber("FXChainFlangerDepth", m_nFXChainFlangerDepth); this->m_Properties.SetNumber("FXPhaserEnable", m_bFXPhaserEnable ? 1 : 0);
this->m_Properties.SetNumber("FXChainFlangerFeedback", m_nFXChainFlangerFeedback); this->m_Properties.SetNumber("FXPhaserRate", m_nFXPhaserRate);
this->m_Properties.SetNumber("FXChainOrbitoneEnable", m_bFXChainOrbitoneEnable ? 1 : 0); this->m_Properties.SetNumber("FXPhaserDepth", m_nFXPhaserDepth);
this->m_Properties.SetNumber("FXChainOrbitoneWet", m_nFXChainOrbitoneWet); this->m_Properties.SetNumber("FXPhaserFeedback", m_nFXPhaserFeedback);
this->m_Properties.SetNumber("FXChainOrbitoneRate", m_nFXChainOrbitoneRate); this->m_Properties.SetNumber("FXPhaserNbStages", m_nFXPhaserNbStages);
this->m_Properties.SetNumber("FXChainOrbitoneDepth", m_nFXChainOrbitoneDepth); this->m_Properties.SetNumber("FXDelayEnable", m_bFXDelayEnable ? 1 : 0);
this->m_Properties.SetNumber("FXChainPhaserEnable", m_bFXChainPhaserEnable ? 1 : 0); this->m_Properties.SetNumber("FXDelayLeftDelayTime", m_nFXDelayLeftDelayTime);
this->m_Properties.SetNumber("FXChainPhaserWet", m_nFXChainPhaserWet); this->m_Properties.SetNumber("FXDelayRightDelayTime", m_nFXDelayRightDelayTime);
this->m_Properties.SetNumber("FXChainPhaserRate", m_nFXChainPhaserRate); this->m_Properties.SetNumber("FXDelayFeedback", m_nFXDelayFeedback);
this->m_Properties.SetNumber("FXChainPhaserDepth", m_nFXChainPhaserDepth); this->m_Properties.SetNumber("FXShimmerReverbEnable", m_bFXShimmerReverbEnable ? 1 : 0);
this->m_Properties.SetNumber("FXChainPhaserFeedback", m_nFXChainPhaserFeedback); this->m_Properties.SetNumber("FXShimmerReverbInputGain", m_nFXShimmerReverbInputGain);
this->m_Properties.SetNumber("FXChainPhaserNbStages", m_nFXChainPhaserNbStages); this->m_Properties.SetNumber("FXShimmerReverbTime", m_nFXShimmerReverbTime);
this->m_Properties.SetNumber("FXChainDelayEnable", m_bFXChainDelayEnable ? 1 : 0); this->m_Properties.SetNumber("FXShimmerReverbDiffusion", m_nFXShimmerReverbDiffusion);
this->m_Properties.SetNumber("FXChainDelayWet", m_nFXChainDelayWet); this->m_Properties.SetNumber("FXShimmerReverbLP", m_nFXShimmerReverbLP);
this->m_Properties.SetNumber("FXChainDelayLeftDelayTime", m_nFXChainDelayLeftDelayTime);
this->m_Properties.SetNumber("FXChainDelayRightDelayTime", m_nFXChainDelayRightDelayTime); for(unsigned in = 0; in < CConfig::ToneGenerators; ++in)
this->m_Properties.SetNumber("FXChainDelayFeedback", m_nFXChainDelayFeedback); {
this->m_Properties.SetNumber("FXChainShimmerReverbEnable", m_bFXChainShimmerReverbEnable ? 1 : 0); for(unsigned fx = 0; fx < MixerOutput::kFXCount; ++fx)
this->m_Properties.SetNumber("FXChainShimmerReverbWet", m_nFXChainShimmerReverbWet); {
this->m_Properties.SetNumber("FXChainShimmerReverbInputGain", m_nFXChainShimmerReverbInputGain); std::ostringstream oss("FXSendLevel_");
this->m_Properties.SetNumber("FXChainShimmerReverbTime", m_nFXChainShimmerReverbTime); oss << in << "_x_" << fx;
this->m_Properties.SetNumber("FXChainShimmerReverbDiffusion", m_nFXChainShimmerReverbDiffusion); this->m_Properties.SetNumber(oss.str().c_str(), this->m_nFXSendLevel[in][fx]);
this->m_Properties.SetNumber("FXChainShimmerReverbLP", m_nFXChainShimmerReverbLP); }
}
for(unsigned ret = 0; ret < (MixerOutput::kFXCount - 1); ++ret)
{
for(unsigned fx = 0; fx < MixerOutput::kFXCount; ++fx)
{
std::ostringstream oss("FXReturnLevel_");
oss << ret << "_x_" << fx;
this->m_Properties.SetNumber(oss.str().c_str(), this->m_nFXReturnLevel[ret][fx]);
}
}
#endif #endif
return m_Properties.Save (); return m_Properties.Save ();
@ -1000,355 +1028,294 @@ bool CPerformanceConfig::DeletePerformance(unsigned nID)
return bOK; return bOK;
} }
#ifdef ARM_ALLOW_MULTI_CORE #ifdef MIXING_CONSOLE_ENABLE
bool CPerformanceConfig::GetFXChainEnable(void) const
{
return this->m_bFXChainEnable;
}
unsigned CPerformanceConfig::GetFXChainWet(void) const
{
return this->m_nFXChainWet;
}
bool CPerformanceConfig::GetFXChainTubeEnable(void) const
{
return this->m_bFXChainTubeEnable;
}
unsigned CPerformanceConfig::GetFXChainTubeWet(void) const
{
return this->m_nFXChainTubeWet;
}
unsigned CPerformanceConfig::GetFXChainTubeOverdrive(void) const
{
return this->m_nFXChainTubeOverdrive;
}
bool CPerformanceConfig::GetFXChainChorusEnable(void) const
{
return this->m_bFXChainChorusEnable;
}
unsigned CPerformanceConfig::GetFXChainChorusWet(void) const
{
return this->m_nFXChainChorusWet;
}
unsigned CPerformanceConfig::GetFXChainChorusRate(void) const
{
return this->m_nFXChainChorusRate;
}
unsigned CPerformanceConfig::GetFXChainChorusDepth(void) const
{
return this->m_nFXChainChorusDepth;
}
bool CPerformanceConfig::GetFXChainFlangerEnable(void) const
{
return this->m_bFXChainFlangerEnable;
}
unsigned CPerformanceConfig::GetFXChainFlangerWet(void) const
{
return this->m_nFXChainFlangerWet;
}
unsigned CPerformanceConfig::GetFXChainFlangerRate(void) const
{
return this->m_nFXChainFlangerRate;
}
unsigned CPerformanceConfig::GetFXChainFlangerDepth(void) const
{
return this->m_nFXChainFlangerDepth;
}
unsigned CPerformanceConfig::GetFXChainFlangerFeedback(void) const
{
return this->m_nFXChainFlangerFeedback;
}
bool CPerformanceConfig::GetFXChainOrbitoneEnable(void) const bool CPerformanceConfig::GetFXTubeEnable(void) const
{ {
return this->m_bFXChainOrbitoneEnable; return this->m_bFXTubeEnable;
} }
unsigned CPerformanceConfig::GetFXChainOrbitoneWet(void) const unsigned CPerformanceConfig::GetFXTubeOverdrive(void) const
{ {
return this->m_nFXChainOrbitoneWet; return this->m_nFXTubeOverdrive;
} }
unsigned CPerformanceConfig::GetFXChainOrbitoneRate(void) const bool CPerformanceConfig::GetFXChorusEnable(void) const
{ {
return this->m_nFXChainOrbitoneRate; return this->m_bFXChorusEnable;
} }
unsigned CPerformanceConfig::GetFXChainOrbitoneDepth(void) const unsigned CPerformanceConfig::GetFXChorusRate(void) const
{ {
return this->m_nFXChainOrbitoneDepth; return this->m_nFXChorusRate;
} }
bool CPerformanceConfig::GetFXChainPhaserEnable(void) const unsigned CPerformanceConfig::GetFXChorusDepth(void) const
{ {
return this->m_bFXChainPhaserEnable; return this->m_nFXChorusDepth;
} }
unsigned CPerformanceConfig::GetFXChainPhaserWet(void) const bool CPerformanceConfig::GetFXFlangerEnable(void) const
{ {
return this->m_nFXChainPhaserWet; return this->m_bFXFlangerEnable;
} }
unsigned CPerformanceConfig::GetFXChainPhaserRate(void) const unsigned CPerformanceConfig::GetFXFlangerRate(void) const
{ {
return this->m_nFXChainPhaserRate; return this->m_nFXFlangerRate;
} }
unsigned CPerformanceConfig::GetFXChainPhaserDepth(void) const unsigned CPerformanceConfig::GetFXFlangerDepth(void) const
{ {
return this->m_nFXChainPhaserDepth; return this->m_nFXFlangerDepth;
} }
unsigned CPerformanceConfig::GetFXChainPhaserFeedback(void) const unsigned CPerformanceConfig::GetFXFlangerFeedback(void) const
{ {
return this->m_nFXChainPhaserFeedback; return this->m_nFXFlangerFeedback;
} }
unsigned CPerformanceConfig::GetFXChainPhaserNbStages(void) const bool CPerformanceConfig::GetFXOrbitoneEnable(void) const
{ {
return this->m_nFXChainPhaserNbStages; return this->m_bFXOrbitoneEnable;
} }
bool CPerformanceConfig::GetFXChainDelayEnable(void) const unsigned CPerformanceConfig::GetFXOrbitoneRate(void) const
{ {
return this->m_bFXChainDelayEnable; return this->m_nFXOrbitoneRate;
} }
unsigned CPerformanceConfig::GetFXChainDelayWet(void) const unsigned CPerformanceConfig::GetFXOrbitoneDepth(void) const
{ {
return this->m_nFXChainDelayWet; return this->m_nFXOrbitoneDepth;
} }
unsigned CPerformanceConfig::GetFXChainDelayLeftDelayTime(void) const bool CPerformanceConfig::GetFXPhaserEnable(void) const
{ {
return this->m_nFXChainDelayLeftDelayTime; return this->m_bFXPhaserEnable;
} }
unsigned CPerformanceConfig::GetFXChainDelayRightDelayTime(void) const unsigned CPerformanceConfig::GetFXPhaserRate(void) const
{ {
return this->m_nFXChainDelayRightDelayTime; return this->m_nFXPhaserRate;
} }
unsigned CPerformanceConfig::GetFXChainDelayFeedback(void) const unsigned CPerformanceConfig::GetFXPhaserDepth(void) const
{ {
return this->m_nFXChainDelayFeedback; return this->m_nFXPhaserDepth;
} }
bool CPerformanceConfig::GetFXChainShimmerReverbEnable(void) const unsigned CPerformanceConfig::GetFXPhaserFeedback(void) const
{ {
return this->m_bFXChainShimmerReverbEnable; return this->m_nFXPhaserFeedback;
} }
unsigned CPerformanceConfig::GetFXChainShimmerReverbWet(void) const unsigned CPerformanceConfig::GetFXPhaserNbStages(void) const
{ {
return this->m_nFXChainShimmerReverbWet; return this->m_nFXPhaserNbStages;
} }
unsigned CPerformanceConfig::GetFXChainShimmerReverbInputGain(void) const bool CPerformanceConfig::GetFXDelayEnable(void) const
{ {
return this->m_nFXChainShimmerReverbInputGain; return this->m_bFXDelayEnable;
} }
unsigned CPerformanceConfig::GetFXChainShimmerReverbTime(void) const unsigned CPerformanceConfig::GetFXDelayLeftDelayTime(void) const
{ {
return this->m_nFXChainShimmerReverbTime; return this->m_nFXDelayLeftDelayTime;
} }
unsigned CPerformanceConfig::GetFXChainShimmerReverbDiffusion(void) const unsigned CPerformanceConfig::GetFXDelayRightDelayTime(void) const
{ {
return this->m_nFXChainShimmerReverbDiffusion; return this->m_nFXDelayRightDelayTime;
} }
unsigned CPerformanceConfig::GetFXChainShimmerReverbLP(void) const unsigned CPerformanceConfig::GetFXDelayFeedback(void) const
{ {
return this->m_nFXChainShimmerReverbLP; return this->m_nFXDelayFeedback;
} }
void CPerformanceConfig::SetFXChainEnable(bool bValue) bool CPerformanceConfig::GetFXShimmerReverbEnable(void) const
{ {
this->m_bFXChainEnable = bValue; return this->m_bFXShimmerReverbEnable;
} }
void CPerformanceConfig::SetFXChainWet(unsigned nValue) unsigned CPerformanceConfig::GetFXShimmerReverbInputGain(void) const
{ {
this->m_nFXChainWet = nValue; return this->m_nFXShimmerReverbInputGain;
} }
void CPerformanceConfig::SetFXChainTubeEnable(bool bValue) unsigned CPerformanceConfig::GetFXShimmerReverbTime(void) const
{ {
this->m_bFXChainTubeEnable = bValue; return this->m_nFXShimmerReverbTime;
} }
void CPerformanceConfig::SetFXChainTubeWet(unsigned nValue) unsigned CPerformanceConfig::GetFXShimmerReverbDiffusion(void) const
{ {
this->m_nFXChainTubeWet = nValue; return this->m_nFXShimmerReverbDiffusion;
} }
void CPerformanceConfig::SetFXChainTubeOverdrive(unsigned nValue) unsigned CPerformanceConfig::GetFXShimmerReverbLP(void) const
{ {
this->m_nFXChainTubeOverdrive = nValue; return this->m_nFXShimmerReverbLP;
} }
void CPerformanceConfig::SetFXChainChorusEnable(bool bValue) unsigned CPerformanceConfig::GetFXSendLevel(unsigned in, MixerOutput fx) const
{ {
this->m_bFXChainChorusEnable = bValue; assert(in < CConfig::ToneGenerators);
assert(fx < MixerOutput::kFXCount);
return this->m_nFXSendLevel[in][fx];
} }
void CPerformanceConfig::SetFXChainChorusWet(unsigned nValue) unsigned CPerformanceConfig::GetFXReturnLevel(MixerOutput ret, MixerOutput fx) const
{ {
this->m_nFXChainChorusWet = nValue; assert(ret < (MixerOutput::kFXCount - 1));
assert(fx < MixerOutput::kFXCount);
return (ret == fx) ? 0 : this->m_nFXReturnLevel[ret][fx];
} }
void CPerformanceConfig::SetFXChainChorusRate(unsigned nValue) void CPerformanceConfig::SetFXTubeEnable(bool bValue)
{ {
this->m_nFXChainChorusRate = nValue; this->m_bFXTubeEnable = bValue;
} }
void CPerformanceConfig::SetFXChainChorusDepth(unsigned nValue) void CPerformanceConfig::SetFXTubeOverdrive(unsigned nValue)
{ {
this->m_nFXChainChorusDepth = nValue; this->m_nFXTubeOverdrive = nValue;
} }
void CPerformanceConfig::SetFXChainFlangerEnable(bool bValue) void CPerformanceConfig::SetFXChorusEnable(bool bValue)
{ {
this->m_bFXChainFlangerEnable = bValue; this->m_bFXChorusEnable = bValue;
} }
void CPerformanceConfig::SetFXChainFlangerWet(unsigned nValue) void CPerformanceConfig::SetFXChorusRate(unsigned nValue)
{ {
this->m_nFXChainFlangerWet = nValue; this->m_nFXChorusRate = nValue;
} }
void CPerformanceConfig::SetFXChainFlangerRate(unsigned nValue) void CPerformanceConfig::SetFXChorusDepth(unsigned nValue)
{ {
this->m_nFXChainFlangerRate = nValue; this->m_nFXChorusDepth = nValue;
} }
void CPerformanceConfig::SetFXChainFlangerDepth(unsigned nValue) void CPerformanceConfig::SetFXFlangerEnable(bool bValue)
{ {
this->m_nFXChainFlangerDepth = nValue; this->m_bFXFlangerEnable = bValue;
} }
void CPerformanceConfig::SetFXChainFlangerFeedback(unsigned nValue) void CPerformanceConfig::SetFXFlangerRate(unsigned nValue)
{ {
this->m_nFXChainFlangerFeedback = nValue; this->m_nFXFlangerRate = nValue;
} }
void CPerformanceConfig::SetFXChainOrbitoneEnable(bool bValue) void CPerformanceConfig::SetFXFlangerDepth(unsigned nValue)
{ {
this->m_bFXChainOrbitoneEnable = bValue; this->m_nFXFlangerDepth = nValue;
} }
void CPerformanceConfig::SetFXChainOrbitoneWet(unsigned nValue) void CPerformanceConfig::SetFXFlangerFeedback(unsigned nValue)
{ {
this->m_nFXChainOrbitoneWet = nValue; this->m_nFXFlangerFeedback = nValue;
} }
void CPerformanceConfig::SetFXChainOrbitoneRate(unsigned nValue) void CPerformanceConfig::SetFXOrbitoneEnable(bool bValue)
{ {
this->m_nFXChainOrbitoneRate = nValue; this->m_bFXOrbitoneEnable = bValue;
} }
void CPerformanceConfig::SetFXChainOrbitoneDepth(unsigned nValue) void CPerformanceConfig::SetFXOrbitoneRate(unsigned nValue)
{ {
this->m_nFXChainOrbitoneDepth = nValue; this->m_nFXOrbitoneRate = nValue;
} }
void CPerformanceConfig::SetFXChainPhaserEnable(bool bValue) void CPerformanceConfig::SetFXOrbitoneDepth(unsigned nValue)
{ {
this->m_bFXChainPhaserEnable = bValue; this->m_nFXOrbitoneDepth = nValue;
} }
void CPerformanceConfig::SetFXChainPhaserWet(unsigned nValue) void CPerformanceConfig::SetFXPhaserEnable(bool bValue)
{ {
this->m_nFXChainPhaserWet = nValue; this->m_bFXPhaserEnable = bValue;
} }
void CPerformanceConfig::SetFXChainPhaserRate(unsigned nValue) void CPerformanceConfig::SetFXPhaserRate(unsigned nValue)
{ {
this->m_nFXChainPhaserRate = nValue; this->m_nFXPhaserRate = nValue;
} }
void CPerformanceConfig::SetFXChainPhaserDepth(unsigned nValue) void CPerformanceConfig::SetFXPhaserDepth(unsigned nValue)
{ {
this->m_nFXChainPhaserDepth = nValue; this->m_nFXPhaserDepth = nValue;
} }
void CPerformanceConfig::SetFXChainPhaserFeedback(unsigned nValue) void CPerformanceConfig::SetFXPhaserFeedback(unsigned nValue)
{ {
this->m_nFXChainPhaserFeedback = nValue; this->m_nFXPhaserFeedback = nValue;
} }
void CPerformanceConfig::SetFXChainPhaserNbStages(unsigned nValue) void CPerformanceConfig::SetFXPhaserNbStages(unsigned nValue)
{ {
this->m_nFXChainPhaserNbStages = nValue; this->m_nFXPhaserNbStages = nValue;
} }
void CPerformanceConfig::SetFXChainDelayEnable(unsigned bValue) void CPerformanceConfig::SetFXDelayEnable(unsigned bValue)
{ {
this->m_bFXChainDelayEnable = bValue; this->m_bFXDelayEnable = bValue;
} }
void CPerformanceConfig::SetFXChainDelayWet(unsigned nValue) void CPerformanceConfig::SetFXDelayLeftDelayTime(unsigned nValue)
{ {
this->m_nFXChainDelayWet = nValue; this->m_nFXDelayLeftDelayTime = nValue;
} }
void CPerformanceConfig::SetFXChainDelayLeftDelayTime(unsigned nValue) void CPerformanceConfig::SetFXDelayRightDelayTime(unsigned nValue)
{ {
this->m_nFXChainDelayLeftDelayTime = nValue; this->m_nFXDelayRightDelayTime = nValue;
} }
void CPerformanceConfig::SetFXChainDelayRightDelayTime(unsigned nValue) void CPerformanceConfig::SetFXDelayFeedback(unsigned nValue)
{ {
this->m_nFXChainDelayRightDelayTime = nValue; this->m_nFXDelayFeedback = nValue;
} }
void CPerformanceConfig::SetFXChainDelayFeedback(unsigned nValue) void CPerformanceConfig::SetFXShimmerReverbEnable(unsigned bValue)
{ {
this->m_nFXChainDelayFeedback = nValue; this->m_bFXShimmerReverbEnable = bValue;
} }
void CPerformanceConfig::SetFXChainShimmerReverbEnable(unsigned bValue) void CPerformanceConfig::SetFXShimmerReverbInputGain(unsigned nValue)
{ {
this->m_bFXChainShimmerReverbEnable = bValue; this->m_nFXShimmerReverbInputGain = nValue;
} }
void CPerformanceConfig::SetFXChainShimmerReverbWet(unsigned nValue) void CPerformanceConfig::SetFXShimmerReverbTime(unsigned nValue)
{ {
this->m_nFXChainShimmerReverbWet = nValue; this->m_nFXShimmerReverbTime = nValue;
} }
void CPerformanceConfig::SetFXChainShimmerReverbInputGain(unsigned nValue) void CPerformanceConfig::SetFXShimmerReverbDiffusion(unsigned nValue)
{ {
this->m_nFXChainShimmerReverbInputGain = nValue; this->m_nFXShimmerReverbDiffusion = nValue;
} }
void CPerformanceConfig::SetFXChainShimmerReverbTime(unsigned nValue) void CPerformanceConfig::SetFXShimmerReverbLP(unsigned nValue)
{ {
this->m_nFXChainShimmerReverbTime = nValue; this->m_nFXShimmerReverbLP = nValue;
} }
void CPerformanceConfig::SetFXChainShimmerReverbDiffusion(unsigned nValue) void CPerformanceConfig::SetFXSendLevel(unsigned in, MixerOutput fx, unsigned nValue)
{ {
this->m_nFXChainShimmerReverbDiffusion = nValue; assert(in < CConfig::ToneGenerators);
assert(fx < MixerOutput::kFXCount);
this->m_nFXSendLevel[in][fx] = nValue;
} }
void CPerformanceConfig::SetFXChainShimmerReverbLP(unsigned nValue) void CPerformanceConfig::SetFXReturnLevel(MixerOutput ret, MixerOutput fx, unsigned nValue)
{ {
this->m_nFXChainShimmerReverbLP = nValue; assert(ret < (MixerOutput::kFXCount - 1));
assert(fx < MixerOutput::kFXCount);
this->m_nFXReturnLevel[ret][fx] = (ret == fx) ? 0 : nValue;
} }
#endif #endif

@ -24,6 +24,7 @@
#define _performanceconfig_h #define _performanceconfig_h
#include "config.h" #include "config.h"
#include "mixing_console_constants.h"
#include <fatfs/ff.h> #include <fatfs/ff.h>
#include <Properties/propertiesfatfsfile.h> #include <Properties/propertiesfatfsfile.h>
#define NUM_VOICE_PARAM 156 #define NUM_VOICE_PARAM 156
@ -117,78 +118,64 @@ public:
void SetReverbDiffusion (unsigned nValue); void SetReverbDiffusion (unsigned nValue);
void SetReverbLevel (unsigned nValue); void SetReverbLevel (unsigned nValue);
#ifdef ARM_ALLOW_MULTI_CORE #ifdef MIXING_CONSOLE_ENABLE
bool GetFXChainEnable(void) const; bool GetFXTubeEnable(void) const;
unsigned GetFXChainWet(void) const; unsigned GetFXTubeOverdrive(void) const;
bool GetFXChainTubeEnable(void) const; bool GetFXChorusEnable(void) const;
unsigned GetFXChainTubeWet(void) const; unsigned GetFXChorusRate(void) const;
unsigned GetFXChainTubeOverdrive(void) const; unsigned GetFXChorusDepth(void) const;
bool GetFXChainChorusEnable(void) const; bool GetFXFlangerEnable(void) const;
unsigned GetFXChainChorusWet(void) const; unsigned GetFXFlangerRate(void) const;
unsigned GetFXChainChorusRate(void) const; unsigned GetFXFlangerDepth(void) const;
unsigned GetFXChainChorusDepth(void) const; unsigned GetFXFlangerFeedback(void) const;
bool GetFXChainFlangerEnable(void) const; bool GetFXOrbitoneEnable(void) const;
unsigned GetFXChainFlangerWet(void) const; unsigned GetFXOrbitoneRate(void) const;
unsigned GetFXChainFlangerRate(void) const; unsigned GetFXOrbitoneDepth(void) const;
unsigned GetFXChainFlangerDepth(void) const; bool GetFXPhaserEnable(void) const;
unsigned GetFXChainFlangerFeedback(void) const; unsigned GetFXPhaserRate(void) const;
bool GetFXChainOrbitoneEnable(void) const; unsigned GetFXPhaserDepth(void) const;
unsigned GetFXChainOrbitoneWet(void) const; unsigned GetFXPhaserFeedback(void) const;
unsigned GetFXChainOrbitoneRate(void) const; unsigned GetFXPhaserNbStages(void) const;
unsigned GetFXChainOrbitoneDepth(void) const; bool GetFXDelayEnable(void) const;
bool GetFXChainPhaserEnable(void) const; unsigned GetFXDelayLeftDelayTime(void) const;
unsigned GetFXChainPhaserWet(void) const; unsigned GetFXDelayRightDelayTime(void) const;
unsigned GetFXChainPhaserRate(void) const; unsigned GetFXDelayFeedback(void) const;
unsigned GetFXChainPhaserDepth(void) const; bool GetFXShimmerReverbEnable(void) const;
unsigned GetFXChainPhaserFeedback(void) const; unsigned GetFXShimmerReverbInputGain(void) const;
unsigned GetFXChainPhaserNbStages(void) const; unsigned GetFXShimmerReverbTime(void) const;
bool GetFXChainDelayEnable(void) const; unsigned GetFXShimmerReverbDiffusion(void) const;
unsigned GetFXChainDelayWet(void) const; unsigned GetFXShimmerReverbLP(void) const;
unsigned GetFXChainDelayLeftDelayTime(void) const; unsigned GetFXSendLevel(unsigned in, MixerOutput fx) const;
unsigned GetFXChainDelayRightDelayTime(void) const; unsigned GetFXReturnLevel(MixerOutput ret, MixerOutput fx) const;
unsigned GetFXChainDelayFeedback(void) const;
bool GetFXChainShimmerReverbEnable(void) const;
unsigned GetFXChainShimmerReverbWet(void) const;
unsigned GetFXChainShimmerReverbInputGain(void) const;
unsigned GetFXChainShimmerReverbTime(void) const;
unsigned GetFXChainShimmerReverbDiffusion(void) const;
unsigned GetFXChainShimmerReverbLP(void) const;
void SetFXChainEnable(bool bValue); void SetFXTubeEnable(bool bValue);
void SetFXChainWet(unsigned nValue); void SetFXTubeOverdrive(unsigned nValue);
void SetFXChainTubeEnable(bool bValue); void SetFXChorusEnable(bool bValue);
void SetFXChainTubeWet(unsigned nValue); void SetFXChorusRate(unsigned nValue);
void SetFXChainTubeOverdrive(unsigned nValue); void SetFXChorusDepth(unsigned nValue);
void SetFXChainChorusEnable(bool bValue); void SetFXFlangerEnable(bool bValue);
void SetFXChainChorusWet(unsigned nValue); void SetFXFlangerRate(unsigned nValue);
void SetFXChainChorusRate(unsigned nValue); void SetFXFlangerDepth(unsigned nValue);
void SetFXChainChorusDepth(unsigned nValue); void SetFXFlangerFeedback(unsigned nValue);
void SetFXChainFlangerEnable(bool bValue); void SetFXOrbitoneEnable(bool bValue);
void SetFXChainFlangerWet(unsigned nValue); void SetFXOrbitoneRate(unsigned nValue);
void SetFXChainFlangerRate(unsigned nValue); void SetFXOrbitoneDepth(unsigned nValue);
void SetFXChainFlangerDepth(unsigned nValue); void SetFXPhaserEnable(bool bValue);
void SetFXChainFlangerFeedback(unsigned nValue); void SetFXPhaserRate(unsigned nValue);
void SetFXChainOrbitoneEnable(bool bValue); void SetFXPhaserDepth(unsigned nValue);
void SetFXChainOrbitoneWet(unsigned nValue); void SetFXPhaserFeedback(unsigned nValue);
void SetFXChainOrbitoneRate(unsigned nValue); void SetFXPhaserNbStages(unsigned nValue);
void SetFXChainOrbitoneDepth(unsigned nValue); void SetFXDelayEnable(unsigned nValue);
void SetFXChainPhaserEnable(bool bValue); void SetFXDelayLeftDelayTime(unsigned nValue);
void SetFXChainPhaserWet(unsigned nValue); void SetFXDelayRightDelayTime(unsigned nValue);
void SetFXChainPhaserRate(unsigned nValue); void SetFXDelayFeedback(unsigned nValue);
void SetFXChainPhaserDepth(unsigned nValue); void SetFXShimmerReverbEnable(unsigned nValue);
void SetFXChainPhaserFeedback(unsigned nValue); void SetFXShimmerReverbInputGain(unsigned nValue);
void SetFXChainPhaserNbStages(unsigned nValue); void SetFXShimmerReverbTime(unsigned nValue);
void SetFXChainDelayEnable(unsigned nValue); void SetFXShimmerReverbDiffusion(unsigned nValue);
void SetFXChainDelayWet(unsigned nValue); void SetFXShimmerReverbLP(unsigned nValue);
void SetFXChainDelayLeftDelayTime(unsigned nValue); void SetFXSendLevel(unsigned in, MixerOutput fx, unsigned nValue);
void SetFXChainDelayRightDelayTime(unsigned nValue); void SetFXReturnLevel(MixerOutput ret, MixerOutput fx, unsigned nValue);
void SetFXChainDelayFeedback(unsigned nValue);
void SetFXChainShimmerReverbEnable(unsigned nValue);
void SetFXChainShimmerReverbWet(unsigned nValue);
void SetFXChainShimmerReverbInputGain(unsigned nValue);
void SetFXChainShimmerReverbTime(unsigned nValue);
void SetFXChainShimmerReverbDiffusion(unsigned nValue);
void SetFXChainShimmerReverbLP(unsigned nValue);
#endif #endif
bool VoiceDataFilled(unsigned nTG); bool VoiceDataFilled(unsigned nTG);
@ -258,42 +245,38 @@ private:
unsigned m_nReverbDiffusion; unsigned m_nReverbDiffusion;
unsigned m_nReverbLevel; unsigned m_nReverbLevel;
#ifdef ARM_ALLOW_MULTI_CORE #ifdef MIXING_CONSOLE_ENABLE
bool m_bFXChainEnable; bool m_bFXTubeEnable;
unsigned m_nFXChainWet; unsigned m_nFXTubeWet;
bool m_bFXChainTubeEnable; unsigned m_nFXTubeOverdrive;
unsigned m_nFXChainTubeWet; bool m_bFXChorusEnable;
unsigned m_nFXChainTubeOverdrive; unsigned m_nFXChorusRate;
bool m_bFXChainChorusEnable; unsigned m_nFXChorusDepth;
unsigned m_nFXChainChorusWet; bool m_bFXFlangerEnable;
unsigned m_nFXChainChorusRate; unsigned m_nFXFlangerRate;
unsigned m_nFXChainChorusDepth; unsigned m_nFXFlangerDepth;
bool m_bFXChainFlangerEnable; unsigned m_nFXFlangerFeedback;
unsigned m_nFXChainFlangerWet; bool m_bFXOrbitoneEnable;
unsigned m_nFXChainFlangerRate; unsigned m_nFXOrbitoneRate;
unsigned m_nFXChainFlangerDepth; unsigned m_nFXOrbitoneDepth;
unsigned m_nFXChainFlangerFeedback; bool m_bFXPhaserEnable;
bool m_bFXChainOrbitoneEnable; unsigned m_nFXPhaserRate;
unsigned m_nFXChainOrbitoneWet; unsigned m_nFXPhaserDepth;
unsigned m_nFXChainOrbitoneRate; unsigned m_nFXPhaserFeedback;
unsigned m_nFXChainOrbitoneDepth; unsigned m_nFXPhaserNbStages;
bool m_bFXChainPhaserEnable; bool m_bFXDelayEnable;
unsigned m_nFXChainPhaserWet; unsigned m_nFXDelayLeftDelayTime;
unsigned m_nFXChainPhaserRate; unsigned m_nFXDelayRightDelayTime;
unsigned m_nFXChainPhaserDepth; unsigned m_nFXDelayFeedback;
unsigned m_nFXChainPhaserFeedback; bool m_bFXShimmerReverbEnable;
unsigned m_nFXChainPhaserNbStages; unsigned m_nFXShimmerReverbInputGain;
bool m_bFXChainDelayEnable; unsigned m_nFXShimmerReverbTime;
unsigned m_nFXChainDelayWet; unsigned m_nFXShimmerReverbDiffusion;
unsigned m_nFXChainDelayLeftDelayTime; unsigned m_nFXShimmerReverbLP;
unsigned m_nFXChainDelayRightDelayTime;
unsigned m_nFXChainDelayFeedback; unsigned m_nFXSendLevel[CConfig::ToneGenerators][MixerOutput::kFXCount];
bool m_bFXChainShimmerReverbEnable; unsigned m_nFXReturnLevel[MixerOutput::kFXCount - 1][MixerOutput::kFXCount];
unsigned m_nFXChainShimmerReverbWet;
unsigned m_nFXChainShimmerReverbInputGain;
unsigned m_nFXChainShimmerReverbTime;
unsigned m_nFXChainShimmerReverbDiffusion;
unsigned m_nFXChainShimmerReverbLP;
#endif #endif
}; };

@ -1,12 +1,16 @@
CXX := gcc CXX := gcc
# CXXFLAGS := -O2 # CXXFLAGS := -O2
CXXFLAGS := -g CXXFLAGS := -g
DEFINES := -DCPU=x86 DEFINES := -DCPU=x86 -DDEBUG=1
INCLUDES := -I../../CMSIS_5/CMSIS/DSP/Include/ -I../../CMSIS_5/CMSIS/Core/Include/ INCLUDES := -I../../CMSIS_5/CMSIS/DSP/Include/ \
-I../../CMSIS_5/CMSIS/Core/Include/ \
-I../../circle-stdlib/libs/circle/include \
-I../../circle-stdlib/libs/circle/addon \
-I../../Synth_Dexed/src
GCC := $(CXX) $(INCLUDES) $(CXXFLAGS) GCC := $(CXX) $(INCLUDES) $(CXXFLAGS)
LD := gcc LD := gcc
LIBS := -lm -lstdc++ LIBS := -lm -lstdc++ -lgtest -lpthread
OBJS := \ OBJS := \
fx.o \ fx.o \
@ -19,15 +23,40 @@ OBJS := \
fx_flanger.o \ fx_flanger.o \
fx_delay.o \ fx_delay.o \
fx_shimmer_reverb.o \ fx_shimmer_reverb.o \
fx_dry.o \
fx_rack.o \ fx_rack.o \
effect_platervbstereo.o \ effect_platervbstereo.o \
arm_functions.o \
wavein.o \ wavein.o \
waveout.o \ waveout.o \
fxrack_test.o fxrack_test.o
test: fxrack_test OBJS2:= \
fx.o \
fx_components.o \
fx_svf.o \
fx_tube.o \
fx_chorus.o \
fx_phaser.o \
fx_orbitone.o \
fx_flanger.o \
fx_delay.o \
fx_shimmer_reverb.o \
fx_dry.o \
fx_rack.o \
effect_platervbstereo.o \
arm_functions.o \
wavein.o \
waveout.o \
all_tests.o
test: all_tests fxrack_test
./all_tests
./fxrack_test ./fxrack_test
../%.cpp: ../%.h
touch $@
%.o: ../%.cpp %.o: ../%.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
@ -37,6 +66,9 @@ wavein.o: wavein.cpp
waveout.o: waveout.cpp waveout.o: waveout.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
arm_functions.o: arm_functions.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
# # waveplay.o: waveplay.cpp # # waveplay.o: waveplay.cpp
# # $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ # # $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
@ -85,12 +117,21 @@ waveout.o: waveout.cpp
# effect_platervbstereo.o: ../effect_platervbstereo.cpp # effect_platervbstereo.o: ../effect_platervbstereo.cpp
# $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ # $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fxrack_test.cpp: ../mixing_console.h ../mixing_console.cpp
touch $@
fxrack_test.o: fxrack_test.cpp fxrack_test.o: fxrack_test.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
all_tests.o: all_tests.cpp
$(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@
fxrack_test: $(OBJS) fxrack_test: $(OBJS)
$(LD) $(OBJS) -o fxrack_test $(LIBS) $(LD) $(OBJS) -o fxrack_test $(LIBS)
all_tests: $(OBJS2)
$(LD) $(OBJS2) -o all_tests $(LIBS)
clean: clean:
rm -f *.o fxrack_test rm -f *.o fxrack_test

@ -0,0 +1,101 @@
#pragma once
#include <gtest/gtest.h>
#include "../mixing_console_constants.h"
TEST(MixerOutputTest, GetMixerOutputStringForTube)
{
auto v = getMixerOutputString(MixerOutput::FX_Tube);
EXPECT_EQ(v, "Tube");
}
TEST(MixerOutputTest, GetMixerOutputStringForChorus)
{
auto v = getMixerOutputString(MixerOutput::FX_Chorus);
EXPECT_EQ(v, "Chorus");
}
TEST(MixerOutputTest, GetMixerOutputStringForFlanger)
{
auto v = getMixerOutputString(MixerOutput::FX_Flanger);
EXPECT_EQ(v, "Flanger");
}
TEST(MixerOutputTest, GetMixerOutputStringForOrbitone)
{
auto v = getMixerOutputString(MixerOutput::FX_Orbitone);
EXPECT_EQ(v, "Orbitone");
}
TEST(MixerOutputTest, GetMixerOutputStringForPhaser)
{
auto v = getMixerOutputString(MixerOutput::FX_Phaser);
EXPECT_EQ(v, "Phaser");
}
TEST(MixerOutputTest, GetMixerOutputStringForDelay)
{
auto v = getMixerOutputString(MixerOutput::FX_Delay);
EXPECT_EQ(v, "Delay");
}
TEST(MixerOutputTest, GetMixerOutputStringForPlateReverb)
{
auto v = getMixerOutputString(MixerOutput::FX_PlateReverb);
EXPECT_EQ(v, "PlateReverb");
}
TEST(MixerOutputTest, GetMixerOutputStringForShimmerReverb)
{
auto v = getMixerOutputString(MixerOutput::FX_ShimmerReverb);
EXPECT_EQ(v, "ShimmerReverb");
}
TEST(MixerOutputTest, GetMixerOutputFromStringTube)
{
MixerOutput v = getMixerOutputFromString("Tube");
EXPECT_EQ(v, MixerOutput::FX_Tube);
}
TEST(MixerOutputTest, GetMixerOutputFromStringChorus)
{
MixerOutput v = getMixerOutputFromString("Chorus");
EXPECT_EQ(v, MixerOutput::FX_Chorus);
}
TEST(MixerOutputTest, GetMixerOutputFromStringFlanger)
{
MixerOutput v = getMixerOutputFromString("Flanger");
EXPECT_EQ(v, MixerOutput::FX_Flanger);
}
TEST(MixerOutputTest, GetMixerOutputFromStringOrbitone)
{
MixerOutput v = getMixerOutputFromString("Orbitone");
EXPECT_EQ(v, MixerOutput::FX_Orbitone);
}
TEST(MixerOutputTest, GetMixerOutputFromStringPhaser)
{
MixerOutput v = getMixerOutputFromString("Phaser");
EXPECT_EQ(v, MixerOutput::FX_Phaser);
}
TEST(MixerOutputTest, GetMixerOutputFromStringDelay)
{
MixerOutput v = getMixerOutputFromString("Delay");
EXPECT_EQ(v, MixerOutput::FX_Delay);
}
TEST(MixerOutputTest, GetMixerOutputFromStringPlateReverb)
{
MixerOutput v = getMixerOutputFromString("PlateReverb");
EXPECT_EQ(v, MixerOutput::FX_PlateReverb);
}
TEST(MixerOutputTest, GetMixerOutputFromStringShimmerReverb)
{
MixerOutput v = getMixerOutputFromString("ShimmerReverb");
EXPECT_EQ(v, MixerOutput::FX_ShimmerReverb);
}

@ -0,0 +1,12 @@
#pragma once
#include <gtest/gtest.h>
#include "../uimenu.h"
#include "../minidexed.h"
TEST(UIMenuTest, CountGlobalParams)
{
size_t nb = CMiniDexed::ParameterUnknown;
EXPECT_EQ(nb, 156);
}

@ -0,0 +1,8 @@
#include "MixerOutputTest.hpp"
#include "UIMenuTest.hpp"
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -0,0 +1,46 @@
#include <arm_math.h>
float32_t arm_sin_f32(float32_t phase)
{
return sin(phase);
}
float32_t arm_cos_f32(float32_t phase)
{
return cos(phase);
}
void arm_scale_f32(const float32_t *pSrc, float32_t scale, float32_t *pDst, uint32_t blockSize)
{
for(unsigned i = 0; i < blockSize; ++i)
{
pDst[i] = scale * pSrc[i];
}
}
void arm_copy_f32(const float32_t *pSrc, float32_t *pDst, uint32_t blockSize)
{
memcpy(pDst, pSrc, blockSize * sizeof(float32_t));
}
void arm_add_f32(const float32_t *pSrcA, const float32_t *pSrcB, float32_t *pDst, uint32_t blockSize)
{
for(size_t i = 0; i < blockSize; ++i) pDst[i] = pSrcA[i] + pSrcB[i];
}
void arm_fill_f32(float32_t value, float32_t *pDst, uint32_t blockSize)
{
for(size_t i = 0; i < blockSize; ++i) pDst[i] = value;
}
float32_t arm_weighted_sum_f32(const float32_t *in, const float32_t *weights, uint32_t blockSize)
{
float32_t m = 0.0f;
for(size_t i = 0; i < blockSize; ++i) m += in[i] * weights[i];
return m;
}
void arm_clip_f32(const float32_t *pSrc, float32_t *pDst, float32_t low, float32_t high, uint32_t numSamples)
{
for(size_t i = 0; i < numSamples; ++i) pDst[i] = (pSrc[i] < low) ? low : (pSrc[i] > high) ? high : pSrc[i];
}

@ -0,0 +1,4 @@
[ViewState]
Mode=
Vid=
FolderType=Generic

@ -1,6 +1,6 @@
#include "../fx_rack.h" #include "../fx_rack.h"
#include "../effect_platervbstereo.h" #include "../effect_platervbstereo.h"
#include "../mixing_console.h"
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
@ -23,19 +23,6 @@ random_device rd;
mt19937 gen(rd()); mt19937 gen(rd());
uniform_real_distribution<float32_t> dist(-1.0f, 1.0f); uniform_real_distribution<float32_t> dist(-1.0f, 1.0f);
float32_t arm_sin_f32(float32_t phase)
{
return sin(phase);
}
void arm_scale_f32(const float32_t *pSrc, float32_t scale, float32_t *pDst, uint32_t blockSize)
{
for(unsigned i = 0; i < blockSize; ++i)
{
pDst[i] = scale * pSrc[i];
}
}
void testPlateReverb(unsigned& step) void testPlateReverb(unsigned& step)
{ {
const unsigned nbRepeats = 4; const unsigned nbRepeats = 4;
@ -227,7 +214,7 @@ enum FXSitch
Flanger = 1 << 4, Flanger = 1 << 4,
Delay = 1 << 5, Delay = 1 << 5,
Shimmer = 1 << 6, Shimmer = 1 << 6,
kNbFX = 7 _kFXCount = 7
}; };
int scenarii[] = int scenarii[] =
@ -413,9 +400,11 @@ void setupRack(unsigned& step, FXRack* rack)
rack->getFlanger()->setFeedback(0.5f); rack->getFlanger()->setFeedback(0.5f);
rack->getDelay()->setWetLevel(0.6f); rack->getDelay()->setWetLevel(0.6f);
rack->getDelay()->setLeftDelayTime(0.075f); rack->getDelay()->setLeftDelayTime(0.15f);
rack->getDelay()->setLeftDelayTime(0.05f); rack->getDelay()->setLeftDelayTime(0.2f);
rack->getDelay()->setFeedbak(0.5f); rack->getDelay()->setFeedback(0.35f);
rack->getDelay()->setFlutterRate(0.15f);
rack->getDelay()->setFlutterAmount(0.75f);
rack->getShimmerReverb()->setWetLevel(0.5f); rack->getShimmerReverb()->setWetLevel(0.5f);
rack->getShimmerReverb()->setInputGain(0.35f); rack->getShimmerReverb()->setInputGain(0.35f);
@ -435,7 +424,7 @@ void activateRackFXUnitScenario(unsigned& step, FXRack* rack, int scenario)
rack->getShimmerReverb()->setEnable(Active(scenario, FXSitch::Shimmer)); rack->getShimmerReverb()->setEnable(Active(scenario, FXSitch::Shimmer));
} }
void testReset(unsigned& step) void testFXRackReset(unsigned& step)
{ {
FXRack *rack = new FXRack(44100.0f); FXRack *rack = new FXRack(44100.0f);
rack->setEnable(true); rack->setEnable(true);
@ -463,9 +452,9 @@ void testReset(unsigned& step)
delete rack; delete rack;
} }
void testProcessing(unsigned& step) void testFXRackProcessing(unsigned& step)
{ {
const unsigned nbRepeats = 1; const unsigned nbRepeats = 2;
unsigned size; unsigned size;
float32_t** samples = readWaveFile("test.wav", size); float32_t** samples = readWaveFile("test.wav", size);
float32_t* sampleOutL = new float32_t[size * nbRepeats]; float32_t* sampleOutL = new float32_t[size * nbRepeats];
@ -481,6 +470,7 @@ void testProcessing(unsigned& step)
unsigned i = 0; unsigned i = 0;
while(true) while(true)
{ {
rack->reset();
int fxSwitch = scenarii[i]; int fxSwitch = scenarii[i];
if(fxSwitch == -1) if(fxSwitch == -1)
{ {
@ -497,9 +487,9 @@ void testProcessing(unsigned& step)
rack->process(samples[0], samples[1], sampleOutL + i * size, sampleOutR + i * size, size); rack->process(samples[0], samples[1], sampleOutL + i * size, sampleOutR + i * size, size);
} }
// stringstream ss; stringstream ss;
// ss << "result " << name << ".wav"; ss << "waves/result " << name << ".wav";
// saveWaveFile(ss.str(), sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(FS), 16); saveWaveFile(ss.str(), sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(FS), 16);
cout << "done" << endl; cout << "done" << endl;
@ -515,16 +505,177 @@ void testProcessing(unsigned& step)
delete[] sampleOutR; delete[] sampleOutR;
} }
typedef MixingConsole<8> Mixer;
void setupMixingConsoleFX(unsigned& step, Mixer* mixer)
{
cout << "Step #" << (++step) << ": Set Mixing Console FX parameters" << endl;
// mixer->setWetLevel(1.0f);
// mixer->getTube()->setWetLevel(0.25f);
mixer->getTube()->setOverdrive(0.25f);
// mixer->getChorus()->setWetLevel(0.5f);
mixer->getChorus()->setRate(0.4f);
mixer->getChorus()->setDepth(0.5f);
// mixer->getPhaser()->setWetLevel(1.0f);
mixer->getPhaser()->setRate(0.1f);
mixer->getPhaser()->setDepth(1.0f);
mixer->getPhaser()->setFeedback(0.5f);
mixer->getPhaser()->setNbStages(12);
// mixer->getOrbitone()->setWetLevel(0.8f);
mixer->getOrbitone()->setRate(0.4f);
mixer->getOrbitone()->setDepth(0.5f);
// mixer->getFlanger()->setWetLevel(0.5f);
mixer->getFlanger()->setRate(0.03f);
mixer->getFlanger()->setDepth(0.75f);
mixer->getFlanger()->setFeedback(0.5f);
// mixer->getDelay()->setWetLevel(0.6f);
mixer->getDelay()->setLeftDelayTime(0.5f);
mixer->getDelay()->setLeftDelayTime(0.7f);
mixer->getDelay()->setFeedback(0.7f);
mixer->getDelay()->setFlutterRate(0.7f);
mixer->getDelay()->setFlutterAmount(0.7f);
mixer->getPlateReverb()->set_bypass(false);
mixer->getPlateReverb()->size(0.7f);
mixer->getPlateReverb()->hidamp(0.5f);
mixer->getPlateReverb()->lodamp(0.5f);
mixer->getPlateReverb()->lowpass(0.3f);
mixer->getPlateReverb()->diffusion(0.65f);
mixer->getPlateReverb()->level(1.0f);
// mixer->getShimmerReverb()->setWetLevel(0.5f);
mixer->getShimmerReverb()->setInputGain(0.35f);
mixer->getShimmerReverb()->setTime(0.89f);
mixer->getShimmerReverb()->setDiffusion(0.75f);
mixer->getShimmerReverb()->setLP(0.8f);
}
void testUnitMixingConsole(unsigned& step)
{
constexpr float32_t epsilon = 1e-7;
constexpr size_t length = 2;
Mixer* mixer = new Mixer(FS, length);
cout << "Step #" << (++step) << ": MixingConsole unitary dry" << endl;
mixer->setSendLevel(0, MixerOutput::MainOutput, 1.0f);
mixer->setPan(0, 0.5f);
float32_t in[length] = {0.1, 0.2};
float32_t out[StereoChannels::kNumChannels][length];
mixer->setInputSampleBuffer(0, in);
mixer->process(
out[StereoChannels::Left ],
out[StereoChannels::Right]
);
assert((out[StereoChannels::Left ][0] == out[StereoChannels::Right][0]) && (out[StereoChannels::Left ][1] == out[StereoChannels::Right][1]));
assert(out[StereoChannels::Left ][0] - (sqrt(2.0f) / 20.0f) < epsilon);
assert(out[StereoChannels::Left ][1] - (sqrt(2.0f) / 10.0f) < epsilon);
cout << "Step #" << (++step) << ": MixingConsole unitary shimmer" << endl;
mixer->setSendLevel(0, MixerOutput::MainOutput, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_ShimmerReverb, MixerOutput::MainOutput, 1.0f);
mixer->setPan(0, 0.5f);
mixer->setInputSampleBuffer(0, in);
mixer->process(
out[StereoChannels::Left ],
out[StereoChannels::Right]
);
float32_t out2[StereoChannels::kNumChannels][length];
mixer->reset();
mixer->setInputSampleBuffer(0, in);
mixer->process(
out2[StereoChannels::Left ],
out2[StereoChannels::Right]
);
assert(out[StereoChannels::Left ][0] == out2[StereoChannels::Left ][0]);
assert(out[StereoChannels::Left ][1] == out2[StereoChannels::Left ][1]);
delete mixer;
}
void testMixingConsole(unsigned& step)
{
const unsigned nbRepeats = 4;
unsigned size;
float32_t** samples = readWaveFile("test.wav", size);
float32_t* sampleOutL = new float32_t[size * nbRepeats];
float32_t* sampleOutR = new float32_t[size * nbRepeats];
memset(sampleOutL, 0, size * nbRepeats * sizeof(float32_t));
memset(sampleOutR, 0, size * nbRepeats * sizeof(float32_t));
cout << "Step #" << (++step) << ": Testing MixingConsole" << endl;
Mixer* mixer = new Mixer(FS, size);
setupMixingConsoleFX(step, mixer);
mixer->getTube()->setOverdrive(0.15f);
mixer->setSendLevel(0, MixerOutput::FX_Tube, 1.0f);
mixer->setSendLevel(0, MixerOutput::FX_Phaser, 1.0f);
// mixer->setReturnLevel(MixerOutput::FX_Tube, MixerOutput::MainOutput, 1.0f);
// mixer->setSendLevel(0, MixerOutput::FX_Chorus, 1.0f);
// mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Tube, MixerOutput::FX_Chorus, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Chorus, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Phaser, MixerOutput::FX_Delay, 1.0f);
mixer->setSendLevel(0, MixerOutput::MainOutput, 0.25f);
mixer->setReturnLevel(MixerOutput::FX_Tube, MixerOutput::MainOutput, 0.1f);
mixer->setReturnLevel(MixerOutput::FX_Chorus, MixerOutput::MainOutput, 0.15f);
mixer->setReturnLevel(MixerOutput::FX_ShimmerReverb, MixerOutput::MainOutput, 0.3f);
mixer->setReturnLevel(MixerOutput::FX_Delay, MixerOutput::MainOutput, 0.3f);
for(unsigned j = 0; j < nbRepeats; ++j)
{
// for(unsigned i = 0; i < size; ++i)
// {
// mixer->setInputSample(0, samples[0][i], samples[1][i]);
// mixer->processSample(sampleOutL[i + j * size], sampleOutR[i + j * size]);
// }
mixer->setInputSampleBuffer(0, samples[0], samples[1]);
mixer->process(sampleOutL + j * size, sampleOutR + j * size);
}
saveWaveFile("result-new-console.wav", sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(FS), 16);
delete mixer;
cout << "Step #" << (++step) << ": Testing MixingConsole [DONE]" << endl;
delete[] samples[0];
delete[] samples[1];
delete[] samples;
delete[] sampleOutL;
delete[] sampleOutR;
}
int main() int main()
{ {
unsigned step = 0; unsigned step = 0;
testLFO(step); // testLFO(step);
testFlutter(step);
testSVF(step); // testFlutter(step);
testPlateReverb(step);
testReset(step); // testSVF(step);
testProcessing(step);
// testPlateReverb(step);
// testFXRackReset(step);
// testFXRackProcessing(step);
// testUnitMixingConsole(step);
testMixingConsole(step);
return 0; return 0;
} }

@ -34,57 +34,70 @@ using namespace std;
const CUIMenu::TMenuItem CUIMenu::s_MenuRoot[] = const CUIMenu::TMenuItem CUIMenu::s_MenuRoot[] =
{ {
{"MiniDexed", MenuHandler, s_MainMenu}, {"MiniDexed", MenuHandler, CUIMenu::s_MainMenu},
{0} {0}
}; };
// inserting menu items before "TG1" affect TGShortcutHandler() // inserting menu items before "TG1" affect TGShortcutHandler()
const CUIMenu::TMenuItem CUIMenu::s_MainMenu[] = const CUIMenu::TMenuItem CUIMenu::s_MainMenu[] =
{ {
{"TG1", MenuHandler, s_TGMenu, 0}, {"TG1", MenuHandler, CUIMenu::s_TGMenu, 0},
#ifdef ARM_ALLOW_MULTI_CORE #ifdef ARM_ALLOW_MULTI_CORE
{"TG2", MenuHandler, s_TGMenu, 1}, {"TG2", MenuHandler, CUIMenu::s_TGMenu, 1},
{"TG3", MenuHandler, s_TGMenu, 2}, {"TG3", MenuHandler, CUIMenu::s_TGMenu, 2},
{"TG4", MenuHandler, s_TGMenu, 3}, {"TG4", MenuHandler, CUIMenu::s_TGMenu, 3},
{"TG5", MenuHandler, s_TGMenu, 4}, {"TG5", MenuHandler, CUIMenu::s_TGMenu, 4},
{"TG6", MenuHandler, s_TGMenu, 5}, {"TG6", MenuHandler, CUIMenu::s_TGMenu, 5},
{"TG7", MenuHandler, s_TGMenu, 6}, {"TG7", MenuHandler, CUIMenu::s_TGMenu, 6},
{"TG8", MenuHandler, s_TGMenu, 7}, {"TG8", MenuHandler, CUIMenu::s_TGMenu, 7},
#endif #endif
{"Effects", MenuHandler, s_EffectsMenu}, {"Effects", MenuHandler, CUIMenu::s_EffectsMenu},
{"Performance", MenuHandler, s_PerformanceMenu}, {"Performance", MenuHandler, CUIMenu::s_PerformanceMenu},
{0} {0}
}; };
const CUIMenu::TMenuItem CUIMenu::s_TGMenu[] = const CUIMenu::TMenuItem CUIMenu::s_TGMenu[] =
{ {
{"Voice", EditProgramNumber}, {"Voice", EditProgramNumber},
{"Bank", EditVoiceBankNumber}, {"Bank", EditVoiceBankNumber},
{"Volume", EditTGParameter, 0, CMiniDexed::TGParameterVolume}, {"Volume", EditTGParameter, 0, CMiniDexed::TGParameterVolume},
#ifdef ARM_ALLOW_MULTI_CORE #ifdef ARM_ALLOW_MULTI_CORE
{"Pan", EditTGParameter, 0, CMiniDexed::TGParameterPan}, {"Pan", EditTGParameter, 0, CMiniDexed::TGParameterPan},
#endif #endif
#ifdef MIXING_CONSOLE_ENABLE
{"Tube-Send", EditTGParameter, 0, CMiniDexed::TGParameterMixingSendFXTube},
{"Chorus-Send", EditTGParameter, 0, CMiniDexed::TGParameterMixingSendFXChorus},
{"FlangR-Send", EditTGParameter, 0, CMiniDexed::TGParameterMixingSendFXFlanger},
{"Orb-Send", EditTGParameter, 0, CMiniDexed::TGParameterMixingSendFXOrbittone},
{"Phaser-Send", EditTGParameter, 0, CMiniDexed::TGParameterMixingSendFXPhaser},
{"Delay-Send", EditTGParameter, 0, CMiniDexed::TGParameterMixingSendFXDelay},
{"Reverb-Send", EditTGParameter, 0, CMiniDexed::TGParameterMixingSendFXPlateReverb},
{"ShimmR-Send", EditTGParameter, 0, CMiniDexed::TGParameterMixingSendFXShimmerReverb},
{"Dry-Level", EditTGParameter, 0, CMiniDexed::TGParameterMixingSendFXMainOutput},
#else
{"Reverb-Send", EditTGParameter, 0, CMiniDexed::TGParameterReverbSend}, {"Reverb-Send", EditTGParameter, 0, CMiniDexed::TGParameterReverbSend},
{"Detune", EditTGParameter, 0, CMiniDexed::TGParameterMasterTune}, #endif
{"Cutoff", EditTGParameter, 0, CMiniDexed::TGParameterCutoff}, {"Detune", EditTGParameter, 0, CMiniDexed::TGParameterMasterTune},
{"Resonance", EditTGParameter, 0, CMiniDexed::TGParameterResonance}, {"Cutoff", EditTGParameter, 0, CMiniDexed::TGParameterCutoff},
{"Pitch Bend", MenuHandler, s_EditPitchBendMenu}, {"Resonance", EditTGParameter, 0, CMiniDexed::TGParameterResonance},
{"Portamento", MenuHandler, s_EditPortamentoMenu}, {"Pitch Bend", MenuHandler, CUIMenu::s_EditPitchBendMenu},
{"Poly/Mono", EditTGParameter, 0, CMiniDexed::TGParameterMonoMode}, {"Portamento", MenuHandler, CUIMenu::s_EditPortamentoMenu},
{"Modulation", MenuHandler, s_ModulationMenu}, {"Poly/Mono", EditTGParameter, 0, CMiniDexed::TGParameterMonoMode},
{"Channel", EditTGParameter, 0, CMiniDexed::TGParameterMIDIChannel}, {"Modulation", MenuHandler, CUIMenu::s_ModulationMenu},
{"Edit Voice", MenuHandler, s_EditVoiceMenu}, {"Channel", EditTGParameter, 0, CMiniDexed::TGParameterMIDIChannel},
{"Edit Voice", MenuHandler, CUIMenu::s_EditVoiceMenu},
{0} {0}
}; };
const CUIMenu::TMenuItem CUIMenu::s_EffectsMenu[] = const CUIMenu::TMenuItem CUIMenu::s_EffectsMenu[] =
{ {
{"Compress", EditGlobalParameter, 0, CMiniDexed::ParameterCompressorEnable}, {"Compress", EditGlobalParameter, 0, CMiniDexed::ParameterCompressorEnable},
#ifdef MIXING_CONSOLE_ENABLE
{"FX", MenuHandler, CUIMenu::s_FXMenu},
#else
#ifdef ARM_ALLOW_MULTI_CORE #ifdef ARM_ALLOW_MULTI_CORE
{"Reverb", MenuHandler, s_ReverbMenu}, {"Reverb", MenuHandler, CUIMenu::s_ReverbMenu},
#endif #endif
#ifdef FXRACK_ENABLE
{"FXChain", MenuHandler, s_FXChainMenu},
#endif #endif
{0} {0}
}; };
@ -106,10 +119,10 @@ const CUIMenu::TMenuItem CUIMenu::s_EditPortamentoMenu[] =
const CUIMenu::TMenuItem CUIMenu::s_ModulationMenu[] = const CUIMenu::TMenuItem CUIMenu::s_ModulationMenu[] =
{ {
{"Mod. Wheel", MenuHandler, s_ModulationMenuParameters, CMiniDexed::TGParameterMWRange}, {"Mod. Wheel", MenuHandler, CUIMenu::s_ModulationMenuParameters, CMiniDexed::TGParameterMWRange},
{"Foot Control", MenuHandler, s_ModulationMenuParameters, CMiniDexed::TGParameterFCRange}, {"Foot Control", MenuHandler, CUIMenu::s_ModulationMenuParameters, CMiniDexed::TGParameterFCRange},
{"Breath Control", MenuHandler, s_ModulationMenuParameters, CMiniDexed::TGParameterBCRange}, {"Breath Control", MenuHandler, CUIMenu::s_ModulationMenuParameters, CMiniDexed::TGParameterBCRange},
{"Aftertouch", MenuHandler, s_ModulationMenuParameters, CMiniDexed::TGParameterATRange}, {"Aftertouch", MenuHandler, CUIMenu::s_ModulationMenuParameters, CMiniDexed::TGParameterATRange},
{0} {0}
}; };
@ -138,89 +151,177 @@ const CUIMenu::TMenuItem CUIMenu::s_ReverbMenu[] =
#endif #endif
#ifdef FXRACK_ENABLE #ifdef MIXING_CONSOLE_ENABLE
const CUIMenu::TMenuItem CUIMenu::s_FXChainMenu[] = const CUIMenu::TMenuItem CUIMenu::s_FXMenu[] =
{ {
// FXChain {"Tube", MenuHandler, CUIMenu::s_FXTube},
{"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainEnable}, {"Chorus", MenuHandler, CUIMenu::s_FXChorus},
{"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainWet}, {"FlangR", MenuHandler, CUIMenu::s_FXFlanger},
{"Orb", MenuHandler, CUIMenu::s_FXOrbitone},
{"PhasR", MenuHandler, CUIMenu::s_FXPhaser},
{"Delay", MenuHandler, CUIMenu::s_FXDelay},
{"Reverb", MenuHandler, CUIMenu::s_ReverbMenu},
{"Shimmer", MenuHandler, CUIMenu::s_FXShimmerReverb},
{0}
};
{"Tube", MenuHandler, s_FXChainTube}, const CUIMenu::TMenuItem CUIMenu::s_FXTube[] =
{"Chorus", MenuHandler, s_FXChainChorus}, {
{"FlangR", MenuHandler, s_FXChainFlanger}, {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Orb", MenuHandler, s_FXChainOrbitone}, {"Overdrv", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeOverdrive},
{"PhasR", MenuHandler, s_FXChainPhaser},
{"Delay", MenuHandler, s_FXChainDelay},
{"Shimmer", MenuHandler, s_FXChainShimmerReverb},
{0} {0}
}; };
const CUIMenu::TMenuItem CUIMenu::s_FXChainTube[] = const CUIMenu::TMenuItem CUIMenu::s_FXChorus[] =
{ {
{"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainTubeEnable}, {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChorusEnable},
{"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainTubeWet}, {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXChorusRate},
{"Overdrv", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainTubeOverdrive}, {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXChorusDepth},
{0} {0}
}; };
const CUIMenu::TMenuItem CUIMenu::s_FXChainChorus[] = const CUIMenu::TMenuItem CUIMenu::s_FXFlanger[] =
{ {
{"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainChorusEnable}, {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXFlangerEnable},
{"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainChorusWet}, {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXFlangerRate},
{"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainChorusRate}, {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXFlangerDepth},
{"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainChorusDepth}, {"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXFlangerFeedback},
{0} {0}
}; };
const CUIMenu::TMenuItem CUIMenu::s_FXChainFlanger[] = const CUIMenu::TMenuItem CUIMenu::s_FXOrbitone[] =
{ {
{"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerEnable}, {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXOrbitoneEnable},
{"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerWet}, {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXOrbitoneRate},
{"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerRate}, {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXOrbitoneDepth},
{"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerDepth},
{"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerFeedback},
{0} {0}
}; };
const CUIMenu::TMenuItem CUIMenu::s_FXChainOrbitone[] = const CUIMenu::TMenuItem CUIMenu::s_FXPhaser[] =
{ {
{"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainOrbitoneEnable}, {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXPhaserEnable},
{"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainOrbitoneWet}, {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXPhaserRate},
{"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainOrbitoneRate}, {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXPhaserDepth},
{"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainOrbitoneDepth}, {"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXPhaserFeedback},
{"Stages", EditGlobalParameter, 0, CMiniDexed::ParameterFXPhaserNbStages},
{0} {0}
}; };
const CUIMenu::TMenuItem CUIMenu::s_FXChainPhaser[] = const CUIMenu::TMenuItem CUIMenu::s_FXDelay[] =
{ {
{"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainPhaserEnable}, {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXDelayEnable},
{"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainPhaserWet}, {"L Delay", EditGlobalParameter, 0, CMiniDexed::ParameterFXDelayLeftDelayTime},
{"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainPhaserRate}, {"R Delay", EditGlobalParameter, 0, CMiniDexed::ParameterFXDelayRightDelayTime},
{"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainPhaserDepth}, {"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXDelayFeedback},
{"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainPhaserFeedback}, {"Flt Rte", EditGlobalParameter, 0, CMiniDexed::ParameterFXDelayFlutterRate},
{"Stages", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainPhaserNbStages}, {"Flt Amt", EditGlobalParameter, 0, CMiniDexed::ParameterFXDelayFlutterAmount},
{0} {0}
}; };
const CUIMenu::TMenuItem CUIMenu::s_FXChainDelay[] = const CUIMenu::TMenuItem CUIMenu::s_FXShimmerReverb[] =
{ {
{"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainDelayEnable}, {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXShimmerReverbEnable},
{"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainDelayWet}, {"Gain", EditGlobalParameter, 0, CMiniDexed::ParameterFXShimmerReverbInputGain},
{"L Delay", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainDelayLeftDelayTime}, {"Time", EditGlobalParameter, 0, CMiniDexed::ParameterFXShimmerReverbTime},
{"R Delay", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainDelayRightDelayTime}, {"Diffus", EditGlobalParameter, 0, CMiniDexed::ParameterFXShimmerReverbDiffusion},
{"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainDelayFeedback}, {"LowPass", EditGlobalParameter, 0, CMiniDexed::ParameterFXShimmerReverbLP},
{0} {0}
}; };
const CUIMenu::TMenuItem CUIMenu::s_FXChainShimmerReverb[] = const CUIMenu::TMenuItem CUIMenu::s_FXTubeReturn[] =
{ {
{"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbEnable}, {"ChR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbWet}, {"FlR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Gain", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbInputGain}, {"Orb Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Time", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbTime}, {"PhR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Diffus", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbDiffusion}, {"Del Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"LowPass", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbLP}, {"Rev Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ShR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{0}
};
const CUIMenu::TMenuItem CUIMenu::s_FXChorusReturn[] =
{
{"Tub Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"FlR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Orb Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"PhR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Del Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Rev Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ShR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{0}
};
const CUIMenu::TMenuItem CUIMenu::s_FXFlangerReturn[] =
{
{"Tub Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ChR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Orb Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"PhR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Del Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Rev Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ShR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{0}
};
const CUIMenu::TMenuItem CUIMenu::s_FXOrbitoneReturn[] =
{
{"Tub Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ChR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"FlR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"PhR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Del Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Rev Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ShR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{0}
};
const CUIMenu::TMenuItem CUIMenu::s_FXPhaserReturn[] =
{
{"Tub Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ChR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"FlR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Orb Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Del Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Rev Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ShR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{0}
};
const CUIMenu::TMenuItem CUIMenu::s_FXDelayReturn[] =
{
{"Tub Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ChR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"FlR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Orb Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"PhR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Rev Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ShR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{0}
};
const CUIMenu::TMenuItem CUIMenu::s_FXReverbReturn[] =
{
{"Tub Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ChR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"FlR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Orb Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"PhR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Del Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ShR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{0}
};
const CUIMenu::TMenuItem CUIMenu::s_FXShimmerReturn[] =
{
{"Tub Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"ChR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"FlR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Orb Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"PhR Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Del Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{"Rev Rtn", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable},
{0} {0}
}; };
@ -229,32 +330,32 @@ const CUIMenu::TMenuItem CUIMenu::s_FXChainShimmerReverb[] =
// inserting menu items before "OP1" affect OPShortcutHandler() // inserting menu items before "OP1" affect OPShortcutHandler()
const CUIMenu::TMenuItem CUIMenu::s_EditVoiceMenu[] = const CUIMenu::TMenuItem CUIMenu::s_EditVoiceMenu[] =
{ {
{"OP1", MenuHandler, s_OperatorMenu, 0}, {"OP1", MenuHandler, CUIMenu::s_OperatorMenu, 0},
{"OP2", MenuHandler, s_OperatorMenu, 1}, {"OP2", MenuHandler, CUIMenu::s_OperatorMenu, 1},
{"OP3", MenuHandler, s_OperatorMenu, 2}, {"OP3", MenuHandler, CUIMenu::s_OperatorMenu, 2},
{"OP4", MenuHandler, s_OperatorMenu, 3}, {"OP4", MenuHandler, CUIMenu::s_OperatorMenu, 3},
{"OP5", MenuHandler, s_OperatorMenu, 4}, {"OP5", MenuHandler, CUIMenu::s_OperatorMenu, 4},
{"OP6", MenuHandler, s_OperatorMenu, 5}, {"OP6", MenuHandler, CUIMenu::s_OperatorMenu, 5},
{"Algorithm", EditVoiceParameter, 0, DEXED_ALGORITHM}, {"Algorithm", EditVoiceParameter, 0, DEXED_ALGORITHM},
{"Feedback", EditVoiceParameter, 0, DEXED_FEEDBACK}, {"Feedback", EditVoiceParameter, 0, DEXED_FEEDBACK},
{"P EG Rate 1", EditVoiceParameter, 0, DEXED_PITCH_EG_R1}, {"P EG Rate 1", EditVoiceParameter, 0, DEXED_PITCH_EG_R1},
{"P EG Rate 2", EditVoiceParameter, 0, DEXED_PITCH_EG_R2}, {"P EG Rate 2", EditVoiceParameter, 0, DEXED_PITCH_EG_R2},
{"P EG Rate 3", EditVoiceParameter, 0, DEXED_PITCH_EG_R3}, {"P EG Rate 3", EditVoiceParameter, 0, DEXED_PITCH_EG_R3},
{"P EG Rate 4", EditVoiceParameter, 0, DEXED_PITCH_EG_R4}, {"P EG Rate 4", EditVoiceParameter, 0, DEXED_PITCH_EG_R4},
{"P EG Level 1",EditVoiceParameter, 0, DEXED_PITCH_EG_L1}, {"P EG Level 1",EditVoiceParameter, 0, DEXED_PITCH_EG_L1},
{"P EG Level 2",EditVoiceParameter, 0, DEXED_PITCH_EG_L2}, {"P EG Level 2",EditVoiceParameter, 0, DEXED_PITCH_EG_L2},
{"P EG Level 3",EditVoiceParameter, 0, DEXED_PITCH_EG_L3}, {"P EG Level 3",EditVoiceParameter, 0, DEXED_PITCH_EG_L3},
{"P EG Level 4",EditVoiceParameter, 0, DEXED_PITCH_EG_L4}, {"P EG Level 4",EditVoiceParameter, 0, DEXED_PITCH_EG_L4},
{"Osc Key Sync",EditVoiceParameter, 0, DEXED_OSC_KEY_SYNC}, {"Osc Key Sync",EditVoiceParameter, 0, DEXED_OSC_KEY_SYNC},
{"LFO Speed", EditVoiceParameter, 0, DEXED_LFO_SPEED}, {"LFO Speed", EditVoiceParameter, 0, DEXED_LFO_SPEED},
{"LFO Delay", EditVoiceParameter, 0, DEXED_LFO_DELAY}, {"LFO Delay", EditVoiceParameter, 0, DEXED_LFO_DELAY},
{"LFO PMD", EditVoiceParameter, 0, DEXED_LFO_PITCH_MOD_DEP}, {"LFO PMD", EditVoiceParameter, 0, DEXED_LFO_PITCH_MOD_DEP},
{"LFO AMD", EditVoiceParameter, 0, DEXED_LFO_AMP_MOD_DEP}, {"LFO AMD", EditVoiceParameter, 0, DEXED_LFO_AMP_MOD_DEP},
{"LFO Sync", EditVoiceParameter, 0, DEXED_LFO_SYNC}, {"LFO Sync", EditVoiceParameter, 0, DEXED_LFO_SYNC},
{"LFO Wave", EditVoiceParameter, 0, DEXED_LFO_WAVE}, {"LFO Wave", EditVoiceParameter, 0, DEXED_LFO_WAVE},
{"P Mod Sens.", EditVoiceParameter, 0, DEXED_LFO_PITCH_MOD_SENS}, {"P Mod Sens.", EditVoiceParameter, 0, DEXED_LFO_PITCH_MOD_SENS},
{"Transpose", EditVoiceParameter, 0, DEXED_TRANSPOSE}, {"Transpose", EditVoiceParameter, 0, DEXED_TRANSPOSE},
{"Name", InputTxt,0 , 3}, {"Name", InputTxt, 0, 3},
{0} {0}
}; };
@ -281,7 +382,7 @@ const CUIMenu::TMenuItem CUIMenu::s_OperatorMenu[] =
{"Rate Scaling",EditOPParameter, 0, DEXED_OP_OSC_RATE_SCALE}, {"Rate Scaling",EditOPParameter, 0, DEXED_OP_OSC_RATE_SCALE},
{"A Mod Sens.", EditOPParameter, 0, DEXED_OP_AMP_MOD_SENS}, {"A Mod Sens.", EditOPParameter, 0, DEXED_OP_AMP_MOD_SENS},
{"K Vel. Sens.",EditOPParameter, 0, DEXED_OP_KEY_VEL_SENS}, {"K Vel. Sens.",EditOPParameter, 0, DEXED_OP_KEY_VEL_SENS},
{"Enable", EditOPParameter, 0, DEXED_OP_ENABLE}, {"Enable", EditOPParameter, 0, DEXED_OP_ENABLE},
{0} {0}
}; };
@ -306,58 +407,50 @@ const CUIMenu::TParameter CUIMenu::s_GlobalParameter[CMiniDexed::ParameterUnknow
{0, 99, 1} // ParameterReverbLevel {0, 99, 1} // ParameterReverbLevel
// BEGIN FXRack global parameters mapping definition // BEGIN FXRack global parameters mapping definition
#ifdef FXRACK_ENABLE #ifdef MIXING_CONSOLE_ENABLE
, ,
// FXChain parameters
{0, 1, 1, ToOnOff}, // ParameterFXChainEnable // FX > Tube parameters
{0, 99, 1}, // ParameterFXChainWet {0, 1, 1, ToOnOff}, // ParameterFXTubeEnable
{0, 99, 1}, // ParameterFXTubeOverdrive
// FXChain > Tube parameters
{0, 1, 1, ToOnOff}, // ParameterFXChainTubeEnable // FX > Chorus parameters
{0, 99, 1}, // ParameterFXChainTubeWet {0, 1, 1, ToOnOff}, // ParameterFXChorusEnable
{0, 99, 1}, // ParameterFXChainTubeOverdrive {0, 99, 1}, // ParameterFXChorusRate
{0, 99, 1}, // ParameterFXChorusDepth
// FXChain > Chorus parameters
{0, 1, 1, ToOnOff}, // ParameterFXChainChorusEnable // FX > Flanger parameters
{0, 99, 1}, // ParameterFXChainChorusWet {0, 1, 1, ToOnOff}, // ParameterFXFlangerEnable
{0, 99, 1}, // ParameterFXChainChorusRate {0, 99, 1}, // ParameterFXFlangerRate
{0, 99, 1}, // ParameterFXChainChorusDepth {0, 99, 1}, // ParameterFXFlangerDepth
{0, 99, 1}, // ParameterFXFlangerFeedback
// FXChain > Flanger parameters
{0, 1, 1, ToOnOff}, // ParameterFXChainFlangerEnable // FX > Orbitone parameters
{0, 99, 1}, // ParameterFXChainFlangerWet {0, 1, 1, ToOnOff}, // ParameterFXOrbitoneEnable
{0, 99, 1}, // ParameterFXChainFlangerRate {0, 99, 1}, // ParameterFXOrbitoneRate
{0, 99, 1}, // ParameterFXChainFlangerDepth {0, 99, 1}, // ParameterFXOrbitoneDepth
{0, 99, 1}, // ParameterFXChainFlangerFeedback
// FX > Phaser parameters
// FXChain > Orbitone parameters {0, 1, 1, ToOnOff}, // ParameterFXPhaserEnable
{0, 1, 1, ToOnOff}, // ParameterFXChainOrbitoneEnable {0, 99, 1}, // ParameterFXPhaserRate
{0, 99, 1}, // ParameterFXChainOrbitoneWet {0, 99, 1}, // ParameterFXPhaserDepth
{0, 99, 1}, // ParameterFXChainOrbitoneRate {0, 99, 1}, // ParameterFXPhaserFeedback
{0, 99, 1}, // ParameterFXChainOrbitoneDepth {2, MAX_NB_PHASES, 1}, // ParameterFXPhaserNbStages
// FXChain > Phaser parameters // FX > Delay parameters
{0, 1, 1, ToOnOff}, // ParameterFXChainPhaserEnable {0, 1, 1, ToOnOff}, // ParameterFXDelayEnable
{0, 99, 1}, // ParameterFXChainPhaserWet {0, 99, 1}, // ParameterFXDelayLeftDelayTime
{0, 99, 1}, // ParameterFXChainPhaserRate {0, 99, 1}, // ParameterFXDelayRightDelayTime
{0, 99, 1}, // ParameterFXChainPhaserDepth {0, 99, 1}, // ParameterFXDelayFeedback
{0, 99, 1}, // ParameterFXChainPhaserFeedback {0, 99, 1}, // ParameterFXDelayFlutterRate
{2, MAX_NB_PHASES, 1}, // ParameterFXChainPhaserNbStages {0, 99, 1}, // ParameterFXDelayFlutterAmount
// FXChain > Delay parameters // FX > ShimmerReverb parameters
{0, 1, 1, ToOnOff}, // ParameterFXChainDelayEnable {0, 1, 1, ToOnOff}, // ParameterFXShimmerReverbEnable
{0, 99, 1}, // ParameterFXChainDelayWet {0, 99, 1}, // ParameterFXShimmerReverbInputGain
{0, 99, 1}, // ParameterFXChainDelayLeftDelayTime {0, 99, 1}, // ParameterFXShimmerReverbTime
{0, 99, 1}, // ParameterFXChainDelayRightDelayTime {0, 99, 1}, // ParameterFXShimmerReverbDiffusion
{0, 99, 1}, // ParameterFXChainDelayFeedback {0, 99, 1}, // ParameterFXShimmerReverbLP
// FXChain > ShimmerReverb parameters
{0, 1, 1, ToOnOff}, // ParameterFXChainShimmerReverbEnable
{0, 99, 1}, // ParameterFXChainShimmerReverbWet
{0, 99, 1}, // ParameterFXChainShimmerReverbInputGain
{0, 99, 1}, // ParameterFXChainShimmerReverbTime
{0, 99, 1}, // ParameterFXChainShimmerReverbDiffusion
{0, 99, 1}, // ParameterFXChainShimmerReverbLP
#endif #endif
// END FXRack global parameters mapping definition // END FXRack global parameters mapping definition

@ -142,15 +142,22 @@ private:
#ifdef ARM_ALLOW_MULTI_CORE #ifdef ARM_ALLOW_MULTI_CORE
static const TMenuItem s_ReverbMenu[]; static const TMenuItem s_ReverbMenu[];
#endif #endif
#ifdef FXRACK_ENABLE #ifdef MIXING_CONSOLE_ENABLE
static const TMenuItem s_FXChainMenu[]; static const TMenuItem s_FXMenu[];
static const TMenuItem s_FXChainTube[]; static const TMenuItem s_FXTube[];
static const TMenuItem s_FXChainChorus[]; static const TMenuItem s_FXTubeReturn[];
static const TMenuItem s_FXChainFlanger[]; static const TMenuItem s_FXChorus[];
static const TMenuItem s_FXChainOrbitone[]; static const TMenuItem s_FXChorusReturn[];
static const TMenuItem s_FXChainPhaser[]; static const TMenuItem s_FXFlanger[];
static const TMenuItem s_FXChainDelay[]; static const TMenuItem s_FXFlangerReturn[];
static const TMenuItem s_FXChainShimmerReverb[]; static const TMenuItem s_FXOrbitone[];
static const TMenuItem s_FXOrbitoneReturn[];
static const TMenuItem s_FXPhaser[];
static const TMenuItem s_FXPhaserReturn[];
static const TMenuItem s_FXDelay[];
static const TMenuItem s_FXDelayReturn[];
static const TMenuItem s_FXShimmerReverb[];
static const TMenuItem s_FXShimmerReverbReturn[];
#endif #endif
static const TMenuItem s_EditVoiceMenu[]; static const TMenuItem s_EditVoiceMenu[];
static const TMenuItem s_OperatorMenu[]; static const TMenuItem s_OperatorMenu[];

@ -229,6 +229,68 @@ void CUserInterface::DisplayWrite (const char *pMenu, const char *pParam, const
LCDWrite (Msg); LCDWrite (Msg);
} }
#ifdef DEBUG
#include "cstring"
void CUserInterface::clear()
{
static size_t nbChars = this->m_pConfig->GetLCDColumns() * this->m_pConfig->GetLCDRows();
std::string txt("\x1B[H\E[?25l");
txt.append(nbChars, ' ');
txt.append("\x1B[K");
if (this->m_pLCDBuffered)
{
this->m_pLCDBuffered->Write(txt.c_str(), txt.length());
this->m_pLCDBuffered->Update ();
}
}
void CUserInterface::log(const char* txt)
{
if (this->m_pLCDBuffered)
{
this->m_pLCDBuffered->Write(txt, strlen(txt));
this->m_pLCDBuffered->Update ();
}
}
void CUserInterface::log(float32_t v)
{
std::ostringstream ss;
ss << std::fixed << std::setprecision(2) << v;
std::string txt = ss.str();
if (this->m_pLCDBuffered)
{
this->m_pLCDBuffered->Write(txt.c_str(), txt.length());
this->m_pLCDBuffered->Update ();
}
}
void CUserInterface::log(unsigned v)
{
std::string txt = std::to_string(v);
if (this->m_pLCDBuffered)
{
this->m_pLCDBuffered->Write(txt.c_str(), txt.length());
this->m_pLCDBuffered->Update ();
}
}
void CUserInterface::log(int v)
{
std::string txt = std::to_string(v);
if (this->m_pLCDBuffered)
{
this->m_pLCDBuffered->Write(txt.c_str(), txt.length());
this->m_pLCDBuffered->Update ();
}
}
#endif
void CUserInterface::LCDWrite (const char *pString) void CUserInterface::LCDWrite (const char *pString)
{ {
if (m_pLCDBuffered) if (m_pLCDBuffered)

@ -55,9 +55,19 @@ public:
// To be called from the MIDI device on reception of a MIDI CC message // To be called from the MIDI device on reception of a MIDI CC message
void UIMIDICmdHandler (unsigned nMidiCh, unsigned nMidiCmd, unsigned nMidiData1, unsigned nMidiData2); void UIMIDICmdHandler (unsigned nMidiCh, unsigned nMidiCmd, unsigned nMidiData1, unsigned nMidiData2);
#ifdef DEBUG
public:
void clear();
void log(const char* txt);
void log(float32_t v);
void log(unsigned v);
void log(int v);
#else
private: private:
#endif
void LCDWrite (const char *pString); // Print to optional HD44780 display void LCDWrite (const char *pString); // Print to optional HD44780 display
private:
void EncoderEventHandler (CKY040::TEvent Event); void EncoderEventHandler (CKY040::TEvent Event);
static void EncoderEventStub (CKY040::TEvent Event, void *pParam); static void EncoderEventStub (CKY040::TEvent Event, void *pParam);
void UIButtonsEventHandler (CUIButton::BtnEvent Event); void UIButtonsEventHandler (CUIButton::BtnEvent Event);

Loading…
Cancel
Save