diff --git a/Source/audio/Effect.cpp b/Source/audio/Effect.cpp index d7b4f3e..67d31de 100644 --- a/Source/audio/Effect.cpp +++ b/Source/audio/Effect.cpp @@ -1,30 +1,79 @@ #include "Effect.h" +#include Effect::Effect(std::shared_ptr effectApplication, std::vector parameters) : effectApplication(effectApplication), parameters(parameters), enabled(nullptr) { - smoothValues = std::vector(parameters.size(), 0.0); + actualValues = std::vector(parameters.size(), 0.0); } Effect::Effect(std::shared_ptr effectApplication, EffectParameter* parameter) : Effect(effectApplication, std::vector{parameter}) {} Effect::Effect(std::function&, double)> application, std::vector parameters) : application(application), parameters(parameters), enabled(nullptr) { - smoothValues = std::vector(parameters.size(), 0.0); + actualValues = std::vector(parameters.size(), 0.0); } Effect::Effect(std::function&, double)> application, EffectParameter* parameter) : Effect(application, std::vector{parameter}) {} Vector2 Effect::apply(int index, Vector2 input) { - for (int i = 0; i < parameters.size(); i++) { - double weight = parameters[i]->smoothValueChange ? 0.0005 : 1.0; - smoothValues[i] = (1.0 - weight) * smoothValues[i] + weight * parameters[i]->getValueUnnormalised(); - } + animateValues(); if (application) { - return application(index, input, smoothValues, sampleRate); + return application(index, input, actualValues, sampleRate); } else if (effectApplication != nullptr) { - return effectApplication->apply(index, input, smoothValues, sampleRate); + return effectApplication->apply(index, input, actualValues, sampleRate); } return input; } +void Effect::animateValues() { + for (int i = 0; i < parameters.size(); i++) { + auto parameter = parameters[i]; + float minValue = parameter->min; + float maxValue = parameter->max; + float phase = nextPhase(parameter); + float percentage = phase / (2 * std::numbers::pi); + + switch ((int) parameter->lfo->getValueUnnormalised()) { + case static_cast(LfoType::Sine): + actualValues[i] = std::sin(phase) * 0.5 + 0.5; + actualValues[i] = actualValues[i] * (maxValue - minValue) + minValue; + break; + case static_cast(LfoType::Square): + actualValues[i] = (percentage < 0.5) ? maxValue : minValue; + break; + case static_cast(LfoType::Seesaw): + // modified sigmoid function + actualValues[i] = (percentage < 0.5) ? percentage * 2 : (1 - percentage) * 2; + actualValues[i] = 1 / (1 + std::exp(-16 * (actualValues[i] - 0.5))); + actualValues[i] = actualValues[i] * (maxValue - minValue) + minValue; + break; + case static_cast(LfoType::Triangle): + actualValues[i] = (percentage < 0.5) ? percentage * 2 : (1 - percentage) * 2; + actualValues[i] = actualValues[i] * (maxValue - minValue) + minValue; + break; + case static_cast(LfoType::Sawtooth): + actualValues[i] = percentage * (maxValue - minValue) + minValue; + break; + case static_cast(LfoType::ReverseSawtooth): + actualValues[i] = (1 - percentage) * (maxValue - minValue) + minValue; + break; + default: + double weight = parameter->smoothValueChange ? 0.0005 : 1.0; + actualValues[i] = (1.0 - weight) * actualValues[i] + weight * parameter->getValueUnnormalised(); + break; + } + } +} + +// should only be the audio thread calling this, but either way it's not a big deal +float Effect::nextPhase(EffectParameter* parameter) { + parameter->phase += parameter->lfoRate->getValueUnnormalised() / sampleRate; + + if (parameter->phase > 1) { + parameter->phase -= 1; + } + + return parameter->phase * 2 * std::numbers::pi; +} + void Effect::apply() { apply(0, Vector2()); } diff --git a/Source/audio/Effect.h b/Source/audio/Effect.h index d0e908a..cad711d 100644 --- a/Source/audio/Effect.h +++ b/Source/audio/Effect.h @@ -14,6 +14,7 @@ public: Effect(std::function&, double)> application, EffectParameter* parameter); Vector2 apply(int index, Vector2 input); + void apply(); double getValue(int index); double getValue(); @@ -33,11 +34,13 @@ public: private: juce::SpinLock listenerLock; - std::vector smoothValues; - double frequency = 1.0; + std::vector actualValues; int precedence = -1; int sampleRate = 192000; std::function&, double)> application; std::shared_ptr effectApplication; + + void animateValues(); + float nextPhase(EffectParameter* parameter); }; \ No newline at end of file diff --git a/Source/audio/EffectParameter.h b/Source/audio/EffectParameter.h index 91f4055..dc3922d 100644 --- a/Source/audio/EffectParameter.h +++ b/Source/audio/EffectParameter.h @@ -222,6 +222,7 @@ public: std::atomic smoothValueChange = true; IntParameter* lfo = new IntParameter(name + " LFO", id + "Lfo", 1, 1, 8); FloatParameter* lfoRate = new FloatParameter(name + " LFO Rate", id + "LfoRate", 1.0f, 0.0f, 100.0f, 0.1f, "Hz"); + std::atomic phase = 0.0f; std::vector getParameters() { return { this, lfo, lfoRate };