From 6c1dfb5ee6894530327db819db41f139b41f8050 Mon Sep 17 00:00:00 2001 From: abscisys Date: Fri, 20 Jan 2023 00:59:30 +0100 Subject: [PATCH] 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 --- .gitignore | 2 + src/Makefile | 2 +- src/extra_features.h | 7 +- src/fx.h | 2 + src/fx_chorus.h | 2 +- src/fx_components.cpp | 132 +++++- src/fx_components.h | 190 ++------ src/fx_delay.cpp | 77 ++- src/fx_delay.h | 13 +- src/fx_engine.hpp | 87 +++- src/fx_orbitone.h | 2 +- src/fx_shimmer_reverb.cpp | 31 +- src/fx_shimmer_reverb.h | 2 +- src/fx_svf.cpp | 182 +++----- src/fx_svf.h | 28 +- src/fx_tube.cpp | 16 +- src/fx_tube.h | 2 +- src/fx_unit2.hpp | 101 ++++ src/mididevice.cpp | 21 +- src/minidexed.cpp | 822 +++++++++++++++++++-------------- src/minidexed.h | 209 ++++++--- src/mixing_console.cpp | 354 ++++++++++++++ src/mixing_console.h | 96 ++++ src/mixing_console_constants.h | 59 +++ src/performanceconfig.cpp | 475 +++++++++---------- src/performanceconfig.h | 197 ++++---- src/test/Makefile | 49 +- src/test/MixerOutputTest.hpp | 101 ++++ src/test/UIMenuTest.hpp | 12 + src/test/all_tests.cpp | 8 + src/test/arm_functions.cpp | 46 ++ src/test/desktop.ini | 4 + src/test/fxrack_test.cpp | 211 +++++++-- src/uimenu.cpp | 417 ++++++++++------- src/uimenu.h | 25 +- src/userinterface.cpp | 62 +++ src/userinterface.h | 10 + 37 files changed, 2731 insertions(+), 1325 deletions(-) create mode 100644 src/fx_unit2.hpp create mode 100644 src/mixing_console.cpp create mode 100644 src/mixing_console.h create mode 100644 src/mixing_console_constants.h create mode 100644 src/test/MixerOutputTest.hpp create mode 100644 src/test/UIMenuTest.hpp create mode 100644 src/test/all_tests.cpp create mode 100644 src/test/arm_functions.cpp create mode 100644 src/test/desktop.ini diff --git a/.gitignore b/.gitignore index 597ceeb..10d4c66 100644 --- a/.gitignore +++ b/.gitignore @@ -49,5 +49,7 @@ sdcard # temporary tests src/test/fxrack_test +src/test/all_tests +src/test/waves/ src/test/result*.wav src/test/*.csv diff --git a/src/Makefile b/src/Makefile index 454438d..57bb99e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -12,7 +12,7 @@ OBJS = main.o kernel.o minidexed.o config.o userinterface.o uimenu.o \ effect_compressor.o effect_platervbstereo.o \ fx.o fx_components.o \ fx_svf.o fx_tube.o fx_chorus.o fx_flanger.o fx_orbitone.o fx_phaser.o \ - fx_delay.o fx_shimmer_reverb.o fx_rack.o \ + fx_delay.o fx_shimmer_reverb.o fx_dry.o \ uibuttons.o midipin.o OPTIMIZE = -O3 diff --git a/src/extra_features.h b/src/extra_features.h index a86a657..ac545e4 100644 --- a/src/extra_features.h +++ b/src/extra_features.h @@ -20,6 +20,11 @@ #if defined(ARM_ALLOW_MULTI_CORE) -#define FXRACK_ENABLE //Add support for the FXRack +#define MIXING_CONSOLE_ENABLE //Add support for the MixingConsole #endif + +#ifdef DEBUG +#include +#include +#endif \ No newline at end of file diff --git a/src/fx.h b/src/fx.h index 1f94091..396614b 100644 --- a/src/fx.h +++ b/src/fx.h @@ -22,6 +22,8 @@ #include #include "common.h" +#include "extra_features.h" + #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&) = delete; \ void operator=(const TypeName&) = delete diff --git a/src/fx_chorus.h b/src/fx_chorus.h index 59f72c6..13f3040 100644 --- a/src/fx_chorus.h +++ b/src/fx_chorus.h @@ -48,7 +48,7 @@ public: float32_t getRate() const; private: - typedef FxEngine<2048, FORMAT_16_BIT, false> Engine; + typedef FxEngine<2048, Format::FORMAT_FLOAT32, false> Engine; Engine engine_; float32_t rate_; // Normalized frequency for the 2 LFOs frequencies (0.0 - 10.0) diff --git a/src/fx_components.cpp b/src/fx_components.cpp index dfa5f7c..5ccc838 100644 --- a/src/fx_components.cpp +++ b/src/fx_components.cpp @@ -7,6 +7,8 @@ /////////////////////////////// const float32_t Constants::M2PI = 2.0f * PI; const float32_t Constants::MPI_2 = PI / 2.0f; +const float32_t Constants::MPI_3 = PI / 3.0f; +const float32_t Constants::MPI_4 = PI / 4.0f; const float32_t Constants::M1_PI = 1.0f / PI; ///////////////////////// @@ -139,7 +141,7 @@ float32_t LFO::current() const //////////////////////////////////// // JitterGenerator implementation // //////////////////////////////////// -JitterGenerator::JitterGenerator(float32_t sampling_rate) : +JitterGenerator::JitterGenerator(float32_t sampling_rate) : FXBase(sampling_rate), rnd_generator_(rnd_device_()), rnd_distribution_(-1.0f, 1.0f), @@ -198,6 +200,116 @@ float32_t JitterGenerator::process() 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 // ////////////////////////////////// @@ -210,7 +322,7 @@ float32_t softSaturator1(float32_t in, float32_t threshold) y = x; } else if(x > threshold) - { + { y = threshold + (x - threshold) / (1.0f + std::pow((x - threshold) / (1.0f - threshold), 2.0f)); } else if(x > 1.0f) @@ -220,7 +332,7 @@ float32_t softSaturator1(float32_t in, float32_t threshold) float32_t g = 2.0f / (1.0f + threshold); y *= g; - + return (in < 0.0f) ? -y : y; } @@ -259,6 +371,20 @@ float32_t softSaturator2(float32_t input, float32_t saturation) 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) { bias = 0.5 + (2.0f - bias) / 4.0f; diff --git a/src/fx_components.h b/src/fx_components.h index 2ac27fa..03b0082 100644 --- a/src/fx_components.h +++ b/src/fx_components.h @@ -28,6 +28,8 @@ struct Constants { const static float32_t M2PI; // 2 * PI 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 }; @@ -76,162 +78,6 @@ private: std::uniform_real_distribution rnd_distribution_; }; -template -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 -class 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 { @@ -260,7 +106,39 @@ private: 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 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); \ No newline at end of file diff --git a/src/fx_delay.cpp b/src/fx_delay.cpp index c47f1d4..49f4b88 100644 --- a/src/fx_delay.cpp +++ b/src/fx_delay.cpp @@ -2,18 +2,21 @@ #include -#define MAX_DELAY_TIME 1.0f -#define MAX_FLUTTER_DELAY_TIME 0.01f +#define MAX_DELAY_TIME 2.0f +#define MAX_FLUTTER_DELAY_TIME 0.001f -#define LPF_CUTOFF_REF 14000.0f -#define HPF_CUTOFF_REF 60.0f +#define LPF_CUTOFF_REF 12000.0f +#define HPF_CUTOFF_REF 80.0f Delay::LowHighPassFilter::LowHighPassFilter(float32_t sampling_rate) : FXElement(sampling_rate), lpf_(sampling_rate, StateVariableFilter::Type::LPF, LPF_CUTOFF_REF), - hpf_(sampling_rate, StateVariableFilter::Type::HPF, HPF_CUTOFF_REF) + hpf_(sampling_rate, StateVariableFilter::Type::HPF, HPF_CUTOFF_REF), + ratio_(1.0f) { this->setCutoffChangeRatio(0.0f); + this->lpf_.setGainDB(0.82f); + this->hpf_.setGainDB(0.82f); } Delay::LowHighPassFilter::~LowHighPassFilter() @@ -22,10 +25,16 @@ Delay::LowHighPassFilter::~LowHighPassFilter() void Delay::LowHighPassFilter::setCutoffChangeRatio(float32_t ratio) { - ratio += 1.0f; + static const float32_t weight = 4.0f; - this->lpf_.setCutoff(LPF_CUTOFF_REF * ratio); - this->hpf_.setCutoff(HPF_CUTOFF_REF * ratio); + ratio = constrain(ratio, -1.0f, 1.0f); + 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() @@ -45,15 +54,18 @@ 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), read_pos_L_(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_R_ = new float32_t[this->MaxSampleDelayTime]; this->setLeftDelayTime(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(); } @@ -70,12 +82,23 @@ void Delay::reset() this->read_pos_L_ = 0; this->read_pos_R_ = 0; this->filter_.reset(); + this->jitter_generator_.reset(); } void Delay::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) { - float32_t delay_time_L = (MAX_DELAY_TIME * this->getLeftDelayTime() ) * this->getSamplingRate(); - float32_t delay_time_R = (MAX_DELAY_TIME * this->getRightDelayTime()) * this->getSamplingRate(); + static const float32_t max_delay_time = MAX_DELAY_TIME * 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 unsigned write_pos_L = static_cast(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 ); - this->buffer_L_[write_pos_L] += outL * this->getFeedbackLevel(); - this->buffer_R_[write_pos_R] += outR * this->getFeedbackLevel(); + this->buffer_L_[write_pos_L] += outL * this->getFeedback(); + this->buffer_R_[write_pos_R] += outR * this->getFeedback(); // Increment read positions ++this->read_pos_L_; @@ -129,12 +152,32 @@ float32_t Delay::getRightDelayTime() const 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); } -float32_t Delay::getFeedbackLevel() const +float32_t Delay::getFeedback() const { 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_; +} diff --git a/src/fx_delay.h b/src/fx_delay.h index f250ff4..3f67edd 100644 --- a/src/fx_delay.h +++ b/src/fx_delay.h @@ -44,6 +44,7 @@ class Delay : public FXElement private: StateVariableFilter lpf_; StateVariableFilter hpf_; + float32_t ratio_; }; @@ -60,8 +61,14 @@ public: void setRightDelayTime(float32_t delay_time); float32_t getRightDelayTime() const; - void setFeedbak(float32_t feedback); - float32_t getFeedbackLevel() const; + void setFeedback(float32_t feedback); + float32_t getFeedback() const; + + void setFlutterRate(float32_t rate); + float32_t getFlutterRate() const; + + void setFlutterAmount(float32_t amount); + float32_t getFlutterAmount() const; private: 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_R_; // Right delay time in seconds (0.0 - 2.0) float32_t feedback_; // Feedback (0.0 - 1.0) + float32_t jitter_amount_; LowHighPassFilter filter_; + PerlinNoiseGenerator jitter_generator_; }; diff --git a/src/fx_engine.hpp b/src/fx_engine.hpp index d295d0b..bd6d90a 100644 --- a/src/fx_engine.hpp +++ b/src/fx_engine.hpp @@ -8,10 +8,11 @@ #define MAKE_INTEGRAL_FRACTIONAL(x) \ int32_t x ## _integral = static_cast(x); \ - float x ## _fractional = x - static_cast(x ## _integral); + float32_t x ## _fractional = x - static_cast(x ## _integral); enum Format { + FORMAT_FLOAT32, FORMAT_12_BIT, FORMAT_16_BIT, FORMAT_32_BIT @@ -38,7 +39,23 @@ inline int16_t clip16(int32_t x) } template <> -struct DataType +struct DataType +{ + 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 { typedef uint16_t T; @@ -53,9 +70,41 @@ struct DataType } }; +template <> +struct DataType +{ + typedef uint32_t T; + + static inline float32_t decompress(T value) + { + return static_cast(static_cast(value)) / 65536.0f; + } + + static inline T compress(float32_t value) + { + return clip16(static_cast(value * 65536.0f)); + } +}; + +template <> +struct DataType +{ + typedef uint32_t T; + + static inline float32_t decompress(T value) + { + return static_cast(static_cast(value)) / static_cast(UINT32_MAX); + } + + static inline T compress(float32_t value) + { + return value * static_cast(INT32_MAX); + } +}; + template < size_t size, - Format format = FORMAT_16_BIT, + Format format, bool enable_lfo = true> class FxEngine : public FXBase { @@ -67,15 +116,15 @@ public: enum LFOIndex { 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) : FXBase(sampling_rate) { - this->buffer_ = new uint16_t[size]; - this->lfo_[LFOIndex::LFO_1] = 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->buffer_ = new T[size]; + 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->clear(); } @@ -84,14 +133,13 @@ public: delete[] this->buffer_; if(enable_lfo) { - delete this->lfo_[LFO_1]; - delete this->lfo_[LFO_2]; + for(unsigned i = 0; i < LFOIndex::kLFOCount; ++i) delete this->lfo_[i]; } } void clear() { - memset(this->buffer_, 0, size * sizeof(uint16_t)); + memset(this->buffer_, 0, size * sizeof(T)); this->write_ptr_ = 0; } @@ -100,8 +148,7 @@ public: this->clear(); if(enable_lfo) { - this->lfo_[LFOIndex::LFO_1]->reset(); - this->lfo_[LFOIndex::LFO_2]->reset(); + for(unsigned i = 0; i < LFOIndex::kLFOCount; ++i) this->lfo_[i]->reset(); } } @@ -151,7 +198,7 @@ public: buffer_(nullptr), write_ptr_(0) { - memset(this->lfo_value_, 0, 2 * sizeof(float32_t)); + memset(this->lfo_value_, 0, LFOIndex::kLFOCount * sizeof(T)); } ~Context() @@ -271,6 +318,7 @@ public: inline void interpolate(D& d, float32_t offset, LFOIndex index, float32_t amplitude, float32_t scale) { assert(D::base + D::length <= size); + assert(index < LFOIndex::kLFOCount); offset += amplitude * this->lfo_value_[index]; MAKE_INTEGRAL_FRACTIONAL(offset); float32_t a = DataType::decompress(this->buffer_[(this->write_ptr_ + offset_integral + D::base) & MASK]); @@ -283,13 +331,14 @@ public: private: float32_t accumulator_; float32_t previous_read_; - float32_t lfo_value_[2]; + float32_t lfo_value_[LFOIndex::kLFOCount]; T* buffer_; int32_t write_ptr_; }; inline void setLFOFrequency(LFOIndex index, float32_t frequency) { + assert(index < LFOIndex::kLFOCount); if(enable_lfo) { this->lfo_[index]->setFrequency(frequency); @@ -298,6 +347,7 @@ public: inline void setLFONormalizedFrequency(LFOIndex index, float32_t normalized_frequency) { + assert(index < LFOIndex::kLFOCount); if(enable_lfo) { this->lfo_[index]->setNormalizedFrequency(normalized_frequency); @@ -317,8 +367,7 @@ public: c->write_ptr_ = write_ptr_; if(enable_lfo) { - c->lfo_value_[LFO_1] = this->lfo_[LFO_1]->process(); - c->lfo_value_[LFO_2] = this->lfo_[LFO_2]->process(); + for(unsigned i = 0; i < LFOIndex::kLFOCount; ++i) c->lfo_value_[i] = this->lfo_[i]->process(); } } @@ -328,8 +377,8 @@ private: MASK = size - 1 }; - uint16_t* buffer_; - unsigned write_ptr_; + T* buffer_; + int32_t write_ptr_; - LFO* lfo_[2]; + LFO* lfo_[LFOIndex::kLFOCount]; }; diff --git a/src/fx_orbitone.h b/src/fx_orbitone.h index 811b1d5..2bcfa4e 100644 --- a/src/fx_orbitone.h +++ b/src/fx_orbitone.h @@ -50,7 +50,7 @@ public: float32_t getDepth() const; private: - typedef FxEngine<4096, FORMAT_16_BIT, false> Engine; + typedef FxEngine<4096, Format::FORMAT_FLOAT32, false> Engine; Engine engine_; float32_t depth_; diff --git a/src/fx_shimmer_reverb.cpp b/src/fx_shimmer_reverb.cpp index cfa3e10..b163421 100644 --- a/src/fx_shimmer_reverb.cpp +++ b/src/fx_shimmer_reverb.cpp @@ -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). // 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. - typedef Engine::Reserve<113, - Engine::Reserve<162, - Engine::Reserve<241, - Engine::Reserve<399, - Engine::Reserve<1653, - Engine::Reserve<2038, - Engine::Reserve<3411, - Engine::Reserve<1913, - Engine::Reserve<1663, - Engine::Reserve<4782> > > > > > > > > > Memory; + typedef Engine::Reserve< 113, + Engine::Reserve< 162, + Engine::Reserve< 241, + Engine::Reserve< 399, + Engine::Reserve<1653, + Engine::Reserve<2038, + Engine::Reserve<3411, + Engine::Reserve<1913, + Engine::Reserve<1663, + Engine::Reserve<4782> > > > > > > > > > Memory; Engine::DelayLine ap1; Engine::DelayLine ap2; Engine::DelayLine 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_2 = this->lp_decay_2_; - float32_t wet; + float32_t wet = 0.0f; float32_t apout = 0.0f; engine_.start(&c); // Smear AP1 inside the loop. c.interpolate(ap1, 10.0f, Engine::LFOIndex::LFO_1, 60.0f, 1.0f); c.write(ap1, 100, 0.0f); - c.read(inL + inR, gain); // 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(wet, 0.0f); - outR += wet; + outR = wet; 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.lp(lp_2, klp); c.read(dap2a TAIL, kap); @@ -110,8 +109,8 @@ void ShimmerReverb::processSample(float32_t inL, float32_t inR, float32_t& outL, c.write(del2, 2.0f); c.write(wet, 0.0f); - outR += wet; - + outR = wet; + this->lp_decay_1_ = lp_1; this->lp_decay_2_ = lp_2; } diff --git a/src/fx_shimmer_reverb.h b/src/fx_shimmer_reverb.h index f876581..9b133fd 100644 --- a/src/fx_shimmer_reverb.h +++ b/src/fx_shimmer_reverb.h @@ -47,7 +47,7 @@ public: float32_t getLP() const; private: - typedef FxEngine<16384, FORMAT_16_BIT, true> Engine; + typedef FxEngine<16384, Format::FORMAT_FLOAT32, true> Engine; Engine engine_; float32_t input_gain_; diff --git a/src/fx_svf.cpp b/src/fx_svf.cpp index 33350b3..3267c88 100644 --- a/src/fx_svf.cpp +++ b/src/fx_svf.cpp @@ -5,13 +5,13 @@ StateVariableFilter::StateVariableFilter(float32_t sampling_rate, Type type, float32_t cutoff) : FXElement(sampling_rate), type_(type), - cutoff_(0.0f), - resonance_(0.0f), - peak_gain_(0.0f) + gain_(-1.0f), + cutoff_(cutoff), + resonance_(0.0f) { - this->setPeakGainDB(1.0f); this->setCutoff(cutoff); this->setResonance(0.0f); + this->setGainDB(0.0f); 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(); } } @@ -61,130 +63,88 @@ void StateVariableFilter::setPeakGainDB(float32_t gain) void StateVariableFilter::updateCoefficients() { // Compute the filter coefficients based on the current parameter values - float32_t w0 = PI * this->cutoff_ / this->getSamplingRate(); - float32_t V = pow(10, fabs(this->peak_gain_) / 20.0f); - float32_t K = std::tan(w0); - float32_t K2 = K * K; - float32_t norm; + this->w_ = 2.0f * std::tan(PI * this->cutoff_ / this->getSamplingRate()); + this->a_ = this->w_ / this->resonance_; + this->b_ = this->w_ * this->w_; + float32_t a_b = this->a_ + this->b_; + this->c1_ = a_b / (1.0f + 0.5f * this->a_ + 0.25f * this->b_); + this->c2_ = this->b_ / a_b; switch(this->type_) { + case Type::LPF: - norm = 1.0f / (1.0f + K / this->resonance_ + K2); - this->a0_ = K2 * norm; - 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; + this->d1_ = 0.0f; + this->d0_ = 0.25f * this->c1_ * this->c2_; break; case Type::HPF: - norm = 1.0f / (1.0f + K / this->resonance_ + K2); - this->a0_ = norm; - 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; + this->d1_ = 0.0f; + this->d0_ = 1.0f - 0.5f * this->c1_ + 0.25f * this->c1_ * this->c2_; break; case Type::BPF: - norm = 1.0f / (1.0f + K / this->resonance_ + K2); - this->a0_ = K / this->resonance_ * norm; - 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; + this->d1_ = 1.0f - this->c2_; + this->d0_ = this->d1_ * this->c1_ * 0.5f; 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 - norm = 1.0f / (1.0f + 1.0f / this->resonance_ * K + K2); - this->a0_ = (1.0f + V / this->resonance_ * K + K2) * norm; - this->a1_ = 2.0f * (K2 - 1) * norm; - 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; + const float32_t x = inL - this->z1_[StereoChannels::Left] - this->z2_[StereoChannels::Left] + 1e-20f; + this->z2_[StereoChannels::Left] += this->c2_ * this->z1_[StereoChannels::Left]; + outL = gain * (this->d0_ * x + this->z2_[StereoChannels::Left]); + this->z1_[StereoChannels::Left] += this->c1_ * x; } - else { - // cut - norm = 1.0f / (1 + V / this->resonance_ * K + K2); - this->a0_ = (1.0f + 1.0f / this->resonance_ * K + K2) * norm; - this->a1_ = 2.0f * (K2 - 1) * norm; - 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; + const float32_t x = inR - this->z1_[StereoChannels::Right] - this->z2_[StereoChannels::Right] + 1e-20f; + this->z2_[StereoChannels::Right] += this->c2_ * this->z1_[StereoChannels::Right]; + outR = gain * (this->d0_ * x + this->z2_[StereoChannels::Right]); + this->z1_[StereoChannels::Right] += this->c1_ * x; } break; - case Type::LSH: - if(this->peak_gain_ >= 0) - { - // boost - norm = 1 / (1 + std::sqrt(2) * K + K2); - this->a0_ = (1.0f + std::sqrt(2.0f * V) * K + V * K2) * norm; - this->a1_ = 2.0f * (V * K2 - 1.0f) * norm; - 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; + + case Type::HPF: + { + const float32_t x = inL - this->z1_[StereoChannels::Left] - this->z2_[StereoChannels::Left] + 1e-20f; + outL = gain * this->d0_ * x; + this->z2_[StereoChannels::Left] += this->c2_ * this->z1_[StereoChannels::Left]; + this->z1_[StereoChannels::Left] += this->c1_ * x; } - else - { - // cutK * K - norm = 1.0f / (1.0f + std::sqrt(2.0f * V) * K + V * K2); - this->a0_ = (1.0f + std::sqrt(2.0f) * K + K2) * norm; - this->a1_ = 2.0f * (K2 - 1.0f) * norm; - 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; + { + const float32_t x = inR - this->z1_[StereoChannels::Right] - this->z2_[StereoChannels::Right] + 1e-20f; + outR = gain * this->d0_ * x; + this->z2_[StereoChannels::Right] += this->c2_ * this->z1_[StereoChannels::Right]; + this->z1_[StereoChannels::Right] += this->c1_ * x; } break; - case Type::HSH: - if(this->peak_gain_ >= 0) + + case Type::BPF: { - // boost - norm = 1.0f / (1.0f + std::sqrt(2.0f) * K + K2); - this->a0_ = (V + std::sqrt(2.0f * V) * K + K2) * norm; - this->a1_ = 2.0f * (K2 - V) * norm; - 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; + const float32_t x = inL - this->z1_[StereoChannels::Left] - this->z2_[StereoChannels::Left] + 1e-20f; + outL = gain * (this->d0_ * x) + this->d1_ * this->z1_[StereoChannels::Left]; + this->z2_[StereoChannels::Left] += this->c2_ * this->z1_[StereoChannels::Left]; + this->z1_[StereoChannels::Left] += this->c1_ * x; } - else { - // cut - norm = 1.0f / (V + std::sqrt(2.0f * V) * K + K2); - this->a0_ = (1.0f + std::sqrt(2.0f) * K + K2) * norm; - this->a1_ = 2.0f * (K2 - 1.0f) * norm; - 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; + const float32_t x = inR - this->z1_[StereoChannels::Right] - this->z2_[StereoChannels::Right] + 1e-20f; + outL = gain * (this->d0_ * x) + this->d1_ * this->z1_[StereoChannels::Right]; + this->z2_[StereoChannels::Right] += this->c2_ * this->z1_[StereoChannels::Right]; + this->z1_[StereoChannels::Right] += this->c1_ * x; } - 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; -} diff --git a/src/fx_svf.h b/src/fx_svf.h index 2df768b..3a4b35f 100644 --- a/src/fx_svf.h +++ b/src/fx_svf.h @@ -19,6 +19,7 @@ // #include "fx.h" +#include "mixing_console_constants.h" class StateVariableFilter : public FXElement { @@ -29,20 +30,16 @@ public: { LPF, // Low pass filter HPF, // High pass filter - BPF, // Band pass filter - NOTCH, // Notch Filter - PEQ, // Peaking band EQ filter - LSH, // Low shelf filter - HSH // High shelf filter + BPF // Band pass filter } Type; StateVariableFilter(float32_t sampling_rate, Type type, float32_t cutoff); virtual ~StateVariableFilter(); void setFilterType(Type type); + void setGainDB(float32_t gainDB); void setCutoff(float32_t cutoff); void setResonance(float32_t resonance); - void setPeakGainDB(float32_t gainDB); virtual void reset() override; virtual void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) override; @@ -51,14 +48,17 @@ private: void updateCoefficients(); Type type_; + float32_t gain_; float32_t cutoff_; float32_t resonance_; - float32_t peak_gain_; - float32_t a0_; - float32_t a1_; - float32_t a2_; - float32_t b1_; - float32_t b2_; - float32_t z1_[2]; - float32_t z2_[2]; + float32_t g_; + float32_t w_; + float32_t a_; + float32_t b_; + float32_t c1_; + float32_t c2_; + float32_t d0_; + float32_t d1_; + float32_t z1_[StereoChannels::kNumChannels]; + float32_t z2_[StereoChannels::kNumChannels]; }; \ No newline at end of file diff --git a/src/fx_tube.cpp b/src/fx_tube.cpp index ec6bd00..9a6cf75 100644 --- a/src/fx_tube.cpp +++ b/src/fx_tube.cpp @@ -5,7 +5,7 @@ Tube::Tube(float32_t samplingRate) : FXElement(samplingRate), overdrive_(0.0f), - saturation_(0.0f) + saturator_factor_(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) { - outL = softSaturator2(inL, this->saturation_); - outR = softSaturator2(inR, this->saturation_); + outL = softSaturator4(inL, this->saturator_factor_); + outR = softSaturator4(inR, this->saturator_factor_); } void Tube::setOverdrive(float32_t overdrive) { - this->overdrive_ = constrain(overdrive, 0.0f, 1.0f); - this->saturation_ = 2.0f * this->overdrive_; + static const float32_t N = 200.0f; + + 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 diff --git a/src/fx_tube.h b/src/fx_tube.h index aaaa31e..583325b 100644 --- a/src/fx_tube.h +++ b/src/fx_tube.h @@ -36,5 +36,5 @@ public: private: float32_t overdrive_; - float32_t saturation_; + float32_t saturator_factor_; }; \ No newline at end of file diff --git a/src/fx_unit2.hpp b/src/fx_unit2.hpp new file mode 100644 index 0000000..e5e3606 --- /dev/null +++ b/src/fx_unit2.hpp @@ -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 . + +// +// fx_unit2.h +// +// Unit of FX that handle the mute parameter +// +#pragma once + +#include "fx_components.h" + +#include +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 +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_; +}; diff --git a/src/mididevice.cpp b/src/mididevice.cpp index 898c187..3358dc3 100644 --- a/src/mididevice.cpp +++ b/src/mididevice.cpp @@ -47,7 +47,10 @@ LOGMODULE ("mididevice"); #define MIDI_CC_RESONANCE 71 #define MIDI_CC_FREQUENCY_CUTOFF 74 #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_PHASER_LEVEL 95 // added with mixing console #define MIDI_CC_ALL_SOUND_OFF 120 #define MIDI_CC_ALL_NOTES_OFF 123 #define MIDI_PROGRAM_CHANGE 0b1100 @@ -300,9 +303,25 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign break; 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); +#endif 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: if (pMessage[2] == 0) { diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 3c8774c..18f21fc 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -86,8 +86,12 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, m_nBreathControlTarget[i]=0; m_nAftertouchRange[i]=99; m_nAftertouchTarget[i]=0; - + +#ifdef MIXING_CONSOLE_ENABLE + memset(this->m_nFXSendLevel[i], 0, MixerOutput::kFXCount * sizeof(unsigned)); +#else m_nReverbSend[i] = 0; +#endif m_uchOPMask[i] = 0b111111; // All operators on m_pTG[i] = new CDexedAdapter (CConfig::MaxNotes, pConfig->GetSampleRate ()); @@ -96,6 +100,13 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, m_pTG[i]->activate (); } +#ifdef MIXING_CONSOLE_ENABLE + for(size_t ret = 0; ret < (MixerOutput::kFXCount - 1); ++ret) + { + memset(this->m_nFXReturnLevel[ret], 0, MixerOutput::kFXCount * sizeof(unsigned)); + } +#endif + for (unsigned i = 0; i < CConfig::MaxUSBMIDIDevices; i++) { m_pMIDIKeyboard[i] = new CMIDIKeyboard (this, pConfig, &m_UI, i); @@ -140,6 +151,62 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, setMasterVolume(1.0); + +#ifdef MIXING_CONSOLE_ENABLE + + this->mixing_console_ = new Mixer(static_cast(pConfig->GetSampleRate()), pConfig->GetChunkSize()/2); + + // Tube parameters + this->SetParameter(ParameterFXTubeEnable, 1); + this->SetParameter(ParameterFXTubeOverdrive, 10); + + // Chorus parameters + this->SetParameter(ParameterFXChorusEnable, 1); + this->SetParameter(ParameterFXChorusRate, 50); + this->SetParameter(ParameterFXChorusDepth, 50); + + // Flanger parameters + this->SetParameter(ParameterFXFlangerEnable, 1); + this->SetParameter(ParameterFXFlangerRate, 3); + this->SetParameter(ParameterFXFlangerDepth, 75); + this->SetParameter(ParameterFXFlangerFeedback, 50); + + // Orbitone parameters + this->SetParameter(ParameterFXOrbitoneEnable, 1); + this->SetParameter(ParameterFXOrbitoneRate, 40); + this->SetParameter(ParameterFXOrbitoneDepth, 50); + + // Phaser parameters + this->SetParameter(ParameterFXPhaserEnable, 1); + this->SetParameter(ParameterFXPhaserRate, 5); + this->SetParameter(ParameterFXPhaserDepth, 99); + this->SetParameter(ParameterFXPhaserFeedback, 50); + this->SetParameter(ParameterFXPhaserNbStages, 12); + + // Delay parameters + this->SetParameter(ParameterFXDelayEnable, 1); + this->SetParameter(ParameterFXDelayLeftDelayTime, 15); + this->SetParameter(ParameterFXDelayRightDelayTime, 22); + this->SetParameter(ParameterFXDelayFeedback, 35); + + // AudioEffectPlateReverb parameters + this->SetParameter(ParameterReverbEnable, 1); + this->SetParameter(ParameterReverbSize, 70); + this->SetParameter(ParameterReverbHighDamp, 50); + this->SetParameter(ParameterReverbLowDamp, 50); + this->SetParameter(ParameterReverbLowPass, 30); + this->SetParameter(ParameterReverbDiffusion, 65); + this->SetParameter(ParameterReverbLevel, 99); + + // ShimmerReverb parameters + this->SetParameter(ParameterFXShimmerReverbEnable, 1); + this->SetParameter(ParameterFXShimmerReverbInputGain, 99); + this->SetParameter(ParameterFXShimmerReverbTime, 80); + this->SetParameter(ParameterFXShimmerReverbDiffusion, 80); + this->SetParameter(ParameterFXShimmerReverbLP, 70); + +#else + // BEGIN setup tg_mixer tg_mixer = new AudioStereoMixer(pConfig->GetChunkSize()/2); // END setup tgmixer @@ -156,64 +223,9 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, SetParameter (ParameterReverbLevel, 99); // END setup reverb - SetParameter (ParameterCompressorEnable, 1); - - // BEGIN setup FXRack - #ifdef FXRACK_ENABLE - this->fx_rack = new FXRack(static_cast(pConfig->GetSampleRate())); - - // FXChain parameters - this->SetParameter(ParameterFXChainEnable, 1); - this->SetParameter(ParameterFXChainWet, 99); - - // FXChain > Tube parameters - this->SetParameter(ParameterFXChainTubeEnable, 1); - this->SetParameter(ParameterFXChainTubeWet, 50); - this->SetParameter(ParameterFXChainTubeOverdrive, 10); +#endif - // FXChain > Chorus parameters - this->SetParameter(ParameterFXChainChorusEnable, 1); - this->SetParameter(ParameterFXChainChorusWet, 50); - this->SetParameter(ParameterFXChainChorusRate, 50); - this->SetParameter(ParameterFXChainChorusDepth, 50); - - // FXChain > Flanger parameters - this->SetParameter(ParameterFXChainFlangerEnable, 1); - this->SetParameter(ParameterFXChainFlangerWet, 50); - this->SetParameter(ParameterFXChainFlangerRate, 3); - this->SetParameter(ParameterFXChainFlangerDepth, 75); - this->SetParameter(ParameterFXChainFlangerFeedback, 50); - - // FXChain > Orbitone parameters - this->SetParameter(ParameterFXChainOrbitoneEnable, 1); - this->SetParameter(ParameterFXChainOrbitoneWet, 80); - this->SetParameter(ParameterFXChainOrbitoneRate, 40); - this->SetParameter(ParameterFXChainOrbitoneDepth, 50); - - // FXChain > Phaser parameters - this->SetParameter(ParameterFXChainPhaserEnable, 1); - this->SetParameter(ParameterFXChainPhaserWet, 50); - this->SetParameter(ParameterFXChainPhaserRate, 5); - this->SetParameter(ParameterFXChainPhaserDepth, 99); - this->SetParameter(ParameterFXChainPhaserFeedback, 50); - this->SetParameter(ParameterFXChainPhaserNbStages, 12); - - // FXChain > Delay parameters - this->SetParameter(ParameterFXChainDelayEnable, 1); - this->SetParameter(ParameterFXChainDelayWet, 50); - this->SetParameter(ParameterFXChainDelayLeftDelayTime, 15); - this->SetParameter(ParameterFXChainDelayRightDelayTime, 22); - this->SetParameter(ParameterFXChainDelayFeedback, 35); - - // FXChain > ShimmerReverb parameters - this->SetParameter(ParameterFXChainShimmerReverbEnable, 1); - this->SetParameter(ParameterFXChainShimmerReverbWet, 70); - this->SetParameter(ParameterFXChainShimmerReverbInputGain, 99); - this->SetParameter(ParameterFXChainShimmerReverbTime, 80); - this->SetParameter(ParameterFXChainShimmerReverbDiffusion, 80); - this->SetParameter(ParameterFXChainShimmerReverbLP, 70); - #endif - // END setup FXRack + SetParameter (ParameterCompressorEnable, 1); }; bool CMiniDexed::Initialize (void) @@ -251,10 +263,18 @@ bool CMiniDexed::Initialize (void) m_pTG[i]->setBCController (99, 1, 0); m_pTG[i]->setATController (99, 1, 0); +#ifdef MIXING_CONSOLE_ENABLE + // setup the mixer so that it remains identical to the initial version of the synth + this->mixing_console_->setPan(i, this->m_nPan[i] / 127.0f); + float32_t sendRev = this->m_nFXSendLevel[i][MixerOutput::FX_PlateReverb] / 99.0f; + this->mixing_console_->setSendLevel(i, MixerOutput::FX_PlateReverb, sendRev); + this->mixing_console_->setSendLevel(i, MixerOutput::MainOutput, 1.0f - sendRev); +#else tg_mixer->pan(i,mapfloat(m_nPan[i],0,127,0.0f,1.0f)); tg_mixer->gain(i,1.0f); reverb_send_mixer->pan(i,mapfloat(m_nPan[i],0,127,0.0f,1.0f)); reverb_send_mixer->gain(i,mapfloat(m_nReverbSend[i],0,99,0.0f,1.0f)); +#endif } if (m_PerformanceConfig.Load ()) @@ -468,13 +488,51 @@ void CMiniDexed::SetPan (unsigned nPan, unsigned nTG) assert (nTG < CConfig::ToneGenerators); m_nPan[nTG] = nPan; - + +#ifdef MIXING_CONSOLE_ENABLE + this->mixing_console_->setPan(nTG, mapfloat(nPan, 0, 127, 0.0f, 1.0f)); +#else tg_mixer->pan(nTG,mapfloat(nPan,0,127,0.0f,1.0f)); reverb_send_mixer->pan(nTG,mapfloat(nPan,0,127,0.0f,1.0f)); +#endif m_UI.ParameterChanged (); } +#ifdef MIXING_CONSOLE_ENABLE + +void CMiniDexed::setMixingConsoleSendLevel(unsigned nTG, MixerOutput fx, unsigned nFXSend) +{ + assert (nTG < CConfig::ToneGenerators); + nFXSend = constrain((int)nFXSend,0,99); + + this->m_nFXSendLevel[nTG][fx] = nFXSend; + this->mixing_console_->setSendLevel(nTG, fx, nFXSend / 99.0f); + + this->m_UI.ParameterChanged (); +} + +void CMiniDexed::setMixingConsoleReturnLevel(MixerOutput ret, MixerOutput fx, unsigned nFXReturn) +{ + assert (ret < (MixerOutput::kFXCount - 1)); + assert (fx < MixerOutput::kFXCount); + if(ret == fx) + { + nFXReturn = 0; + } + else + { + nFXReturn = constrain((int)nFXReturn,0,99); + } + + this->m_nFXReturnLevel[ret][fx] = nFXReturn; + this->mixing_console_->setReturnLevel(ret, fx, nFXReturn / 99.0f); + + this->m_UI.ParameterChanged (); +} + +#else + void CMiniDexed::SetReverbSend (unsigned nReverbSend, unsigned nTG) { nReverbSend=constrain((int)nReverbSend,0,99); @@ -487,6 +545,8 @@ void CMiniDexed::SetReverbSend (unsigned nReverbSend, unsigned nTG) m_UI.ParameterChanged (); } +#endif // MIXING_CONSOLE_ENABLE + void CMiniDexed::SetMasterTune (int nMasterTune, unsigned nTG) { nMasterTune=constrain((int)nMasterTune,-99,99); @@ -679,7 +739,11 @@ void CMiniDexed::ControllersRefresh (unsigned nTG) void CMiniDexed::SetParameter (TParameter Parameter, int nValue) { +#ifdef MIXING_CONSOLE_ENABLE + assert(this->mixing_console_); +#else assert (reverb); +#endif assert (Parameter < ParameterUnknown); m_nParameter[Parameter] = nValue; @@ -694,283 +758,279 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue) } break; - case ParameterReverbEnable: - nValue=constrain((int)nValue,0,1); - m_FXSpinLock.Acquire (); - reverb->set_bypass (!nValue); - m_FXSpinLock.Release (); - break; - - case ParameterReverbSize: - nValue=constrain((int)nValue,0,99); - m_FXSpinLock.Acquire (); - reverb->size (nValue / 99.0f); - m_FXSpinLock.Release (); - break; - - case ParameterReverbHighDamp: - nValue=constrain((int)nValue,0,99); - m_FXSpinLock.Acquire (); - reverb->hidamp (nValue / 99.0f); - m_FXSpinLock.Release (); - break; - - case ParameterReverbLowDamp: - nValue=constrain((int)nValue,0,99); - m_FXSpinLock.Acquire (); - reverb->lodamp (nValue / 99.0f); - m_FXSpinLock.Release (); - break; - - case ParameterReverbLowPass: - nValue=constrain((int)nValue,0,99); - m_FXSpinLock.Acquire (); - reverb->lowpass (nValue / 99.0f); - m_FXSpinLock.Release (); - break; - - case ParameterReverbDiffusion: - nValue=constrain((int)nValue,0,99); - m_FXSpinLock.Acquire (); - reverb->diffusion (nValue / 99.0f); - m_FXSpinLock.Release (); - break; - - case ParameterReverbLevel: - nValue=constrain((int)nValue,0,99); - m_FXSpinLock.Acquire (); - reverb->level (nValue / 99.0f); - m_FXSpinLock.Release (); - break; - - // BEGIN FXChain parameters - #ifdef FXRACK_ENABLE - case ParameterFXChainEnable: +#ifdef MIXING_CONSOLE_ENABLE + // Tube parameters + case ParameterFXTubeEnable: nValue = constrain((int)nValue, 0, 1); this->m_FXSpinLock.Acquire(); - this->fx_rack->setEnable(!!nValue); + this->mixing_console_->getTube()->setMute(!nValue); this->m_FXSpinLock.Release(); break; - case ParameterFXChainWet: + case ParameterFXTubeOverdrive: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->setWetLevel(nValue / 99.0f); + this->mixing_console_->getTube()->setOverdrive(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - // FXChain > Tube parameters - case ParameterFXChainTubeEnable: + // Chorus parameters + case ParameterFXChorusEnable: nValue = constrain((int)nValue, 0, 1); this->m_FXSpinLock.Acquire(); - this->fx_rack->getTube()->setEnable(!!nValue); + this->mixing_console_->getChorus()->setMute(!nValue); this->m_FXSpinLock.Release(); break; - case ParameterFXChainTubeWet: + case ParameterFXChorusRate: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getTube()->setWetLevel(nValue / 99.0f); + this->mixing_console_->getChorus()->setRate(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainTubeOverdrive: + case ParameterFXChorusDepth: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getTube()->setOverdrive(nValue / 99.0f); + this->mixing_console_->getChorus()->setDepth(nValue / 9.9f); this->m_FXSpinLock.Release(); break; - // FXChain > Chorus parameters - case ParameterFXChainChorusEnable: + // Flanger parameters + case ParameterFXFlangerEnable: nValue = constrain((int)nValue, 0, 1); this->m_FXSpinLock.Acquire(); - this->fx_rack->getChorus()->setEnable(!!nValue); + this->mixing_console_->getFlanger()->setMute(!nValue); this->m_FXSpinLock.Release(); break; - case ParameterFXChainChorusWet: + case ParameterFXFlangerRate: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getChorus()->setWetLevel(nValue / 99.0f); + this->mixing_console_->getFlanger()->setRate(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainChorusRate: + case ParameterFXFlangerDepth: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getChorus()->setRate(nValue / 99.0f); + this->mixing_console_->getFlanger()->setDepth(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainChorusDepth: + case ParameterFXFlangerFeedback: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getChorus()->setDepth(nValue / 9.9f); + this->mixing_console_->getFlanger()->setFeedback(mapfloat(nValue, 0, 99, 0.0f, 0.97f)); this->m_FXSpinLock.Release(); break; - // FXChain > Flanger parameters - case ParameterFXChainFlangerEnable: + // Orbitone parameters + case ParameterFXOrbitoneEnable: nValue = constrain((int)nValue, 0, 1); this->m_FXSpinLock.Acquire(); - this->fx_rack->getFlanger()->setEnable(!!nValue); - this->m_FXSpinLock.Release(); - break; - case ParameterFXChainFlangerWet: - nValue = constrain((int)nValue, 0, 99); - this->m_FXSpinLock.Acquire(); - this->fx_rack->getFlanger()->setWetLevel(nValue / 99.0f); - this->m_FXSpinLock.Release(); - break; - case ParameterFXChainFlangerRate: - nValue = constrain((int)nValue, 0, 99); - this->m_FXSpinLock.Acquire(); - this->fx_rack->getFlanger()->setRate(nValue / 99.0f); + this->mixing_console_->getOrbitone()->setMute(!nValue); this->m_FXSpinLock.Release(); break; - case ParameterFXChainFlangerDepth: + case ParameterFXOrbitoneRate: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getFlanger()->setDepth(nValue / 99.0f); + this->mixing_console_->getOrbitone()->setRate(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainFlangerFeedback: + case ParameterFXOrbitoneDepth: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getFlanger()->setFeedback(mapfloat(nValue, 0, 99, 0.0f, 0.97f)); + this->mixing_console_->getOrbitone()->setDepth(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - // FXChain > Orbitone parameters - case ParameterFXChainOrbitoneEnable: + // Phaser parameters + case ParameterFXPhaserEnable: nValue = constrain((int)nValue, 0, 1); this->m_FXSpinLock.Acquire(); - this->fx_rack->getOrbitone()->setEnable(!!nValue); + this->mixing_console_->getPhaser()->setMute(!nValue); this->m_FXSpinLock.Release(); break; - case ParameterFXChainOrbitoneWet: + case ParameterFXPhaserRate: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getOrbitone()->setWetLevel(nValue / 99.0f); + this->mixing_console_->getPhaser()->setRate(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainOrbitoneRate: + case ParameterFXPhaserDepth: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getOrbitone()->setRate(nValue / 99.0f); + this->mixing_console_->getPhaser()->setDepth(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainOrbitoneDepth: + case ParameterFXPhaserFeedback: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getOrbitone()->setDepth(nValue / 99.0f); + this->mixing_console_->getPhaser()->setFeedback(mapfloat(nValue, 0, 99, 0.0f, 0.97f)); this->m_FXSpinLock.Release(); break; - - // FXChain > Phaser parameters - case ParameterFXChainPhaserEnable: - nValue = constrain((int)nValue, 0, 1); + case ParameterFXPhaserNbStages: + nValue = constrain((int)nValue, 2, MAX_NB_PHASES); this->m_FXSpinLock.Acquire(); - this->fx_rack->getPhaser()->setEnable(!!nValue); + this->mixing_console_->getPhaser()->setNbStages(nValue); this->m_FXSpinLock.Release(); break; - case ParameterFXChainPhaserWet: - nValue = constrain((int)nValue, 0, 99); + + // Delay parameters + case ParameterFXDelayEnable: + nValue = constrain((int)nValue, 0, 1); this->m_FXSpinLock.Acquire(); - this->fx_rack->getPhaser()->setWetLevel(nValue / 99.0f); + this->mixing_console_->getDelay()->setMute(!nValue); this->m_FXSpinLock.Release(); break; - case ParameterFXChainPhaserRate: + case ParameterFXDelayLeftDelayTime: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getPhaser()->setRate(nValue / 99.0f); + this->mixing_console_->getDelay()->setLeftDelayTime(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainPhaserDepth: + case ParameterFXDelayRightDelayTime: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getPhaser()->setDepth(nValue / 99.0f); + this->mixing_console_->getDelay()->setRightDelayTime(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainPhaserFeedback: + case ParameterFXDelayFeedback: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getPhaser()->setFeedback(mapfloat(nValue, 0, 99, 0.0f, 0.97f)); + this->mixing_console_->getDelay()->setFeedbak(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainPhaserNbStages: - nValue = constrain((int)nValue, 2, MAX_NB_PHASES); - this->m_FXSpinLock.Acquire(); - this->fx_rack->getPhaser()->setNbStages(nValue); - this->m_FXSpinLock.Release(); + + // AudioEffectPlateReverb parameters + case ParameterReverbEnable: + nValue=constrain((int)nValue,0,1); + m_FXSpinLock.Acquire (); + this->mixing_console_->getPlateReverb()->set_bypass (!nValue); + m_FXSpinLock.Release (); break; - // FXChain > Delay parameters - case ParameterFXChainDelayEnable: - nValue = constrain((int)nValue, 0, 1); - this->m_FXSpinLock.Acquire(); - this->fx_rack->getDelay()->setEnable(!!nValue); - this->m_FXSpinLock.Release(); + case ParameterReverbSize: + nValue=constrain((int)nValue,0,99); + m_FXSpinLock.Acquire (); + this->mixing_console_->getPlateReverb()->size (nValue / 99.0f); + m_FXSpinLock.Release (); break; - case ParameterFXChainDelayWet: - nValue = constrain((int)nValue, 0, 99); - this->m_FXSpinLock.Acquire(); - this->fx_rack->getDelay()->setWetLevel(nValue / 99.0f); - this->m_FXSpinLock.Release(); + + case ParameterReverbHighDamp: + nValue=constrain((int)nValue,0,99); + m_FXSpinLock.Acquire (); + this->mixing_console_->getPlateReverb()->hidamp (nValue / 99.0f); + m_FXSpinLock.Release (); break; - case ParameterFXChainDelayLeftDelayTime: - nValue = constrain((int)nValue, 0, 99); - this->m_FXSpinLock.Acquire(); - this->fx_rack->getDelay()->setLeftDelayTime(nValue / 99.0f); - this->m_FXSpinLock.Release(); + + case ParameterReverbLowDamp: + nValue=constrain((int)nValue,0,99); + m_FXSpinLock.Acquire (); + this->mixing_console_->getPlateReverb()->lodamp (nValue / 99.0f); + m_FXSpinLock.Release (); break; - case ParameterFXChainDelayRightDelayTime: - nValue = constrain((int)nValue, 0, 99); - this->m_FXSpinLock.Acquire(); - this->fx_rack->getDelay()->setRightDelayTime(nValue / 99.0f); - this->m_FXSpinLock.Release(); + + case ParameterReverbLowPass: + nValue=constrain((int)nValue,0,99); + m_FXSpinLock.Acquire (); + this->mixing_console_->getPlateReverb()->lowpass (nValue / 99.0f); + m_FXSpinLock.Release (); break; - case ParameterFXChainDelayFeedback: - nValue = constrain((int)nValue, 0, 99); - this->m_FXSpinLock.Acquire(); - this->fx_rack->getDelay()->setFeedbak(nValue / 99.0f); - this->m_FXSpinLock.Release(); + + case ParameterReverbDiffusion: + nValue=constrain((int)nValue,0,99); + m_FXSpinLock.Acquire (); + this->mixing_console_->getPlateReverb()->diffusion (nValue / 99.0f); + m_FXSpinLock.Release (); break; - - // FXChain > ShimmerReverb parameters - case ParameterFXChainShimmerReverbEnable: + + case ParameterReverbLevel: + nValue=constrain((int)nValue,0,99); + m_FXSpinLock.Acquire (); + this->mixing_console_->getPlateReverb()->level (nValue / 99.0f); + m_FXSpinLock.Release (); + break; + + // ShimmerReverb parameters + case ParameterFXShimmerReverbEnable: nValue = constrain((int)nValue, 0, 1); this->m_FXSpinLock.Acquire(); - this->fx_rack->getShimmerReverb()->setEnable(!!nValue); + this->mixing_console_->getShimmerReverb()->setMute(!nValue); this->m_FXSpinLock.Release(); break; - case ParameterFXChainShimmerReverbWet: + case ParameterFXShimmerReverbInputGain: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getShimmerReverb()->setWetLevel(nValue / 99.0f); + this->mixing_console_->getShimmerReverb()->setInputGain(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainShimmerReverbInputGain: + case ParameterFXShimmerReverbTime: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getShimmerReverb()->setInputGain(nValue / 99.0f); + this->mixing_console_->getShimmerReverb()->setTime(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainShimmerReverbTime: + case ParameterFXShimmerReverbDiffusion: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getShimmerReverb()->setTime(nValue / 99.0f); + this->mixing_console_->getShimmerReverb()->setDiffusion(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainShimmerReverbDiffusion: + case ParameterFXShimmerReverbLP: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getShimmerReverb()->setDiffusion(nValue / 99.0f); + this->mixing_console_->getShimmerReverb()->setLP(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainShimmerReverbLP: - nValue = constrain((int)nValue, 0, 99); - this->m_FXSpinLock.Acquire(); - this->fx_rack->getShimmerReverb()->setLP(nValue / 99.0f); - this->m_FXSpinLock.Release(); + +#else + + case ParameterReverbEnable: + nValue=constrain((int)nValue,0,1); + m_FXSpinLock.Acquire (); + reverb->set_bypass (!nValue); + m_FXSpinLock.Release (); + break; + + case ParameterReverbSize: + nValue=constrain((int)nValue,0,99); + m_FXSpinLock.Acquire (); + reverb->size (nValue / 99.0f); + m_FXSpinLock.Release (); + break; + + case ParameterReverbHighDamp: + nValue=constrain((int)nValue,0,99); + m_FXSpinLock.Acquire (); + reverb->hidamp (nValue / 99.0f); + m_FXSpinLock.Release (); break; - #endif - // END FXChain parameters + + case ParameterReverbLowDamp: + nValue=constrain((int)nValue,0,99); + m_FXSpinLock.Acquire (); + reverb->lodamp (nValue / 99.0f); + m_FXSpinLock.Release (); + break; + + case ParameterReverbLowPass: + nValue=constrain((int)nValue,0,99); + m_FXSpinLock.Acquire (); + reverb->lowpass (nValue / 99.0f); + m_FXSpinLock.Release (); + break; + + case ParameterReverbDiffusion: + nValue=constrain((int)nValue,0,99); + m_FXSpinLock.Acquire (); + reverb->diffusion (nValue / 99.0f); + m_FXSpinLock.Release (); + break; + + case ParameterReverbLevel: + nValue=constrain((int)nValue,0,99); + m_FXSpinLock.Acquire (); + reverb->level (nValue / 99.0f); + m_FXSpinLock.Release (); + break; + +#endif default: assert (0); @@ -1029,7 +1089,19 @@ void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nT SetMIDIChannel ((uint8_t) nValue, nTG); break; +#ifdef MIXING_CONSOLE_ENABLE + case TGParameterMixingSendFXTube: this->setMixingConsoleSendLevel(nTG, MixerOutput::FX_Tube, nValue); break; + case TGParameterMixingSendFXChorus: this->setMixingConsoleSendLevel(nTG, MixerOutput::FX_Chorus, nValue); break; + case TGParameterMixingSendFXFlanger: this->setMixingConsoleSendLevel(nTG, MixerOutput::FX_Flanger, nValue); break; + case TGParameterMixingSendFXOrbittone: this->setMixingConsoleSendLevel(nTG, MixerOutput::FX_Orbitone, nValue); break; + case TGParameterMixingSendFXPhaser: this->setMixingConsoleSendLevel(nTG, MixerOutput::FX_Phaser, nValue); break; + case TGParameterMixingSendFXDelay: this->setMixingConsoleSendLevel(nTG, MixerOutput::FX_Delay, nValue); break; + case TGParameterMixingSendFXPlateReverb: this->setMixingConsoleSendLevel(nTG, MixerOutput::FX_PlateReverb, nValue); break; + case TGParameterMixingSendFXShimmerReverb: this->setMixingConsoleSendLevel(nTG, MixerOutput::FX_ShimmerReverb, nValue); break; + case TGParameterMixingSendFXMainOutput: this->setMixingConsoleSendLevel(nTG, MixerOutput::MainOutput, nValue); break; +#else case TGParameterReverbSend: SetReverbSend (nValue, nTG); break; +#endif // MIXING_CONSOLE_ENABLE default: assert (0); @@ -1051,7 +1123,9 @@ int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG) case TGParameterCutoff: return m_nCutoff[nTG]; case TGParameterResonance: return m_nResonance[nTG]; case TGParameterMIDIChannel: return m_nMIDIChannel[nTG]; +#ifndef MIXING_CONSOLE_ENABLE case TGParameterReverbSend: return m_nReverbSend[nTG]; +#endif // undef MIXING_CONSOLE_ENABLE case TGParameterPitchBendRange: return m_nPitchBendRange[nTG]; case TGParameterPitchBendStep: return m_nPitchBendStep[nTG]; case TGParameterPortamentoMode: return m_nPortamentoMode[nTG]; @@ -1234,6 +1308,53 @@ void CMiniDexed::ProcessSound (void) assert (CConfig::ToneGenerators == 8); +#ifdef MIXING_CONSOLE_ENABLE + + // // swap stereo channels if needed + uint8_t indexL = StereoChannels::Left; + uint8_t indexR = StereoChannels::Right; + if(this->m_bChannelsSwapped) + { + indexL = StereoChannels::Left; + indexR = StereoChannels::Right; + } + + // BEGIN TG mixing + float32_t tmp_float[nFrames * 2]; + int16_t tmp_int[nFrames * 2]; + + float32_t SampleBuffer[2][nFrames]; + + if(nMasterVolume > 0.0f) + { + for (uint8_t i = 0; i < CConfig::ToneGenerators; i++) + { + this->mixing_console_->setInputSampleBuffer(i, m_OutputLevel[i]); + } + + this->m_FXSpinLock.Acquire (); + this->mixing_console_->process(SampleBuffer[indexL], SampleBuffer[indexR]); + this->m_FXSpinLock.Release (); + + // Convert dual float array (left, right) to single int16 array (left/right) + this->nMasterVolume = constrain(this->nMasterVolume, 0.0f, 1.0f); + if(this->nMasterVolume == 1.0f) + { + memcpy(tmp_float, SampleBuffer[indexL], nFrames * sizeof(float32_t)); + memcpy(tmp_float + nFrames, SampleBuffer[indexR], nFrames * sizeof(float32_t)); + } + else // 0.0 < this->nMasterVolume < 1.0 + { + arm_scale_f32(SampleBuffer[indexL], this->nMasterVolume, tmp_float, nFrames); + arm_scale_f32(SampleBuffer[indexR], this->nMasterVolume, tmp_float + nFrames, nFrames); + } + arm_float_to_q15(tmp_float, tmp_int, nFrames * 2); + } + else + arm_fill_q15(0, tmp_int, nFrames * 2); + +#else + // swap stereo channels if needed uint8_t indexL=0, indexR=1; if (m_bChannelsSwapped) @@ -1246,7 +1367,7 @@ void CMiniDexed::ProcessSound (void) float32_t tmp_float[nFrames*2]; int16_t tmp_int[nFrames*2]; - if(nMasterVolume > 0.0) + if(nMasterVolume > 0.0f) { for (uint8_t i = 0; i < CConfig::ToneGenerators; i++) { @@ -1290,12 +1411,12 @@ void CMiniDexed::ProcessSound (void) // END adding reverb // BEGIN adding FXRack - #ifdef FXRACK_ENABLE - if(this->fx_rack->isEnable() && this->fx_rack->getWetLevel() > 0.0f) + #ifdef MIXING_CONSOLE_ENABLE + if(this->mixing_console_->isEnable() && this->mixing_console_->getWetLevel() > 0.0f) { this->m_FXSpinLock.Acquire(); - this->fx_rack->process(SampleBuffer[indexL], SampleBuffer[indexR], SampleBuffer[indexL], SampleBuffer[indexR], nFrames); + this->mixing_console_->process(SampleBuffer[indexL], SampleBuffer[indexR], SampleBuffer[indexL], SampleBuffer[indexR], nFrames); this->m_FXSpinLock.Release(); } @@ -1321,6 +1442,8 @@ void CMiniDexed::ProcessSound (void) else arm_fill_q15(0, tmp_int, nFrames * 2); +#endif + if (m_pSoundDevice->Write (tmp_int, sizeof(tmp_int)) != (int) sizeof(tmp_int)) { LOGERR ("Sound data dropped"); @@ -1376,8 +1499,15 @@ bool CMiniDexed::DoSavePerformance (void) m_PerformanceConfig.SetBreathControlTarget (m_nBreathControlTarget[nTG], nTG); m_PerformanceConfig.SetAftertouchRange (m_nAftertouchRange[nTG], nTG); m_PerformanceConfig.SetAftertouchTarget (m_nAftertouchTarget[nTG], nTG); - + +#ifdef MIXING_CONSOLE_ENABLE + for(size_t fx = 0; fx < MixerOutput::kFXCount; ++fx) + { + this->m_PerformanceConfig.SetFXSendLevel(nTG, static_cast(fx), this->m_nFXSendLevel[nTG][fx]); + } +#else m_PerformanceConfig.SetReverbSend (m_nReverbSend[nTG], nTG); +#endif } m_PerformanceConfig.SetCompressorEnable (!!m_nParameter[ParameterCompressorEnable]); @@ -1389,45 +1519,42 @@ bool CMiniDexed::DoSavePerformance (void) m_PerformanceConfig.SetReverbDiffusion (m_nParameter[ParameterReverbDiffusion]); m_PerformanceConfig.SetReverbLevel (m_nParameter[ParameterReverbLevel]); - // BEGIN FXRack parameters - #ifdef FXRACK_ENABLE - this->m_PerformanceConfig.SetFXChainEnable(!!this->m_nParameter[ParameterFXChainEnable]); - this->m_PerformanceConfig.SetFXChainWet(this->m_nParameter[ParameterFXChainWet]); - this->m_PerformanceConfig.SetFXChainTubeEnable(!!this->m_nParameter[ParameterFXChainTubeEnable]); - this->m_PerformanceConfig.SetFXChainTubeWet(this->m_nParameter[ParameterFXChainTubeWet]); - this->m_PerformanceConfig.SetFXChainTubeOverdrive(this->m_nParameter[ParameterFXChainTubeOverdrive]); - this->m_PerformanceConfig.SetFXChainChorusEnable(!!this->m_nParameter[ParameterFXChainChorusEnable]); - this->m_PerformanceConfig.SetFXChainChorusWet(this->m_nParameter[ParameterFXChainChorusWet]); - this->m_PerformanceConfig.SetFXChainChorusRate(this->m_nParameter[ParameterFXChainChorusRate]); - this->m_PerformanceConfig.SetFXChainChorusDepth(this->m_nParameter[ParameterFXChainChorusDepth]); - this->m_PerformanceConfig.SetFXChainFlangerEnable(!!this->m_nParameter[ParameterFXChainFlangerEnable]); - this->m_PerformanceConfig.SetFXChainFlangerWet(this->m_nParameter[ParameterFXChainFlangerWet]); - this->m_PerformanceConfig.SetFXChainFlangerRate(this->m_nParameter[ParameterFXChainFlangerRate]); - this->m_PerformanceConfig.SetFXChainFlangerDepth(this->m_nParameter[ParameterFXChainFlangerDepth]); - this->m_PerformanceConfig.SetFXChainFlangerFeedback(this->m_nParameter[ParameterFXChainFlangerFeedback]); - this->m_PerformanceConfig.SetFXChainOrbitoneEnable(!!this->m_nParameter[ParameterFXChainOrbitoneEnable]); - this->m_PerformanceConfig.SetFXChainOrbitoneWet(this->m_nParameter[ParameterFXChainOrbitoneWet]); - this->m_PerformanceConfig.SetFXChainOrbitoneRate(this->m_nParameter[ParameterFXChainOrbitoneRate]); - this->m_PerformanceConfig.SetFXChainOrbitoneDepth(this->m_nParameter[ParameterFXChainOrbitoneDepth]); - this->m_PerformanceConfig.SetFXChainPhaserEnable(!!this->m_nParameter[ParameterFXChainPhaserEnable]); - this->m_PerformanceConfig.SetFXChainPhaserWet(this->m_nParameter[ParameterFXChainPhaserWet]); - this->m_PerformanceConfig.SetFXChainPhaserRate(this->m_nParameter[ParameterFXChainPhaserRate]); - this->m_PerformanceConfig.SetFXChainPhaserDepth(this->m_nParameter[ParameterFXChainPhaserDepth]); - this->m_PerformanceConfig.SetFXChainPhaserFeedback(this->m_nParameter[ParameterFXChainPhaserFeedback]); - this->m_PerformanceConfig.SetFXChainPhaserNbStages(this->m_nParameter[ParameterFXChainPhaserNbStages]); - this->m_PerformanceConfig.SetFXChainDelayEnable(!!this->m_nParameter[ParameterFXChainDelayEnable]); - this->m_PerformanceConfig.SetFXChainDelayWet(this->m_nParameter[ParameterFXChainDelayWet]); - this->m_PerformanceConfig.SetFXChainDelayLeftDelayTime(this->m_nParameter[ParameterFXChainDelayLeftDelayTime]); - this->m_PerformanceConfig.SetFXChainDelayRightDelayTime(this->m_nParameter[ParameterFXChainDelayRightDelayTime]); - this->m_PerformanceConfig.SetFXChainDelayFeedback(this->m_nParameter[ParameterFXChainDelayFeedback]); - this->m_PerformanceConfig.SetFXChainShimmerReverbEnable(!!this->m_nParameter[ParameterFXChainShimmerReverbEnable]); - this->m_PerformanceConfig.SetFXChainShimmerReverbWet(this->m_nParameter[ParameterFXChainShimmerReverbWet]); - this->m_PerformanceConfig.SetFXChainShimmerReverbInputGain(this->m_nParameter[ParameterFXChainShimmerReverbInputGain]); - this->m_PerformanceConfig.SetFXChainShimmerReverbTime(this->m_nParameter[ParameterFXChainShimmerReverbTime]); - this->m_PerformanceConfig.SetFXChainShimmerReverbDiffusion(this->m_nParameter[ParameterFXChainShimmerReverbDiffusion]); - this->m_PerformanceConfig.SetFXChainShimmerReverbLP(this->m_nParameter[ParameterFXChainShimmerReverbLP]); - #endif - // END FXRack parameters +#ifdef MIXING_CONSOLE_ENABLE + this->m_PerformanceConfig.SetFXTubeEnable(!!this->m_nParameter[ParameterFXTubeEnable]); + this->m_PerformanceConfig.SetFXTubeOverdrive(this->m_nParameter[ParameterFXTubeOverdrive]); + this->m_PerformanceConfig.SetFXChorusEnable(!!this->m_nParameter[ParameterFXChorusEnable]); + this->m_PerformanceConfig.SetFXChorusRate(this->m_nParameter[ParameterFXChorusRate]); + this->m_PerformanceConfig.SetFXChorusDepth(this->m_nParameter[ParameterFXChorusDepth]); + this->m_PerformanceConfig.SetFXFlangerEnable(!!this->m_nParameter[ParameterFXFlangerEnable]); + this->m_PerformanceConfig.SetFXFlangerRate(this->m_nParameter[ParameterFXFlangerRate]); + this->m_PerformanceConfig.SetFXFlangerDepth(this->m_nParameter[ParameterFXFlangerDepth]); + this->m_PerformanceConfig.SetFXFlangerFeedback(this->m_nParameter[ParameterFXFlangerFeedback]); + this->m_PerformanceConfig.SetFXOrbitoneEnable(!!this->m_nParameter[ParameterFXOrbitoneEnable]); + this->m_PerformanceConfig.SetFXOrbitoneRate(this->m_nParameter[ParameterFXOrbitoneRate]); + this->m_PerformanceConfig.SetFXOrbitoneDepth(this->m_nParameter[ParameterFXOrbitoneDepth]); + this->m_PerformanceConfig.SetFXPhaserEnable(!!this->m_nParameter[ParameterFXPhaserEnable]); + this->m_PerformanceConfig.SetFXPhaserRate(this->m_nParameter[ParameterFXPhaserRate]); + this->m_PerformanceConfig.SetFXPhaserDepth(this->m_nParameter[ParameterFXPhaserDepth]); + this->m_PerformanceConfig.SetFXPhaserFeedback(this->m_nParameter[ParameterFXPhaserFeedback]); + this->m_PerformanceConfig.SetFXPhaserNbStages(this->m_nParameter[ParameterFXPhaserNbStages]); + this->m_PerformanceConfig.SetFXDelayEnable(!!this->m_nParameter[ParameterFXDelayEnable]); + this->m_PerformanceConfig.SetFXDelayLeftDelayTime(this->m_nParameter[ParameterFXDelayLeftDelayTime]); + this->m_PerformanceConfig.SetFXDelayRightDelayTime(this->m_nParameter[ParameterFXDelayRightDelayTime]); + this->m_PerformanceConfig.SetFXDelayFeedback(this->m_nParameter[ParameterFXDelayFeedback]); + this->m_PerformanceConfig.SetFXShimmerReverbEnable(!!this->m_nParameter[ParameterFXShimmerReverbEnable]); + this->m_PerformanceConfig.SetFXShimmerReverbInputGain(this->m_nParameter[ParameterFXShimmerReverbInputGain]); + this->m_PerformanceConfig.SetFXShimmerReverbTime(this->m_nParameter[ParameterFXShimmerReverbTime]); + this->m_PerformanceConfig.SetFXShimmerReverbDiffusion(this->m_nParameter[ParameterFXShimmerReverbDiffusion]); + this->m_PerformanceConfig.SetFXShimmerReverbLP(this->m_nParameter[ParameterFXShimmerReverbLP]); + + for(size_t ret = 0; ret < (MixerOutput::kFXCount - 1); ++ret) + { + for(size_t fx = 0; fx < MixerOutput::kFXCount; ++fx) + { + this->m_PerformanceConfig.SetFXReturnLevel(static_cast(ret), static_cast(fx), this->m_nFXReturnLevel[ret][fx]); + } + } +#endif if(m_bSaveAsDeault) { @@ -1768,93 +1895,88 @@ bool CMiniDexed::DoSavePerformanceNewFile (void) void CMiniDexed::LoadPerformanceParameters(void) { for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) - { - - BankSelectLSB (m_PerformanceConfig.GetBankNumber (nTG), nTG); - ProgramChange (m_PerformanceConfig.GetVoiceNumber (nTG), nTG); - SetMIDIChannel (m_PerformanceConfig.GetMIDIChannel (nTG), nTG); - SetVolume (m_PerformanceConfig.GetVolume (nTG), nTG); - SetPan (m_PerformanceConfig.GetPan (nTG), nTG); - SetMasterTune (m_PerformanceConfig.GetDetune (nTG), nTG); - SetCutoff (m_PerformanceConfig.GetCutoff (nTG), nTG); - SetResonance (m_PerformanceConfig.GetResonance (nTG), nTG); - setPitchbendRange (m_PerformanceConfig.GetPitchBendRange (nTG), nTG); - setPitchbendStep (m_PerformanceConfig.GetPitchBendStep (nTG), nTG); - setPortamentoMode (m_PerformanceConfig.GetPortamentoMode (nTG), nTG); - setPortamentoGlissando (m_PerformanceConfig.GetPortamentoGlissando (nTG), nTG); - setPortamentoTime (m_PerformanceConfig.GetPortamentoTime (nTG), nTG); - - m_nNoteLimitLow[nTG] = m_PerformanceConfig.GetNoteLimitLow (nTG); - m_nNoteLimitHigh[nTG] = m_PerformanceConfig.GetNoteLimitHigh (nTG); - m_nNoteShift[nTG] = m_PerformanceConfig.GetNoteShift (nTG); - - if(m_PerformanceConfig.VoiceDataFilled(nTG)) - { - uint8_t* tVoiceData = m_PerformanceConfig.GetVoiceDataFromTxt(nTG); - m_pTG[nTG]->loadVoiceParameters(tVoiceData); - } - setMonoMode(m_PerformanceConfig.GetMonoMode(nTG) ? 1 : 0, nTG); - SetReverbSend (m_PerformanceConfig.GetReverbSend (nTG), nTG); - - setModWheelRange (m_PerformanceConfig.GetModulationWheelRange (nTG), nTG); - setModWheelTarget (m_PerformanceConfig.GetModulationWheelTarget (nTG), nTG); - setFootControllerRange (m_PerformanceConfig.GetFootControlRange (nTG), nTG); - setFootControllerTarget (m_PerformanceConfig.GetFootControlTarget (nTG), nTG); - setBreathControllerRange (m_PerformanceConfig.GetBreathControlRange (nTG), nTG); - setBreathControllerTarget (m_PerformanceConfig.GetBreathControlTarget (nTG), nTG); - setAftertouchRange (m_PerformanceConfig.GetAftertouchRange (nTG), nTG); - setAftertouchTarget (m_PerformanceConfig.GetAftertouchTarget (nTG), nTG); - + { + BankSelectLSB (m_PerformanceConfig.GetBankNumber (nTG), nTG); + ProgramChange (m_PerformanceConfig.GetVoiceNumber (nTG), nTG); + SetMIDIChannel (m_PerformanceConfig.GetMIDIChannel (nTG), nTG); + SetVolume (m_PerformanceConfig.GetVolume (nTG), nTG); + SetPan (m_PerformanceConfig.GetPan (nTG), nTG); + SetMasterTune (m_PerformanceConfig.GetDetune (nTG), nTG); + SetCutoff (m_PerformanceConfig.GetCutoff (nTG), nTG); + SetResonance (m_PerformanceConfig.GetResonance (nTG), nTG); + setPitchbendRange (m_PerformanceConfig.GetPitchBendRange (nTG), nTG); + setPitchbendStep (m_PerformanceConfig.GetPitchBendStep (nTG), nTG); + setPortamentoMode (m_PerformanceConfig.GetPortamentoMode (nTG), nTG); + setPortamentoGlissando (m_PerformanceConfig.GetPortamentoGlissando (nTG), nTG); + setPortamentoTime (m_PerformanceConfig.GetPortamentoTime (nTG), nTG); + + m_nNoteLimitLow[nTG] = m_PerformanceConfig.GetNoteLimitLow (nTG); + m_nNoteLimitHigh[nTG] = m_PerformanceConfig.GetNoteLimitHigh (nTG); + m_nNoteShift[nTG] = m_PerformanceConfig.GetNoteShift (nTG); + + if(m_PerformanceConfig.VoiceDataFilled(nTG)) + { + uint8_t* tVoiceData = m_PerformanceConfig.GetVoiceDataFromTxt(nTG); + m_pTG[nTG]->loadVoiceParameters(tVoiceData); } + setMonoMode(m_PerformanceConfig.GetMonoMode(nTG) ? 1 : 0, nTG); - // Effects - SetParameter (ParameterCompressorEnable, m_PerformanceConfig.GetCompressorEnable () ? 1 : 0); - SetParameter (ParameterReverbEnable, m_PerformanceConfig.GetReverbEnable () ? 1 : 0); - SetParameter (ParameterReverbSize, m_PerformanceConfig.GetReverbSize ()); - SetParameter (ParameterReverbHighDamp, m_PerformanceConfig.GetReverbHighDamp ()); - SetParameter (ParameterReverbLowDamp, m_PerformanceConfig.GetReverbLowDamp ()); - SetParameter (ParameterReverbLowPass, m_PerformanceConfig.GetReverbLowPass ()); - SetParameter (ParameterReverbDiffusion, m_PerformanceConfig.GetReverbDiffusion ()); - SetParameter (ParameterReverbLevel, m_PerformanceConfig.GetReverbLevel ()); - - #ifdef FXRACK_ENABLE - this->SetParameter(ParameterFXChainEnable, this->m_PerformanceConfig.GetFXChainEnable()); - this->SetParameter(ParameterFXChainWet, this->m_PerformanceConfig.GetFXChainWet()); - this->SetParameter(ParameterFXChainTubeEnable, this->m_PerformanceConfig.GetFXChainTubeEnable()); - this->SetParameter(ParameterFXChainTubeWet, this->m_PerformanceConfig.GetFXChainTubeWet()); - this->SetParameter(ParameterFXChainTubeOverdrive, this->m_PerformanceConfig.GetFXChainTubeOverdrive()); - this->SetParameter(ParameterFXChainChorusEnable, this->m_PerformanceConfig.GetFXChainChorusEnable()); - this->SetParameter(ParameterFXChainChorusWet, this->m_PerformanceConfig.GetFXChainChorusWet()); - this->SetParameter(ParameterFXChainChorusRate, this->m_PerformanceConfig.GetFXChainChorusRate()); - this->SetParameter(ParameterFXChainChorusDepth, this->m_PerformanceConfig.GetFXChainChorusDepth()); - this->SetParameter(ParameterFXChainFlangerEnable, this->m_PerformanceConfig.GetFXChainFlangerEnable()); - this->SetParameter(ParameterFXChainFlangerWet, this->m_PerformanceConfig.GetFXChainFlangerWet()); - this->SetParameter(ParameterFXChainFlangerRate, this->m_PerformanceConfig.GetFXChainFlangerRate()); - this->SetParameter(ParameterFXChainFlangerDepth, this->m_PerformanceConfig.GetFXChainFlangerDepth()); - this->SetParameter(ParameterFXChainFlangerFeedback, this->m_PerformanceConfig.GetFXChainFlangerFeedback()); - this->SetParameter(ParameterFXChainOrbitoneEnable, this->m_PerformanceConfig.GetFXChainOrbitoneEnable()); - this->SetParameter(ParameterFXChainOrbitoneWet, this->m_PerformanceConfig.GetFXChainOrbitoneWet()); - this->SetParameter(ParameterFXChainOrbitoneRate, this->m_PerformanceConfig.GetFXChainOrbitoneRate()); - this->SetParameter(ParameterFXChainOrbitoneDepth, this->m_PerformanceConfig.GetFXChainOrbitoneDepth()); - this->SetParameter(ParameterFXChainPhaserEnable, this->m_PerformanceConfig.GetFXChainPhaserEnable()); - this->SetParameter(ParameterFXChainPhaserWet, this->m_PerformanceConfig.GetFXChainPhaserWet()); - this->SetParameter(ParameterFXChainPhaserRate, this->m_PerformanceConfig.GetFXChainPhaserRate()); - this->SetParameter(ParameterFXChainPhaserDepth, this->m_PerformanceConfig.GetFXChainPhaserDepth()); - this->SetParameter(ParameterFXChainPhaserFeedback, this->m_PerformanceConfig.GetFXChainPhaserFeedback()); - this->SetParameter(ParameterFXChainPhaserNbStages, this->m_PerformanceConfig.GetFXChainPhaserNbStages()); - this->SetParameter(ParameterFXChainDelayEnable, this->m_PerformanceConfig.GetFXChainDelayEnable()); - this->SetParameter(ParameterFXChainDelayWet, this->m_PerformanceConfig.GetFXChainDelayWet()); - this->SetParameter(ParameterFXChainDelayLeftDelayTime, this->m_PerformanceConfig.GetFXChainDelayLeftDelayTime()); - this->SetParameter(ParameterFXChainDelayRightDelayTime, this->m_PerformanceConfig.GetFXChainDelayRightDelayTime()); - this->SetParameter(ParameterFXChainDelayFeedback, this->m_PerformanceConfig.GetFXChainDelayFeedback()); - this->SetParameter(ParameterFXChainShimmerReverbEnable, this->m_PerformanceConfig.GetFXChainShimmerReverbEnable()); - this->SetParameter(ParameterFXChainShimmerReverbWet, this->m_PerformanceConfig.GetFXChainShimmerReverbWet()); - this->SetParameter(ParameterFXChainShimmerReverbInputGain, this->m_PerformanceConfig.GetFXChainShimmerReverbInputGain()); - this->SetParameter(ParameterFXChainShimmerReverbTime, this->m_PerformanceConfig.GetFXChainShimmerReverbTime()); - this->SetParameter(ParameterFXChainShimmerReverbDiffusion, this->m_PerformanceConfig.GetFXChainShimmerReverbDiffusion()); - this->SetParameter(ParameterFXChainShimmerReverbLP, this->m_PerformanceConfig.GetFXChainShimmerReverbLP()); - #endif +#ifdef MIXING_CONSOLE_ENABLE + for(size_t fx = 0; fx < MixerOutput::kFXCount; ++fx) + { + this->setMixingConsoleSendLevel(nTG, static_cast(fx), this->m_PerformanceConfig.GetFXSendLevel(nTG, static_cast(fx))); + } +#else + SetReverbSend (m_PerformanceConfig.GetReverbSend (nTG), nTG); +#endif + + setModWheelRange (m_PerformanceConfig.GetModulationWheelRange (nTG), nTG); + setModWheelTarget (m_PerformanceConfig.GetModulationWheelTarget (nTG), nTG); + setFootControllerRange (m_PerformanceConfig.GetFootControlRange (nTG), nTG); + setFootControllerTarget (m_PerformanceConfig.GetFootControlTarget (nTG), nTG); + setBreathControllerRange (m_PerformanceConfig.GetBreathControlRange (nTG), nTG); + setBreathControllerTarget (m_PerformanceConfig.GetBreathControlTarget (nTG), nTG); + setAftertouchRange (m_PerformanceConfig.GetAftertouchRange (nTG), nTG); + setAftertouchTarget (m_PerformanceConfig.GetAftertouchTarget (nTG), nTG); + } + +#ifdef MIXING_CONSOLE_ENABLE + this->SetParameter(ParameterFXTubeEnable, this->m_PerformanceConfig.GetFXTubeEnable()); + this->SetParameter(ParameterFXTubeOverdrive, this->m_PerformanceConfig.GetFXTubeOverdrive()); + this->SetParameter(ParameterFXChorusEnable, this->m_PerformanceConfig.GetFXChorusEnable()); + this->SetParameter(ParameterFXChorusRate, this->m_PerformanceConfig.GetFXChorusRate()); + this->SetParameter(ParameterFXChorusDepth, this->m_PerformanceConfig.GetFXChorusDepth()); + this->SetParameter(ParameterFXFlangerEnable, this->m_PerformanceConfig.GetFXFlangerEnable()); + this->SetParameter(ParameterFXFlangerRate, this->m_PerformanceConfig.GetFXFlangerRate()); + this->SetParameter(ParameterFXFlangerDepth, this->m_PerformanceConfig.GetFXFlangerDepth()); + this->SetParameter(ParameterFXFlangerFeedback, this->m_PerformanceConfig.GetFXFlangerFeedback()); + this->SetParameter(ParameterFXOrbitoneEnable, this->m_PerformanceConfig.GetFXOrbitoneEnable()); + this->SetParameter(ParameterFXOrbitoneRate, this->m_PerformanceConfig.GetFXOrbitoneRate()); + this->SetParameter(ParameterFXOrbitoneDepth, this->m_PerformanceConfig.GetFXOrbitoneDepth()); + this->SetParameter(ParameterFXPhaserEnable, this->m_PerformanceConfig.GetFXPhaserEnable()); + this->SetParameter(ParameterFXPhaserRate, this->m_PerformanceConfig.GetFXPhaserRate()); + this->SetParameter(ParameterFXPhaserDepth, this->m_PerformanceConfig.GetFXPhaserDepth()); + this->SetParameter(ParameterFXPhaserFeedback, this->m_PerformanceConfig.GetFXPhaserFeedback()); + this->SetParameter(ParameterFXPhaserNbStages, this->m_PerformanceConfig.GetFXPhaserNbStages()); + this->SetParameter(ParameterFXDelayEnable, this->m_PerformanceConfig.GetFXDelayEnable()); + this->SetParameter(ParameterFXDelayLeftDelayTime, this->m_PerformanceConfig.GetFXDelayLeftDelayTime()); + this->SetParameter(ParameterFXDelayRightDelayTime, this->m_PerformanceConfig.GetFXDelayRightDelayTime()); + this->SetParameter(ParameterFXDelayFeedback, this->m_PerformanceConfig.GetFXDelayFeedback()); + this->SetParameter(ParameterFXShimmerReverbEnable, this->m_PerformanceConfig.GetFXShimmerReverbEnable()); + this->SetParameter(ParameterFXShimmerReverbInputGain, this->m_PerformanceConfig.GetFXShimmerReverbInputGain()); + this->SetParameter(ParameterFXShimmerReverbTime, this->m_PerformanceConfig.GetFXShimmerReverbTime()); + this->SetParameter(ParameterFXShimmerReverbDiffusion, this->m_PerformanceConfig.GetFXShimmerReverbDiffusion()); + this->SetParameter(ParameterFXShimmerReverbLP, this->m_PerformanceConfig.GetFXShimmerReverbLP()); + + for(size_t ret = 0; ret < (MixerOutput::kFXCount - 1); ++ret) + { + for(size_t fx = 0; fx < MixerOutput::kFXCount; ++fx) + { + this->setMixingConsoleReturnLevel(static_cast(ret), static_cast(fx), this->m_PerformanceConfig.GetFXReturnLevel(static_cast(ret), static_cast(fx))); + } + } +#endif } std::string CMiniDexed::GetNewPerformanceDefaultName(void) diff --git a/src/minidexed.h b/src/minidexed.h index 194c0ea..badd84b 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -45,8 +45,10 @@ #include "effect_platervbstereo.h" #include "effect_compressor.h" -#ifdef FXRACK_ENABLE -#include "fx_rack.h" +#ifdef MIXING_CONSOLE_ENABLE +#include "mixing_console.h" + +typedef MixingConsole Mixer; #endif class CMiniDexed @@ -91,7 +93,12 @@ public: void setBreathController (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 +#endif void setMonoMode(uint8_t mono, uint8_t nTG); void setPitchbendRange(uint8_t range, uint8_t nTG); @@ -140,60 +147,124 @@ public: ParameterReverbDiffusion, ParameterReverbLevel, - // BEGIN FXRack global parameters definition - #ifdef FXRACK_ENABLE - // FXChain parameters - ParameterFXChainEnable, - ParameterFXChainWet, - - // FXChain > Tube parameters - ParameterFXChainTubeEnable, - ParameterFXChainTubeWet, - ParameterFXChainTubeOverdrive, - - // FXChain > Chorus parameters - ParameterFXChainChorusEnable, - ParameterFXChainChorusWet, - ParameterFXChainChorusRate, - ParameterFXChainChorusDepth, + #ifdef MIXING_CONSOLE_ENABLE + // BEGIN FX global parameters definition + // Tube parameters + ParameterFXTubeEnable, + ParameterFXTubeOverdrive, + + // Chorus parameters + ParameterFXChorusEnable, + ParameterFXChorusRate, + ParameterFXChorusDepth, - // FXChain > Flanger parameters - ParameterFXChainFlangerEnable, - ParameterFXChainFlangerWet, - ParameterFXChainFlangerRate, - ParameterFXChainFlangerDepth, - ParameterFXChainFlangerFeedback, - - // FXChain > Orbitone parameters - ParameterFXChainOrbitoneEnable, - ParameterFXChainOrbitoneWet, - ParameterFXChainOrbitoneRate, - ParameterFXChainOrbitoneDepth, - - // FXChain > Phaser parameters - ParameterFXChainPhaserEnable, - ParameterFXChainPhaserWet, - ParameterFXChainPhaserRate, - ParameterFXChainPhaserDepth, - ParameterFXChainPhaserFeedback, - ParameterFXChainPhaserNbStages, - - // FXChain > Delay parameters - ParameterFXChainDelayEnable, - ParameterFXChainDelayWet, - ParameterFXChainDelayLeftDelayTime, - ParameterFXChainDelayRightDelayTime, - ParameterFXChainDelayFeedback, - - // FXChain > ShimmerReverb parameters - ParameterFXChainShimmerReverbEnable, - ParameterFXChainShimmerReverbWet, - ParameterFXChainShimmerReverbInputGain, - ParameterFXChainShimmerReverbTime, - ParameterFXChainShimmerReverbDiffusion, - ParameterFXChainShimmerReverbLP, - #endif - // END FXRack global parameters definition + // Flanger parameters + ParameterFXFlangerEnable, + ParameterFXFlangerRate, + ParameterFXFlangerDepth, + ParameterFXFlangerFeedback, + + // Orbitone parameters + ParameterFXOrbitoneEnable, + ParameterFXOrbitoneRate, + ParameterFXOrbitoneDepth, + + // Phaser parameters + ParameterFXPhaserEnable, + ParameterFXPhaserRate, + ParameterFXPhaserDepth, + ParameterFXPhaserFeedback, + ParameterFXPhaserNbStages, + + // Delay parameters + ParameterFXDelayEnable, + ParameterFXDelayLeftDelayTime, + ParameterFXDelayRightDelayTime, + ParameterFXDelayFeedback, + ParameterFXDelayFlutterRate, + ParameterFXDelayFlutterAmount, + + // ShimmerReverb parameters + ParameterFXShimmerReverbEnable, + ParameterFXShimmerReverbInputGain, + ParameterFXShimmerReverbTime, + ParameterFXShimmerReverbDiffusion, + ParameterFXShimmerReverbLP, + + // Tube Return parameters + ParameterFXTube_ChorusReturn, + ParameterFXTube_FlangerReturn, + ParameterFXTube_OrbitoneReturn, + ParameterFXTube_PhaserReturn, + ParameterFXTube_DelayReturn, + ParameterFXTube_ReverbReturn, + ParameterFXTube_ShimmerReturn, + + // 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 }; @@ -217,7 +288,9 @@ public: TGParameterCutoff, TGParameterResonance, TGParameterMIDIChannel, +#ifndef MIXING_CONSOLE_ENABLE TGParameterReverbSend, +#endif // undef MIXING_CONSOLE_ENABLE TGParameterPitchBendRange, TGParameterPitchBendStep, TGParameterPortamentoMode, @@ -245,6 +318,18 @@ public: TGParameterATAmplitude, TGParameterATEGBias, +#ifdef MIXING_CONSOLE_ENABLE + TGParameterMixingSendFXTube, + TGParameterMixingSendFXChorus, + TGParameterMixingSendFXFlanger, + TGParameterMixingSendFXOrbittone, + TGParameterMixingSendFXPhaser, + TGParameterMixingSendFXDelay, + TGParameterMixingSendFXPlateReverb, + TGParameterMixingSendFXShimmerReverb, + TGParameterMixingSendFXMainOutput, +#endif // MIXING_CONSOLE_ENABLE + TGParameterUnknown }; @@ -315,8 +400,13 @@ private: unsigned m_nNoteLimitHigh[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]; - +#endif + uint8_t m_nRawVoiceData[156]; @@ -345,15 +435,16 @@ private: CPerformanceTimer m_GetChunkTimer; bool m_bProfileEnabled; +#ifdef MIXING_CONSOLE_ENABLE + Mixer* mixing_console_; +#else AudioEffectPlateReverb* reverb; AudioStereoMixer* tg_mixer; AudioStereoMixer* reverb_send_mixer; +#endif CSpinLock m_FXSpinLock; -#ifdef FXRACK_ENABLE - FXRack* fx_rack; -#endif bool m_bSavePerformance; bool m_bSavePerformanceNewFile; diff --git a/src/mixing_console.cpp b/src/mixing_console.cpp new file mode 100644 index 0000000..a65c10d --- /dev/null +++ b/src/mixing_console.cpp @@ -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 . +// + +// Implementation of the MixingConsole class defined in mixing_console.h + +#include "mixing_console.h" + +template +MixingConsole::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(sampling_rate); + this->fx_[MixerOutput::FX_Chorus] = this->chorus_ = new FXUnit2(sampling_rate); + this->fx_[MixerOutput::FX_Flanger] = this->flanger_ = new FXUnit2(sampling_rate); + this->fx_[MixerOutput::FX_Orbitone] = this->orbitone_ = new FXUnit2(sampling_rate); + this->fx_[MixerOutput::FX_Phaser] = this->phaser_ = new FXUnit2(sampling_rate); + this->fx_[MixerOutput::FX_Delay] = this->delay_ = new FXUnit2(sampling_rate); + this->fx_[MixerOutput::FX_PlateReverb] = this->plate_reverb_ = new FXUnit2(sampling_rate); + this->fx_[MixerOutput::FX_ShimmerReverb] = this->shimmer_reverb_ = new FXUnit2(sampling_rate); + this->fx_[MixerOutput::MainOutput] = this->dry_ = new FXUnit2(sampling_rate); + + this->init(); +} + +template +MixingConsole::~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 +void MixingConsole::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 +void MixingConsole::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 +void MixingConsole::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 +void MixingConsole::setSendLevel(size_t in, MixerOutput fx, float32_t lvl) +{ + assert(in < nb_inputs); + assert(fx < kFXCount); + + this->setLevel(in, fx, lvl); +} + +template +void MixingConsole::setInputSample(size_t in, float32_t sampleL, float32_t sampleR) +{ + assert(in < nb_inputs); + + this->setSample(in, sampleL, sampleR); +} + +template +void MixingConsole::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 +void MixingConsole::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 +void MixingConsole::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 +void MixingConsole::setReturnSample(MixerOutput ret, float32_t sampleL, float32_t sampleR) +{ + assert(ret < (kFXCount - 1)); + + this->setSample(nb_inputs + ret, sampleL, sampleR); +} + +// Global section + +template +void MixingConsole::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 +void MixingConsole::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 +FXElement* MixingConsole::getFX(size_t fx) +{ + assert(fx < MixerOutput::kFXCount); + return this->fx_[fx]; +} + +template +FXUnit2* MixingConsole::getTube() +{ + return this->tube_; +} + +template +FXUnit2* MixingConsole::getChorus() +{ + return this->chorus_; +} + +template +FXUnit2* MixingConsole::getFlanger() +{ + return this->flanger_; +} + +template +FXUnit2* MixingConsole::getOrbitone() +{ + return this->orbitone_; +} + +template +FXUnit2* MixingConsole::getPhaser() +{ + return this->phaser_; +} + +template +FXUnit2* MixingConsole::getDelay() +{ + return this->delay_; +} + +template +FXUnit2* MixingConsole::getPlateReverb() +{ + return this->plate_reverb_; +} + +template +FXUnit2* MixingConsole::getShimmerReverb() +{ + return this->shimmer_reverb_; +} + +template +FXUnit2* MixingConsole::getDry() +{ + return this->dry_; +} + +// Processing + +template +void MixingConsole::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 +void MixingConsole::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(i), 0.0f, 0.0f); + } +} + +template +void MixingConsole::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(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 +void MixingConsole::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; + } +} \ No newline at end of file diff --git a/src/mixing_console.h b/src/mixing_console.h new file mode 100644 index 0000000..2bbb1d5 --- /dev/null +++ b/src/mixing_console.h @@ -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 . +// +#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 +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* getTube(); + FXUnit2* getChorus(); + FXUnit2* getFlanger(); + FXUnit2* getOrbitone(); + FXUnit2* getPhaser(); + FXUnit2* getDelay(); + FXUnit2* getPlateReverb(); + FXUnit2* getShimmerReverb(); + FXUnit2* 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_; + FXUnit2* chorus_; + FXUnit2* flanger_; + FXUnit2* orbitone_; + FXUnit2* phaser_; + FXUnit2* delay_; + FXUnit2* plate_reverb_; + FXUnit2* shimmer_reverb_; + FXUnit2* dry_; +}; + +#include "mixing_console.cpp" diff --git a/src/mixing_console_constants.h b/src/mixing_console_constants.h new file mode 100644 index 0000000..03d4ada --- /dev/null +++ b/src/mixing_console_constants.h @@ -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 +std::string_view getMixerOutputString(T enum_val) +{ + static constexpr std::array(T::kFXCount)> names + { + "Tube", + "Chorus", + "Flanger", + "Orbitone", + "Phaser", + "Delay", + "PlateReverb", + "ShimmerReverb", + "MainOutput" + }; + static_assert(names.size() == static_cast(T::kFXCount),"Enum class and string array size mismatch"); + return names[static_cast(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"); +} diff --git a/src/performanceconfig.cpp b/src/performanceconfig.cpp index 419d389..f75f2c0 100644 --- a/src/performanceconfig.cpp +++ b/src/performanceconfig.cpp @@ -24,6 +24,7 @@ #include "mididevice.h" #include #include +#include CPerformanceConfig::CPerformanceConfig (FATFS *pFileSystem) : m_Properties ("performance.ini", pFileSystem) @@ -159,42 +160,58 @@ bool CPerformanceConfig::Load (void) m_nReverbDiffusion = m_Properties.GetNumber ("ReverbDiffusion", 65); m_nReverbLevel = m_Properties.GetNumber ("ReverbLevel", 99); -#ifdef ARM_ALLOW_MULTI_CORE - this->m_bFXChainEnable = this->m_Properties.GetNumber("FXChainEnable", 1); - this->m_nFXChainWet = this->m_Properties.GetNumber("FXChainWet", 99); - this->m_bFXChainTubeEnable = this->m_Properties.GetNumber("FXChainTubeEnable", 1); - this->m_nFXChainTubeWet = this->m_Properties.GetNumber("FXChainTubeWet", 50); - this->m_nFXChainTubeOverdrive = this->m_Properties.GetNumber("FXChainTubeOverdrive", 10); - this->m_bFXChainChorusEnable = this->m_Properties.GetNumber("FXChainChorusEnable", 1); - this->m_nFXChainChorusWet = this->m_Properties.GetNumber("FXChainChorusWet", 50); - this->m_nFXChainChorusRate = this->m_Properties.GetNumber("FXChainChorusRate", 50); - this->m_nFXChainChorusDepth = this->m_Properties.GetNumber("FXChainChorusDepth", 50); - this->m_bFXChainFlangerEnable = this->m_Properties.GetNumber("FXChainFlangerEnable", 1); - this->m_nFXChainFlangerWet = this->m_Properties.GetNumber("FXChainFlangerWet", 50); - this->m_nFXChainFlangerRate = this->m_Properties.GetNumber("FXChainFlangerRate", 15); - this->m_nFXChainFlangerDepth = this->m_Properties.GetNumber("FXChainFlangerDepth", 10); - this->m_nFXChainFlangerFeedback = this->m_Properties.GetNumber("FXChainFlangerFeedback", 20); - this->m_bFXChainOrbitoneEnable = this->m_Properties.GetNumber("FXChainOrbitoneEnable", 1); - this->m_nFXChainOrbitoneWet = this->m_Properties.GetNumber("FXChainOrbitoneWet", 80); - this->m_nFXChainOrbitoneRate = this->m_Properties.GetNumber("FXChainOrbitoneRate", 40); - this->m_nFXChainOrbitoneDepth = this->m_Properties.GetNumber("FXChainOrbitoneDepth", 50); - this->m_bFXChainPhaserEnable = this->m_Properties.GetNumber("FXChainPhaserEnable", 1); - this->m_nFXChainPhaserWet = this->m_Properties.GetNumber("FXChainPhaserWet", 50); - this->m_nFXChainPhaserRate = this->m_Properties.GetNumber("FXChainPhaserRate", 5); - this->m_nFXChainPhaserDepth = this->m_Properties.GetNumber("FXChainPhaserDepth", 99); - this->m_nFXChainPhaserFeedback = this->m_Properties.GetNumber("FXChainPhaserFeedback", 50); - this->m_nFXChainPhaserNbStages = this->m_Properties.GetNumber("FXChainPhaserNbStages", 12); - this->m_bFXChainDelayEnable = this->m_Properties.GetNumber("FXChainDelayEnable", 1); - this->m_nFXChainDelayWet = this->m_Properties.GetNumber("FXChainDelayWet", 50); - this->m_nFXChainDelayLeftDelayTime = this->m_Properties.GetNumber("FXChainDelayLeftDelayTime", 15); - this->m_nFXChainDelayRightDelayTime = this->m_Properties.GetNumber("FXChainDelayRightDelayTime", 22); - this->m_nFXChainDelayFeedback = this->m_Properties.GetNumber("FXChainDelayFeedback", 35); - this->m_bFXChainShimmerReverbEnable = this->m_Properties.GetNumber("FXChainShimmerReverbEnable", 1); - this->m_nFXChainShimmerReverbWet = this->m_Properties.GetNumber("FXChainShimmerReverbWet", 70); - this->m_nFXChainShimmerReverbInputGain = this->m_Properties.GetNumber("FXChainShimmerReverbInputGain", 30); - this->m_nFXChainShimmerReverbTime = this->m_Properties.GetNumber("FXChainShimmerReverbTime", 30); - this->m_nFXChainShimmerReverbDiffusion = this->m_Properties.GetNumber("FXChainShimmerReverbDiffusion", 30); - this->m_nFXChainShimmerReverbLP = this->m_Properties.GetNumber("FXChainShimmerReverbLP", 99); +#ifdef MIXING_CONSOLE_ENABLE + this->m_bFXTubeEnable = this->m_Properties.GetNumber("FXTubeEnable", 1); + this->m_nFXTubeOverdrive = this->m_Properties.GetNumber("FXTubeOverdrive", 10); + this->m_bFXChorusEnable = this->m_Properties.GetNumber("FXChorusEnable", 1); + this->m_nFXChorusRate = this->m_Properties.GetNumber("FXChorusRate", 50); + this->m_nFXChorusDepth = this->m_Properties.GetNumber("FXChorusDepth", 50); + this->m_bFXFlangerEnable = this->m_Properties.GetNumber("FXFlangerEnable", 1); + this->m_nFXFlangerRate = this->m_Properties.GetNumber("FXFlangerRate", 15); + this->m_nFXFlangerDepth = this->m_Properties.GetNumber("FXFlangerDepth", 10); + this->m_nFXFlangerFeedback = this->m_Properties.GetNumber("FXFlangerFeedback", 20); + this->m_bFXOrbitoneEnable = this->m_Properties.GetNumber("FXOrbitoneEnable", 1); + this->m_nFXOrbitoneRate = this->m_Properties.GetNumber("FXOrbitoneRate", 40); + this->m_nFXOrbitoneDepth = this->m_Properties.GetNumber("FXOrbitoneDepth", 50); + this->m_bFXPhaserEnable = this->m_Properties.GetNumber("FXPhaserEnable", 1); + this->m_nFXPhaserRate = this->m_Properties.GetNumber("FXPhaserRate", 5); + this->m_nFXPhaserDepth = this->m_Properties.GetNumber("FXPhaserDepth", 99); + this->m_nFXPhaserFeedback = this->m_Properties.GetNumber("FXPhaserFeedback", 50); + this->m_nFXPhaserNbStages = this->m_Properties.GetNumber("FXPhaserNbStages", 12); + this->m_bFXDelayEnable = this->m_Properties.GetNumber("FXDelayEnable", 1); + this->m_nFXDelayLeftDelayTime = this->m_Properties.GetNumber("FXDelayLeftDelayTime", 15); + this->m_nFXDelayRightDelayTime = this->m_Properties.GetNumber("FXDelayRightDelayTime", 22); + this->m_nFXDelayFeedback = this->m_Properties.GetNumber("FXDelayFeedback", 35); + this->m_bFXShimmerReverbEnable = this->m_Properties.GetNumber("FXShimmerReverbEnable", 1); + this->m_nFXShimmerReverbInputGain = this->m_Properties.GetNumber("FXShimmerReverbInputGain", 30); + this->m_nFXShimmerReverbTime = this->m_Properties.GetNumber("FXShimmerReverbTime", 30); + this->m_nFXShimmerReverbDiffusion = this->m_Properties.GetNumber("FXShimmerReverbDiffusion", 30); + this->m_nFXShimmerReverbLP = this->m_Properties.GetNumber("FXShimmerReverbLP", 99); + + for(unsigned in = 0; in < CConfig::ToneGenerators; ++in) + { + for(unsigned fx = 0; fx < MixerOutput::kFXCount; ++fx) + { + std::ostringstream oss("FXSendLevel_"); + oss << in << "_x_" << fx; + unsigned defaultLevel = 0; + 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 return bResult; @@ -315,42 +332,53 @@ bool CPerformanceConfig::Save (void) m_Properties.SetNumber ("ReverbDiffusion", m_nReverbDiffusion); m_Properties.SetNumber ("ReverbLevel", m_nReverbLevel); -#ifdef ARM_ALLOW_MULTI_CORE - this->m_Properties.SetNumber("FXChainEnable", m_bFXChainEnable ? 1 : 0); - this->m_Properties.SetNumber("FXChainWet", m_nFXChainWet); - this->m_Properties.SetNumber("FXChainTubeEnable", m_bFXChainTubeEnable ? 1 : 0); - this->m_Properties.SetNumber("FXChainTubeWet", m_nFXChainTubeWet); - this->m_Properties.SetNumber("FXChainTubeOverdrive", m_nFXChainTubeOverdrive); - this->m_Properties.SetNumber("FXChainChorusEnable", m_bFXChainChorusEnable ? 1 : 0); - this->m_Properties.SetNumber("FXChainChorusWet", m_nFXChainChorusWet); - this->m_Properties.SetNumber("FXChainChorusRate", m_nFXChainChorusRate); - this->m_Properties.SetNumber("FXChainChorusDepth", m_nFXChainChorusDepth); - this->m_Properties.SetNumber("FXChainFlangerEnable", m_bFXChainFlangerEnable ? 1 : 0); - this->m_Properties.SetNumber("FXChainFlangerWet", m_nFXChainFlangerWet); - this->m_Properties.SetNumber("FXChainFlangerRate", m_nFXChainFlangerRate); - this->m_Properties.SetNumber("FXChainFlangerDepth", m_nFXChainFlangerDepth); - this->m_Properties.SetNumber("FXChainFlangerFeedback", m_nFXChainFlangerFeedback); - this->m_Properties.SetNumber("FXChainOrbitoneEnable", m_bFXChainOrbitoneEnable ? 1 : 0); - this->m_Properties.SetNumber("FXChainOrbitoneWet", m_nFXChainOrbitoneWet); - this->m_Properties.SetNumber("FXChainOrbitoneRate", m_nFXChainOrbitoneRate); - this->m_Properties.SetNumber("FXChainOrbitoneDepth", m_nFXChainOrbitoneDepth); - this->m_Properties.SetNumber("FXChainPhaserEnable", m_bFXChainPhaserEnable ? 1 : 0); - this->m_Properties.SetNumber("FXChainPhaserWet", m_nFXChainPhaserWet); - this->m_Properties.SetNumber("FXChainPhaserRate", m_nFXChainPhaserRate); - this->m_Properties.SetNumber("FXChainPhaserDepth", m_nFXChainPhaserDepth); - this->m_Properties.SetNumber("FXChainPhaserFeedback", m_nFXChainPhaserFeedback); - this->m_Properties.SetNumber("FXChainPhaserNbStages", m_nFXChainPhaserNbStages); - this->m_Properties.SetNumber("FXChainDelayEnable", m_bFXChainDelayEnable ? 1 : 0); - this->m_Properties.SetNumber("FXChainDelayWet", m_nFXChainDelayWet); - this->m_Properties.SetNumber("FXChainDelayLeftDelayTime", m_nFXChainDelayLeftDelayTime); - this->m_Properties.SetNumber("FXChainDelayRightDelayTime", m_nFXChainDelayRightDelayTime); - this->m_Properties.SetNumber("FXChainDelayFeedback", m_nFXChainDelayFeedback); - this->m_Properties.SetNumber("FXChainShimmerReverbEnable", m_bFXChainShimmerReverbEnable ? 1 : 0); - this->m_Properties.SetNumber("FXChainShimmerReverbWet", m_nFXChainShimmerReverbWet); - this->m_Properties.SetNumber("FXChainShimmerReverbInputGain", m_nFXChainShimmerReverbInputGain); - this->m_Properties.SetNumber("FXChainShimmerReverbTime", m_nFXChainShimmerReverbTime); - this->m_Properties.SetNumber("FXChainShimmerReverbDiffusion", m_nFXChainShimmerReverbDiffusion); - this->m_Properties.SetNumber("FXChainShimmerReverbLP", m_nFXChainShimmerReverbLP); +#ifdef MIXING_CONSOLE_ENABLE + this->m_Properties.SetNumber("FXTubeEnable", m_bFXTubeEnable ? 1 : 0); + this->m_Properties.SetNumber("FXTubeOverdrive", m_nFXTubeOverdrive); + this->m_Properties.SetNumber("FXChorusEnable", m_bFXChorusEnable ? 1 : 0); + this->m_Properties.SetNumber("FXChorusRate", m_nFXChorusRate); + this->m_Properties.SetNumber("FXChorusDepth", m_nFXChorusDepth); + this->m_Properties.SetNumber("FXFlangerEnable", m_bFXFlangerEnable ? 1 : 0); + this->m_Properties.SetNumber("FXFlangerRate", m_nFXFlangerRate); + this->m_Properties.SetNumber("FXFlangerDepth", m_nFXFlangerDepth); + this->m_Properties.SetNumber("FXFlangerFeedback", m_nFXFlangerFeedback); + this->m_Properties.SetNumber("FXOrbitoneEnable", m_bFXOrbitoneEnable ? 1 : 0); + this->m_Properties.SetNumber("FXOrbitoneRate", m_nFXOrbitoneRate); + this->m_Properties.SetNumber("FXOrbitoneDepth", m_nFXOrbitoneDepth); + this->m_Properties.SetNumber("FXPhaserEnable", m_bFXPhaserEnable ? 1 : 0); + this->m_Properties.SetNumber("FXPhaserRate", m_nFXPhaserRate); + this->m_Properties.SetNumber("FXPhaserDepth", m_nFXPhaserDepth); + this->m_Properties.SetNumber("FXPhaserFeedback", m_nFXPhaserFeedback); + this->m_Properties.SetNumber("FXPhaserNbStages", m_nFXPhaserNbStages); + this->m_Properties.SetNumber("FXDelayEnable", m_bFXDelayEnable ? 1 : 0); + this->m_Properties.SetNumber("FXDelayLeftDelayTime", m_nFXDelayLeftDelayTime); + this->m_Properties.SetNumber("FXDelayRightDelayTime", m_nFXDelayRightDelayTime); + this->m_Properties.SetNumber("FXDelayFeedback", m_nFXDelayFeedback); + this->m_Properties.SetNumber("FXShimmerReverbEnable", m_bFXShimmerReverbEnable ? 1 : 0); + this->m_Properties.SetNumber("FXShimmerReverbInputGain", m_nFXShimmerReverbInputGain); + this->m_Properties.SetNumber("FXShimmerReverbTime", m_nFXShimmerReverbTime); + this->m_Properties.SetNumber("FXShimmerReverbDiffusion", m_nFXShimmerReverbDiffusion); + this->m_Properties.SetNumber("FXShimmerReverbLP", m_nFXShimmerReverbLP); + + for(unsigned in = 0; in < CConfig::ToneGenerators; ++in) + { + for(unsigned fx = 0; fx < MixerOutput::kFXCount; ++fx) + { + std::ostringstream oss("FXSendLevel_"); + oss << in << "_x_" << fx; + this->m_Properties.SetNumber(oss.str().c_str(), this->m_nFXSendLevel[in][fx]); + } + } + + 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 return m_Properties.Save (); @@ -1000,355 +1028,294 @@ bool CPerformanceConfig::DeletePerformance(unsigned nID) return bOK; } -#ifdef ARM_ALLOW_MULTI_CORE -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; -} +#ifdef MIXING_CONSOLE_ENABLE -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 diff --git a/src/performanceconfig.h b/src/performanceconfig.h index 4cd7790..d30ff39 100644 --- a/src/performanceconfig.h +++ b/src/performanceconfig.h @@ -24,6 +24,7 @@ #define _performanceconfig_h #include "config.h" +#include "mixing_console_constants.h" #include #include #define NUM_VOICE_PARAM 156 @@ -117,78 +118,64 @@ public: void SetReverbDiffusion (unsigned nValue); void SetReverbLevel (unsigned nValue); -#ifdef ARM_ALLOW_MULTI_CORE - bool GetFXChainEnable(void) const; - unsigned GetFXChainWet(void) const; - bool GetFXChainTubeEnable(void) const; - unsigned GetFXChainTubeWet(void) const; - unsigned GetFXChainTubeOverdrive(void) const; - bool GetFXChainChorusEnable(void) const; - unsigned GetFXChainChorusWet(void) const; - unsigned GetFXChainChorusRate(void) const; - unsigned GetFXChainChorusDepth(void) const; - bool GetFXChainFlangerEnable(void) const; - unsigned GetFXChainFlangerWet(void) const; - unsigned GetFXChainFlangerRate(void) const; - unsigned GetFXChainFlangerDepth(void) const; - unsigned GetFXChainFlangerFeedback(void) const; - bool GetFXChainOrbitoneEnable(void) const; - unsigned GetFXChainOrbitoneWet(void) const; - unsigned GetFXChainOrbitoneRate(void) const; - unsigned GetFXChainOrbitoneDepth(void) const; - bool GetFXChainPhaserEnable(void) const; - unsigned GetFXChainPhaserWet(void) const; - unsigned GetFXChainPhaserRate(void) const; - unsigned GetFXChainPhaserDepth(void) const; - unsigned GetFXChainPhaserFeedback(void) const; - unsigned GetFXChainPhaserNbStages(void) const; - bool GetFXChainDelayEnable(void) const; - unsigned GetFXChainDelayWet(void) const; - unsigned GetFXChainDelayLeftDelayTime(void) const; - unsigned GetFXChainDelayRightDelayTime(void) 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; +#ifdef MIXING_CONSOLE_ENABLE + bool GetFXTubeEnable(void) const; + unsigned GetFXTubeOverdrive(void) const; + bool GetFXChorusEnable(void) const; + unsigned GetFXChorusRate(void) const; + unsigned GetFXChorusDepth(void) const; + bool GetFXFlangerEnable(void) const; + unsigned GetFXFlangerRate(void) const; + unsigned GetFXFlangerDepth(void) const; + unsigned GetFXFlangerFeedback(void) const; + bool GetFXOrbitoneEnable(void) const; + unsigned GetFXOrbitoneRate(void) const; + unsigned GetFXOrbitoneDepth(void) const; + bool GetFXPhaserEnable(void) const; + unsigned GetFXPhaserRate(void) const; + unsigned GetFXPhaserDepth(void) const; + unsigned GetFXPhaserFeedback(void) const; + unsigned GetFXPhaserNbStages(void) const; + bool GetFXDelayEnable(void) const; + unsigned GetFXDelayLeftDelayTime(void) const; + unsigned GetFXDelayRightDelayTime(void) const; + unsigned GetFXDelayFeedback(void) const; + bool GetFXShimmerReverbEnable(void) const; + unsigned GetFXShimmerReverbInputGain(void) const; + unsigned GetFXShimmerReverbTime(void) const; + unsigned GetFXShimmerReverbDiffusion(void) const; + unsigned GetFXShimmerReverbLP(void) const; + unsigned GetFXSendLevel(unsigned in, MixerOutput fx) const; + unsigned GetFXReturnLevel(MixerOutput ret, MixerOutput fx) const; - void SetFXChainEnable(bool bValue); - void SetFXChainWet(unsigned nValue); - void SetFXChainTubeEnable(bool bValue); - void SetFXChainTubeWet(unsigned nValue); - void SetFXChainTubeOverdrive(unsigned nValue); - void SetFXChainChorusEnable(bool bValue); - void SetFXChainChorusWet(unsigned nValue); - void SetFXChainChorusRate(unsigned nValue); - void SetFXChainChorusDepth(unsigned nValue); - void SetFXChainFlangerEnable(bool bValue); - void SetFXChainFlangerWet(unsigned nValue); - void SetFXChainFlangerRate(unsigned nValue); - void SetFXChainFlangerDepth(unsigned nValue); - void SetFXChainFlangerFeedback(unsigned nValue); - void SetFXChainOrbitoneEnable(bool bValue); - void SetFXChainOrbitoneWet(unsigned nValue); - void SetFXChainOrbitoneRate(unsigned nValue); - void SetFXChainOrbitoneDepth(unsigned nValue); - void SetFXChainPhaserEnable(bool bValue); - void SetFXChainPhaserWet(unsigned nValue); - void SetFXChainPhaserRate(unsigned nValue); - void SetFXChainPhaserDepth(unsigned nValue); - void SetFXChainPhaserFeedback(unsigned nValue); - void SetFXChainPhaserNbStages(unsigned nValue); - void SetFXChainDelayEnable(unsigned nValue); - void SetFXChainDelayWet(unsigned nValue); - void SetFXChainDelayLeftDelayTime(unsigned nValue); - void SetFXChainDelayRightDelayTime(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); + void SetFXTubeEnable(bool bValue); + void SetFXTubeOverdrive(unsigned nValue); + void SetFXChorusEnable(bool bValue); + void SetFXChorusRate(unsigned nValue); + void SetFXChorusDepth(unsigned nValue); + void SetFXFlangerEnable(bool bValue); + void SetFXFlangerRate(unsigned nValue); + void SetFXFlangerDepth(unsigned nValue); + void SetFXFlangerFeedback(unsigned nValue); + void SetFXOrbitoneEnable(bool bValue); + void SetFXOrbitoneRate(unsigned nValue); + void SetFXOrbitoneDepth(unsigned nValue); + void SetFXPhaserEnable(bool bValue); + void SetFXPhaserRate(unsigned nValue); + void SetFXPhaserDepth(unsigned nValue); + void SetFXPhaserFeedback(unsigned nValue); + void SetFXPhaserNbStages(unsigned nValue); + void SetFXDelayEnable(unsigned nValue); + void SetFXDelayLeftDelayTime(unsigned nValue); + void SetFXDelayRightDelayTime(unsigned nValue); + void SetFXDelayFeedback(unsigned nValue); + void SetFXShimmerReverbEnable(unsigned nValue); + void SetFXShimmerReverbInputGain(unsigned nValue); + void SetFXShimmerReverbTime(unsigned nValue); + void SetFXShimmerReverbDiffusion(unsigned nValue); + void SetFXShimmerReverbLP(unsigned nValue); + void SetFXSendLevel(unsigned in, MixerOutput fx, unsigned nValue); + void SetFXReturnLevel(MixerOutput ret, MixerOutput fx, unsigned nValue); #endif bool VoiceDataFilled(unsigned nTG); @@ -258,42 +245,38 @@ private: unsigned m_nReverbDiffusion; unsigned m_nReverbLevel; -#ifdef ARM_ALLOW_MULTI_CORE - bool m_bFXChainEnable; - unsigned m_nFXChainWet; - bool m_bFXChainTubeEnable; - unsigned m_nFXChainTubeWet; - unsigned m_nFXChainTubeOverdrive; - bool m_bFXChainChorusEnable; - unsigned m_nFXChainChorusWet; - unsigned m_nFXChainChorusRate; - unsigned m_nFXChainChorusDepth; - bool m_bFXChainFlangerEnable; - unsigned m_nFXChainFlangerWet; - unsigned m_nFXChainFlangerRate; - unsigned m_nFXChainFlangerDepth; - unsigned m_nFXChainFlangerFeedback; - bool m_bFXChainOrbitoneEnable; - unsigned m_nFXChainOrbitoneWet; - unsigned m_nFXChainOrbitoneRate; - unsigned m_nFXChainOrbitoneDepth; - bool m_bFXChainPhaserEnable; - unsigned m_nFXChainPhaserWet; - unsigned m_nFXChainPhaserRate; - unsigned m_nFXChainPhaserDepth; - unsigned m_nFXChainPhaserFeedback; - unsigned m_nFXChainPhaserNbStages; - bool m_bFXChainDelayEnable; - unsigned m_nFXChainDelayWet; - unsigned m_nFXChainDelayLeftDelayTime; - unsigned m_nFXChainDelayRightDelayTime; - unsigned m_nFXChainDelayFeedback; - bool m_bFXChainShimmerReverbEnable; - unsigned m_nFXChainShimmerReverbWet; - unsigned m_nFXChainShimmerReverbInputGain; - unsigned m_nFXChainShimmerReverbTime; - unsigned m_nFXChainShimmerReverbDiffusion; - unsigned m_nFXChainShimmerReverbLP; +#ifdef MIXING_CONSOLE_ENABLE + bool m_bFXTubeEnable; + unsigned m_nFXTubeWet; + unsigned m_nFXTubeOverdrive; + bool m_bFXChorusEnable; + unsigned m_nFXChorusRate; + unsigned m_nFXChorusDepth; + bool m_bFXFlangerEnable; + unsigned m_nFXFlangerRate; + unsigned m_nFXFlangerDepth; + unsigned m_nFXFlangerFeedback; + bool m_bFXOrbitoneEnable; + unsigned m_nFXOrbitoneRate; + unsigned m_nFXOrbitoneDepth; + bool m_bFXPhaserEnable; + unsigned m_nFXPhaserRate; + unsigned m_nFXPhaserDepth; + unsigned m_nFXPhaserFeedback; + unsigned m_nFXPhaserNbStages; + bool m_bFXDelayEnable; + unsigned m_nFXDelayLeftDelayTime; + unsigned m_nFXDelayRightDelayTime; + unsigned m_nFXDelayFeedback; + bool m_bFXShimmerReverbEnable; + unsigned m_nFXShimmerReverbInputGain; + unsigned m_nFXShimmerReverbTime; + unsigned m_nFXShimmerReverbDiffusion; + unsigned m_nFXShimmerReverbLP; + + unsigned m_nFXSendLevel[CConfig::ToneGenerators][MixerOutput::kFXCount]; + unsigned m_nFXReturnLevel[MixerOutput::kFXCount - 1][MixerOutput::kFXCount]; + #endif }; diff --git a/src/test/Makefile b/src/test/Makefile index f8778a4..fec7d94 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,12 +1,16 @@ CXX := gcc # CXXFLAGS := -O2 CXXFLAGS := -g -DEFINES := -DCPU=x86 -INCLUDES := -I../../CMSIS_5/CMSIS/DSP/Include/ -I../../CMSIS_5/CMSIS/Core/Include/ +DEFINES := -DCPU=x86 -DDEBUG=1 +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) LD := gcc -LIBS := -lm -lstdc++ +LIBS := -lm -lstdc++ -lgtest -lpthread OBJS := \ fx.o \ @@ -19,15 +23,40 @@ OBJS := \ 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 \ 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 +../%.cpp: ../%.h + touch $@ + %.o: ../%.cpp $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ @@ -37,6 +66,9 @@ wavein.o: wavein.cpp waveout.o: waveout.cpp $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ +arm_functions.o: arm_functions.cpp + $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ + # # waveplay.o: waveplay.cpp # # $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ @@ -85,12 +117,21 @@ waveout.o: waveout.cpp # effect_platervbstereo.o: ../effect_platervbstereo.cpp # $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ +fxrack_test.cpp: ../mixing_console.h ../mixing_console.cpp + touch $@ + fxrack_test.o: fxrack_test.cpp $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ +all_tests.o: all_tests.cpp + $(CXX) $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $^ -o $@ + fxrack_test: $(OBJS) $(LD) $(OBJS) -o fxrack_test $(LIBS) +all_tests: $(OBJS2) + $(LD) $(OBJS2) -o all_tests $(LIBS) + clean: rm -f *.o fxrack_test diff --git a/src/test/MixerOutputTest.hpp b/src/test/MixerOutputTest.hpp new file mode 100644 index 0000000..ab01a0f --- /dev/null +++ b/src/test/MixerOutputTest.hpp @@ -0,0 +1,101 @@ +#pragma once + +#include + +#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); +} diff --git a/src/test/UIMenuTest.hpp b/src/test/UIMenuTest.hpp new file mode 100644 index 0000000..c3fbb14 --- /dev/null +++ b/src/test/UIMenuTest.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +#include "../uimenu.h" +#include "../minidexed.h" + +TEST(UIMenuTest, CountGlobalParams) +{ + size_t nb = CMiniDexed::ParameterUnknown; + EXPECT_EQ(nb, 156); +} \ No newline at end of file diff --git a/src/test/all_tests.cpp b/src/test/all_tests.cpp new file mode 100644 index 0000000..ff0454d --- /dev/null +++ b/src/test/all_tests.cpp @@ -0,0 +1,8 @@ +#include "MixerOutputTest.hpp" +#include "UIMenuTest.hpp" + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/src/test/arm_functions.cpp b/src/test/arm_functions.cpp new file mode 100644 index 0000000..2964f48 --- /dev/null +++ b/src/test/arm_functions.cpp @@ -0,0 +1,46 @@ +#include + +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]; +} \ No newline at end of file diff --git a/src/test/desktop.ini b/src/test/desktop.ini new file mode 100644 index 0000000..d957fd1 --- /dev/null +++ b/src/test/desktop.ini @@ -0,0 +1,4 @@ +[ViewState] +Mode= +Vid= +FolderType=Generic diff --git a/src/test/fxrack_test.cpp b/src/test/fxrack_test.cpp index b09b3a9..abd3e6f 100644 --- a/src/test/fxrack_test.cpp +++ b/src/test/fxrack_test.cpp @@ -1,6 +1,6 @@ #include "../fx_rack.h" - #include "../effect_platervbstereo.h" +#include "../mixing_console.h" #include #include @@ -23,19 +23,6 @@ random_device rd; mt19937 gen(rd()); uniform_real_distribution 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) { const unsigned nbRepeats = 4; @@ -227,7 +214,7 @@ enum FXSitch Flanger = 1 << 4, Delay = 1 << 5, Shimmer = 1 << 6, - kNbFX = 7 + _kFXCount = 7 }; int scenarii[] = @@ -413,9 +400,11 @@ void setupRack(unsigned& step, FXRack* rack) rack->getFlanger()->setFeedback(0.5f); rack->getDelay()->setWetLevel(0.6f); - rack->getDelay()->setLeftDelayTime(0.075f); - rack->getDelay()->setLeftDelayTime(0.05f); - rack->getDelay()->setFeedbak(0.5f); + rack->getDelay()->setLeftDelayTime(0.15f); + rack->getDelay()->setLeftDelayTime(0.2f); + rack->getDelay()->setFeedback(0.35f); + rack->getDelay()->setFlutterRate(0.15f); + rack->getDelay()->setFlutterAmount(0.75f); rack->getShimmerReverb()->setWetLevel(0.5f); rack->getShimmerReverb()->setInputGain(0.35f); @@ -435,7 +424,7 @@ void activateRackFXUnitScenario(unsigned& step, FXRack* rack, int scenario) rack->getShimmerReverb()->setEnable(Active(scenario, FXSitch::Shimmer)); } -void testReset(unsigned& step) +void testFXRackReset(unsigned& step) { FXRack *rack = new FXRack(44100.0f); rack->setEnable(true); @@ -463,9 +452,9 @@ void testReset(unsigned& step) delete rack; } -void testProcessing(unsigned& step) +void testFXRackProcessing(unsigned& step) { - const unsigned nbRepeats = 1; + const unsigned nbRepeats = 2; unsigned size; float32_t** samples = readWaveFile("test.wav", size); float32_t* sampleOutL = new float32_t[size * nbRepeats]; @@ -481,6 +470,7 @@ void testProcessing(unsigned& step) unsigned i = 0; while(true) { + rack->reset(); int fxSwitch = scenarii[i]; if(fxSwitch == -1) { @@ -497,9 +487,9 @@ void testProcessing(unsigned& step) rack->process(samples[0], samples[1], sampleOutL + i * size, sampleOutR + i * size, size); } - // stringstream ss; - // ss << "result " << name << ".wav"; - // saveWaveFile(ss.str(), sampleOutL, sampleOutR, nbRepeats * size, static_cast(FS), 16); + stringstream ss; + ss << "waves/result " << name << ".wav"; + saveWaveFile(ss.str(), sampleOutL, sampleOutR, nbRepeats * size, static_cast(FS), 16); cout << "done" << endl; @@ -515,16 +505,177 @@ void testProcessing(unsigned& step) 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(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() { unsigned step = 0; - testLFO(step); - testFlutter(step); - testSVF(step); - testPlateReverb(step); - testReset(step); - testProcessing(step); + // testLFO(step); + + // testFlutter(step); + + // testSVF(step); + + // testPlateReverb(step); + + // testFXRackReset(step); + // testFXRackProcessing(step); + + // testUnitMixingConsole(step); + testMixingConsole(step); return 0; } diff --git a/src/uimenu.cpp b/src/uimenu.cpp index f94f969..639fa6f 100644 --- a/src/uimenu.cpp +++ b/src/uimenu.cpp @@ -34,57 +34,70 @@ using namespace std; const CUIMenu::TMenuItem CUIMenu::s_MenuRoot[] = { - {"MiniDexed", MenuHandler, s_MainMenu}, + {"MiniDexed", MenuHandler, CUIMenu::s_MainMenu}, {0} }; // inserting menu items before "TG1" affect TGShortcutHandler() const CUIMenu::TMenuItem CUIMenu::s_MainMenu[] = { - {"TG1", MenuHandler, s_TGMenu, 0}, + {"TG1", MenuHandler, CUIMenu::s_TGMenu, 0}, #ifdef ARM_ALLOW_MULTI_CORE - {"TG2", MenuHandler, s_TGMenu, 1}, - {"TG3", MenuHandler, s_TGMenu, 2}, - {"TG4", MenuHandler, s_TGMenu, 3}, - {"TG5", MenuHandler, s_TGMenu, 4}, - {"TG6", MenuHandler, s_TGMenu, 5}, - {"TG7", MenuHandler, s_TGMenu, 6}, - {"TG8", MenuHandler, s_TGMenu, 7}, + {"TG2", MenuHandler, CUIMenu::s_TGMenu, 1}, + {"TG3", MenuHandler, CUIMenu::s_TGMenu, 2}, + {"TG4", MenuHandler, CUIMenu::s_TGMenu, 3}, + {"TG5", MenuHandler, CUIMenu::s_TGMenu, 4}, + {"TG6", MenuHandler, CUIMenu::s_TGMenu, 5}, + {"TG7", MenuHandler, CUIMenu::s_TGMenu, 6}, + {"TG8", MenuHandler, CUIMenu::s_TGMenu, 7}, #endif - {"Effects", MenuHandler, s_EffectsMenu}, - {"Performance", MenuHandler, s_PerformanceMenu}, + {"Effects", MenuHandler, CUIMenu::s_EffectsMenu}, + {"Performance", MenuHandler, CUIMenu::s_PerformanceMenu}, {0} }; const CUIMenu::TMenuItem CUIMenu::s_TGMenu[] = { - {"Voice", EditProgramNumber}, - {"Bank", EditVoiceBankNumber}, - {"Volume", EditTGParameter, 0, CMiniDexed::TGParameterVolume}, + {"Voice", EditProgramNumber}, + {"Bank", EditVoiceBankNumber}, + {"Volume", EditTGParameter, 0, CMiniDexed::TGParameterVolume}, #ifdef ARM_ALLOW_MULTI_CORE - {"Pan", EditTGParameter, 0, CMiniDexed::TGParameterPan}, + {"Pan", EditTGParameter, 0, CMiniDexed::TGParameterPan}, #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}, - {"Detune", EditTGParameter, 0, CMiniDexed::TGParameterMasterTune}, - {"Cutoff", EditTGParameter, 0, CMiniDexed::TGParameterCutoff}, - {"Resonance", EditTGParameter, 0, CMiniDexed::TGParameterResonance}, - {"Pitch Bend", MenuHandler, s_EditPitchBendMenu}, - {"Portamento", MenuHandler, s_EditPortamentoMenu}, - {"Poly/Mono", EditTGParameter, 0, CMiniDexed::TGParameterMonoMode}, - {"Modulation", MenuHandler, s_ModulationMenu}, - {"Channel", EditTGParameter, 0, CMiniDexed::TGParameterMIDIChannel}, - {"Edit Voice", MenuHandler, s_EditVoiceMenu}, +#endif + {"Detune", EditTGParameter, 0, CMiniDexed::TGParameterMasterTune}, + {"Cutoff", EditTGParameter, 0, CMiniDexed::TGParameterCutoff}, + {"Resonance", EditTGParameter, 0, CMiniDexed::TGParameterResonance}, + {"Pitch Bend", MenuHandler, CUIMenu::s_EditPitchBendMenu}, + {"Portamento", MenuHandler, CUIMenu::s_EditPortamentoMenu}, + {"Poly/Mono", EditTGParameter, 0, CMiniDexed::TGParameterMonoMode}, + {"Modulation", MenuHandler, CUIMenu::s_ModulationMenu}, + {"Channel", EditTGParameter, 0, CMiniDexed::TGParameterMIDIChannel}, + {"Edit Voice", MenuHandler, CUIMenu::s_EditVoiceMenu}, {0} }; 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 - {"Reverb", MenuHandler, s_ReverbMenu}, + {"Reverb", MenuHandler, CUIMenu::s_ReverbMenu}, #endif -#ifdef FXRACK_ENABLE - {"FXChain", MenuHandler, s_FXChainMenu}, #endif {0} }; @@ -106,10 +119,10 @@ const CUIMenu::TMenuItem CUIMenu::s_EditPortamentoMenu[] = const CUIMenu::TMenuItem CUIMenu::s_ModulationMenu[] = { - {"Mod. Wheel", MenuHandler, s_ModulationMenuParameters, CMiniDexed::TGParameterMWRange}, - {"Foot Control", MenuHandler, s_ModulationMenuParameters, CMiniDexed::TGParameterFCRange}, - {"Breath Control", MenuHandler, s_ModulationMenuParameters, CMiniDexed::TGParameterBCRange}, - {"Aftertouch", MenuHandler, s_ModulationMenuParameters, CMiniDexed::TGParameterATRange}, + {"Mod. Wheel", MenuHandler, CUIMenu::s_ModulationMenuParameters, CMiniDexed::TGParameterMWRange}, + {"Foot Control", MenuHandler, CUIMenu::s_ModulationMenuParameters, CMiniDexed::TGParameterFCRange}, + {"Breath Control", MenuHandler, CUIMenu::s_ModulationMenuParameters, CMiniDexed::TGParameterBCRange}, + {"Aftertouch", MenuHandler, CUIMenu::s_ModulationMenuParameters, CMiniDexed::TGParameterATRange}, {0} }; @@ -138,89 +151,177 @@ const CUIMenu::TMenuItem CUIMenu::s_ReverbMenu[] = #endif -#ifdef FXRACK_ENABLE +#ifdef MIXING_CONSOLE_ENABLE -const CUIMenu::TMenuItem CUIMenu::s_FXChainMenu[] = +const CUIMenu::TMenuItem CUIMenu::s_FXMenu[] = { - // FXChain - {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainEnable}, - {"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainWet}, + {"Tube", MenuHandler, CUIMenu::s_FXTube}, + {"Chorus", MenuHandler, CUIMenu::s_FXChorus}, + {"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}, - {"Chorus", MenuHandler, s_FXChainChorus}, - {"FlangR", MenuHandler, s_FXChainFlanger}, - {"Orb", MenuHandler, s_FXChainOrbitone}, - {"PhasR", MenuHandler, s_FXChainPhaser}, - {"Delay", MenuHandler, s_FXChainDelay}, - {"Shimmer", MenuHandler, s_FXChainShimmerReverb}, +const CUIMenu::TMenuItem CUIMenu::s_FXTube[] = +{ + {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeEnable}, + {"Overdrv", EditGlobalParameter, 0, CMiniDexed::ParameterFXTubeOverdrive}, {0} }; -const CUIMenu::TMenuItem CUIMenu::s_FXChainTube[] = +const CUIMenu::TMenuItem CUIMenu::s_FXChorus[] = { - {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainTubeEnable}, - {"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainTubeWet}, - {"Overdrv", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainTubeOverdrive}, + {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChorusEnable}, + {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXChorusRate}, + {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXChorusDepth}, {0} }; -const CUIMenu::TMenuItem CUIMenu::s_FXChainChorus[] = +const CUIMenu::TMenuItem CUIMenu::s_FXFlanger[] = { - {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainChorusEnable}, - {"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainChorusWet}, - {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainChorusRate}, - {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainChorusDepth}, + {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXFlangerEnable}, + {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXFlangerRate}, + {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXFlangerDepth}, + {"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXFlangerFeedback}, {0} }; -const CUIMenu::TMenuItem CUIMenu::s_FXChainFlanger[] = +const CUIMenu::TMenuItem CUIMenu::s_FXOrbitone[] = { - {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerEnable}, - {"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerWet}, - {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerRate}, - {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerDepth}, - {"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerFeedback}, + {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXOrbitoneEnable}, + {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXOrbitoneRate}, + {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXOrbitoneDepth}, {0} }; -const CUIMenu::TMenuItem CUIMenu::s_FXChainOrbitone[] = +const CUIMenu::TMenuItem CUIMenu::s_FXPhaser[] = { - {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainOrbitoneEnable}, - {"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainOrbitoneWet}, - {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainOrbitoneRate}, - {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainOrbitoneDepth}, + {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXPhaserEnable}, + {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXPhaserRate}, + {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXPhaserDepth}, + {"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXPhaserFeedback}, + {"Stages", EditGlobalParameter, 0, CMiniDexed::ParameterFXPhaserNbStages}, {0} }; -const CUIMenu::TMenuItem CUIMenu::s_FXChainPhaser[] = +const CUIMenu::TMenuItem CUIMenu::s_FXDelay[] = { - {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainPhaserEnable}, - {"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainPhaserWet}, - {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainPhaserRate}, - {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainPhaserDepth}, - {"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainPhaserFeedback}, - {"Stages", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainPhaserNbStages}, + {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXDelayEnable}, + {"L Delay", EditGlobalParameter, 0, CMiniDexed::ParameterFXDelayLeftDelayTime}, + {"R Delay", EditGlobalParameter, 0, CMiniDexed::ParameterFXDelayRightDelayTime}, + {"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXDelayFeedback}, + {"Flt Rte", EditGlobalParameter, 0, CMiniDexed::ParameterFXDelayFlutterRate}, + {"Flt Amt", EditGlobalParameter, 0, CMiniDexed::ParameterFXDelayFlutterAmount}, {0} }; -const CUIMenu::TMenuItem CUIMenu::s_FXChainDelay[] = +const CUIMenu::TMenuItem CUIMenu::s_FXShimmerReverb[] = { - {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainDelayEnable}, - {"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainDelayWet}, - {"L Delay", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainDelayLeftDelayTime}, - {"R Delay", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainDelayRightDelayTime}, - {"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainDelayFeedback}, + {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXShimmerReverbEnable}, + {"Gain", EditGlobalParameter, 0, CMiniDexed::ParameterFXShimmerReverbInputGain}, + {"Time", EditGlobalParameter, 0, CMiniDexed::ParameterFXShimmerReverbTime}, + {"Diffus", EditGlobalParameter, 0, CMiniDexed::ParameterFXShimmerReverbDiffusion}, + {"LowPass", EditGlobalParameter, 0, CMiniDexed::ParameterFXShimmerReverbLP}, {0} }; -const CUIMenu::TMenuItem CUIMenu::s_FXChainShimmerReverb[] = +const CUIMenu::TMenuItem CUIMenu::s_FXTubeReturn[] = { - {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbEnable}, - {"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbWet}, - {"Gain", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbInputGain}, - {"Time", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbTime}, - {"Diffus", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbDiffusion}, - {"LowPass", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainShimmerReverbLP}, + {"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}, + {"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} }; @@ -229,32 +330,32 @@ const CUIMenu::TMenuItem CUIMenu::s_FXChainShimmerReverb[] = // inserting menu items before "OP1" affect OPShortcutHandler() const CUIMenu::TMenuItem CUIMenu::s_EditVoiceMenu[] = { - {"OP1", MenuHandler, s_OperatorMenu, 0}, - {"OP2", MenuHandler, s_OperatorMenu, 1}, - {"OP3", MenuHandler, s_OperatorMenu, 2}, - {"OP4", MenuHandler, s_OperatorMenu, 3}, - {"OP5", MenuHandler, s_OperatorMenu, 4}, - {"OP6", MenuHandler, s_OperatorMenu, 5}, - {"Algorithm", EditVoiceParameter, 0, DEXED_ALGORITHM}, - {"Feedback", EditVoiceParameter, 0, DEXED_FEEDBACK}, - {"P EG Rate 1", EditVoiceParameter, 0, DEXED_PITCH_EG_R1}, - {"P EG Rate 2", EditVoiceParameter, 0, DEXED_PITCH_EG_R2}, - {"P EG Rate 3", EditVoiceParameter, 0, DEXED_PITCH_EG_R3}, - {"P EG Rate 4", EditVoiceParameter, 0, DEXED_PITCH_EG_R4}, - {"P EG Level 1",EditVoiceParameter, 0, DEXED_PITCH_EG_L1}, - {"P EG Level 2",EditVoiceParameter, 0, DEXED_PITCH_EG_L2}, - {"P EG Level 3",EditVoiceParameter, 0, DEXED_PITCH_EG_L3}, - {"P EG Level 4",EditVoiceParameter, 0, DEXED_PITCH_EG_L4}, - {"Osc Key Sync",EditVoiceParameter, 0, DEXED_OSC_KEY_SYNC}, - {"LFO Speed", EditVoiceParameter, 0, DEXED_LFO_SPEED}, - {"LFO Delay", EditVoiceParameter, 0, DEXED_LFO_DELAY}, - {"LFO PMD", EditVoiceParameter, 0, DEXED_LFO_PITCH_MOD_DEP}, - {"LFO AMD", EditVoiceParameter, 0, DEXED_LFO_AMP_MOD_DEP}, - {"LFO Sync", EditVoiceParameter, 0, DEXED_LFO_SYNC}, - {"LFO Wave", EditVoiceParameter, 0, DEXED_LFO_WAVE}, - {"P Mod Sens.", EditVoiceParameter, 0, DEXED_LFO_PITCH_MOD_SENS}, - {"Transpose", EditVoiceParameter, 0, DEXED_TRANSPOSE}, - {"Name", InputTxt,0 , 3}, + {"OP1", MenuHandler, CUIMenu::s_OperatorMenu, 0}, + {"OP2", MenuHandler, CUIMenu::s_OperatorMenu, 1}, + {"OP3", MenuHandler, CUIMenu::s_OperatorMenu, 2}, + {"OP4", MenuHandler, CUIMenu::s_OperatorMenu, 3}, + {"OP5", MenuHandler, CUIMenu::s_OperatorMenu, 4}, + {"OP6", MenuHandler, CUIMenu::s_OperatorMenu, 5}, + {"Algorithm", EditVoiceParameter, 0, DEXED_ALGORITHM}, + {"Feedback", EditVoiceParameter, 0, DEXED_FEEDBACK}, + {"P EG Rate 1", EditVoiceParameter, 0, DEXED_PITCH_EG_R1}, + {"P EG Rate 2", EditVoiceParameter, 0, DEXED_PITCH_EG_R2}, + {"P EG Rate 3", EditVoiceParameter, 0, DEXED_PITCH_EG_R3}, + {"P EG Rate 4", EditVoiceParameter, 0, DEXED_PITCH_EG_R4}, + {"P EG Level 1",EditVoiceParameter, 0, DEXED_PITCH_EG_L1}, + {"P EG Level 2",EditVoiceParameter, 0, DEXED_PITCH_EG_L2}, + {"P EG Level 3",EditVoiceParameter, 0, DEXED_PITCH_EG_L3}, + {"P EG Level 4",EditVoiceParameter, 0, DEXED_PITCH_EG_L4}, + {"Osc Key Sync",EditVoiceParameter, 0, DEXED_OSC_KEY_SYNC}, + {"LFO Speed", EditVoiceParameter, 0, DEXED_LFO_SPEED}, + {"LFO Delay", EditVoiceParameter, 0, DEXED_LFO_DELAY}, + {"LFO PMD", EditVoiceParameter, 0, DEXED_LFO_PITCH_MOD_DEP}, + {"LFO AMD", EditVoiceParameter, 0, DEXED_LFO_AMP_MOD_DEP}, + {"LFO Sync", EditVoiceParameter, 0, DEXED_LFO_SYNC}, + {"LFO Wave", EditVoiceParameter, 0, DEXED_LFO_WAVE}, + {"P Mod Sens.", EditVoiceParameter, 0, DEXED_LFO_PITCH_MOD_SENS}, + {"Transpose", EditVoiceParameter, 0, DEXED_TRANSPOSE}, + {"Name", InputTxt, 0, 3}, {0} }; @@ -281,7 +382,7 @@ const CUIMenu::TMenuItem CUIMenu::s_OperatorMenu[] = {"Rate Scaling",EditOPParameter, 0, DEXED_OP_OSC_RATE_SCALE}, {"A Mod Sens.", EditOPParameter, 0, DEXED_OP_AMP_MOD_SENS}, {"K Vel. Sens.",EditOPParameter, 0, DEXED_OP_KEY_VEL_SENS}, - {"Enable", EditOPParameter, 0, DEXED_OP_ENABLE}, + {"Enable", EditOPParameter, 0, DEXED_OP_ENABLE}, {0} }; @@ -306,58 +407,50 @@ const CUIMenu::TParameter CUIMenu::s_GlobalParameter[CMiniDexed::ParameterUnknow {0, 99, 1} // ParameterReverbLevel // BEGIN FXRack global parameters mapping definition - #ifdef FXRACK_ENABLE + #ifdef MIXING_CONSOLE_ENABLE , - // FXChain parameters - {0, 1, 1, ToOnOff}, // ParameterFXChainEnable - {0, 99, 1}, // ParameterFXChainWet - - // FXChain > Tube parameters - {0, 1, 1, ToOnOff}, // ParameterFXChainTubeEnable - {0, 99, 1}, // ParameterFXChainTubeWet - {0, 99, 1}, // ParameterFXChainTubeOverdrive - - // FXChain > Chorus parameters - {0, 1, 1, ToOnOff}, // ParameterFXChainChorusEnable - {0, 99, 1}, // ParameterFXChainChorusWet - {0, 99, 1}, // ParameterFXChainChorusRate - {0, 99, 1}, // ParameterFXChainChorusDepth - - // FXChain > Flanger parameters - {0, 1, 1, ToOnOff}, // ParameterFXChainFlangerEnable - {0, 99, 1}, // ParameterFXChainFlangerWet - {0, 99, 1}, // ParameterFXChainFlangerRate - {0, 99, 1}, // ParameterFXChainFlangerDepth - {0, 99, 1}, // ParameterFXChainFlangerFeedback - - // FXChain > Orbitone parameters - {0, 1, 1, ToOnOff}, // ParameterFXChainOrbitoneEnable - {0, 99, 1}, // ParameterFXChainOrbitoneWet - {0, 99, 1}, // ParameterFXChainOrbitoneRate - {0, 99, 1}, // ParameterFXChainOrbitoneDepth - - // FXChain > Phaser parameters - {0, 1, 1, ToOnOff}, // ParameterFXChainPhaserEnable - {0, 99, 1}, // ParameterFXChainPhaserWet - {0, 99, 1}, // ParameterFXChainPhaserRate - {0, 99, 1}, // ParameterFXChainPhaserDepth - {0, 99, 1}, // ParameterFXChainPhaserFeedback - {2, MAX_NB_PHASES, 1}, // ParameterFXChainPhaserNbStages - - // FXChain > Delay parameters - {0, 1, 1, ToOnOff}, // ParameterFXChainDelayEnable - {0, 99, 1}, // ParameterFXChainDelayWet - {0, 99, 1}, // ParameterFXChainDelayLeftDelayTime - {0, 99, 1}, // ParameterFXChainDelayRightDelayTime - {0, 99, 1}, // ParameterFXChainDelayFeedback - - // 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 + + // FX > Tube parameters + {0, 1, 1, ToOnOff}, // ParameterFXTubeEnable + {0, 99, 1}, // ParameterFXTubeOverdrive + + // FX > Chorus parameters + {0, 1, 1, ToOnOff}, // ParameterFXChorusEnable + {0, 99, 1}, // ParameterFXChorusRate + {0, 99, 1}, // ParameterFXChorusDepth + + // FX > Flanger parameters + {0, 1, 1, ToOnOff}, // ParameterFXFlangerEnable + {0, 99, 1}, // ParameterFXFlangerRate + {0, 99, 1}, // ParameterFXFlangerDepth + {0, 99, 1}, // ParameterFXFlangerFeedback + + // FX > Orbitone parameters + {0, 1, 1, ToOnOff}, // ParameterFXOrbitoneEnable + {0, 99, 1}, // ParameterFXOrbitoneRate + {0, 99, 1}, // ParameterFXOrbitoneDepth + + // FX > Phaser parameters + {0, 1, 1, ToOnOff}, // ParameterFXPhaserEnable + {0, 99, 1}, // ParameterFXPhaserRate + {0, 99, 1}, // ParameterFXPhaserDepth + {0, 99, 1}, // ParameterFXPhaserFeedback + {2, MAX_NB_PHASES, 1}, // ParameterFXPhaserNbStages + + // FX > Delay parameters + {0, 1, 1, ToOnOff}, // ParameterFXDelayEnable + {0, 99, 1}, // ParameterFXDelayLeftDelayTime + {0, 99, 1}, // ParameterFXDelayRightDelayTime + {0, 99, 1}, // ParameterFXDelayFeedback + {0, 99, 1}, // ParameterFXDelayFlutterRate + {0, 99, 1}, // ParameterFXDelayFlutterAmount + + // FX > ShimmerReverb parameters + {0, 1, 1, ToOnOff}, // ParameterFXShimmerReverbEnable + {0, 99, 1}, // ParameterFXShimmerReverbInputGain + {0, 99, 1}, // ParameterFXShimmerReverbTime + {0, 99, 1}, // ParameterFXShimmerReverbDiffusion + {0, 99, 1}, // ParameterFXShimmerReverbLP #endif // END FXRack global parameters mapping definition diff --git a/src/uimenu.h b/src/uimenu.h index e8448c5..c565d23 100644 --- a/src/uimenu.h +++ b/src/uimenu.h @@ -142,15 +142,22 @@ private: #ifdef ARM_ALLOW_MULTI_CORE static const TMenuItem s_ReverbMenu[]; #endif -#ifdef FXRACK_ENABLE - static const TMenuItem s_FXChainMenu[]; - static const TMenuItem s_FXChainTube[]; - static const TMenuItem s_FXChainChorus[]; - static const TMenuItem s_FXChainFlanger[]; - static const TMenuItem s_FXChainOrbitone[]; - static const TMenuItem s_FXChainPhaser[]; - static const TMenuItem s_FXChainDelay[]; - static const TMenuItem s_FXChainShimmerReverb[]; +#ifdef MIXING_CONSOLE_ENABLE + static const TMenuItem s_FXMenu[]; + static const TMenuItem s_FXTube[]; + static const TMenuItem s_FXTubeReturn[]; + static const TMenuItem s_FXChorus[]; + static const TMenuItem s_FXChorusReturn[]; + static const TMenuItem s_FXFlanger[]; + static const TMenuItem s_FXFlangerReturn[]; + 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 static const TMenuItem s_EditVoiceMenu[]; static const TMenuItem s_OperatorMenu[]; diff --git a/src/userinterface.cpp b/src/userinterface.cpp index f34e561..236c348 100644 --- a/src/userinterface.cpp +++ b/src/userinterface.cpp @@ -229,6 +229,68 @@ void CUserInterface::DisplayWrite (const char *pMenu, const char *pParam, const 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) { if (m_pLCDBuffered) diff --git a/src/userinterface.h b/src/userinterface.h index 5de2846..e47a31d 100644 --- a/src/userinterface.h +++ b/src/userinterface.h @@ -55,9 +55,19 @@ public: // To be called from the MIDI device on reception of a MIDI CC message 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: +#endif void LCDWrite (const char *pString); // Print to optional HD44780 display +private: void EncoderEventHandler (CKY040::TEvent Event); static void EncoderEventStub (CKY040::TEvent Event, void *pParam); void UIButtonsEventHandler (CUIButton::BtnEvent Event);