2023-03-25 20:24:10 +00:00
|
|
|
#include "Effect.h"
|
2023-07-20 20:41:53 +00:00
|
|
|
#include <numbers>
|
2023-03-25 20:24:10 +00:00
|
|
|
|
2023-07-18 18:20:54 +00:00
|
|
|
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectParameter*> parameters) : effectApplication(effectApplication), parameters(parameters), enabled(nullptr) {
|
2023-07-20 20:41:53 +00:00
|
|
|
actualValues = std::vector<double>(parameters.size(), 0.0);
|
2023-07-14 14:34:24 +00:00
|
|
|
}
|
2023-07-11 12:32:52 +00:00
|
|
|
|
2023-07-18 18:20:54 +00:00
|
|
|
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, EffectParameter* parameter) : Effect(effectApplication, std::vector<EffectParameter*>{parameter}) {}
|
2023-03-28 12:44:46 +00:00
|
|
|
|
2023-07-18 18:20:54 +00:00
|
|
|
Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, std::vector<EffectParameter*> parameters) : application(application), parameters(parameters), enabled(nullptr) {
|
2023-07-20 20:41:53 +00:00
|
|
|
actualValues = std::vector<double>(parameters.size(), 0.0);
|
2023-07-11 12:32:52 +00:00
|
|
|
}
|
2023-07-04 19:47:54 +00:00
|
|
|
|
2023-07-18 18:20:54 +00:00
|
|
|
Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, EffectParameter* parameter) : Effect(application, std::vector<EffectParameter*>{parameter}) {}
|
2023-07-05 11:02:28 +00:00
|
|
|
|
2023-03-28 12:44:46 +00:00
|
|
|
Vector2 Effect::apply(int index, Vector2 input) {
|
2023-07-20 20:41:53 +00:00
|
|
|
animateValues();
|
2023-07-05 11:02:28 +00:00
|
|
|
if (application) {
|
2023-07-20 20:41:53 +00:00
|
|
|
return application(index, input, actualValues, sampleRate);
|
2023-07-05 11:02:28 +00:00
|
|
|
} else if (effectApplication != nullptr) {
|
2023-07-20 20:41:53 +00:00
|
|
|
return effectApplication->apply(index, input, actualValues, sampleRate);
|
2023-07-04 19:47:54 +00:00
|
|
|
}
|
2023-07-05 11:02:28 +00:00
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
2023-07-20 20:41:53 +00:00
|
|
|
void Effect::animateValues() {
|
|
|
|
for (int i = 0; i < parameters.size(); i++) {
|
|
|
|
auto parameter = parameters[i];
|
|
|
|
float minValue = parameter->min;
|
|
|
|
float maxValue = parameter->max;
|
2023-07-21 10:08:55 +00:00
|
|
|
float phase = parameter->lfo != nullptr ? nextPhase(parameter) : 0.0;
|
2023-07-20 20:41:53 +00:00
|
|
|
float percentage = phase / (2 * std::numbers::pi);
|
2023-07-21 10:08:55 +00:00
|
|
|
LfoType type = parameter->lfo != nullptr ? (LfoType)(int)parameter->lfo->getValueUnnormalised() : LfoType::Static;
|
2023-07-20 20:41:53 +00:00
|
|
|
|
2023-07-21 10:08:55 +00:00
|
|
|
switch (type) {
|
2023-07-20 20:54:21 +00:00
|
|
|
case LfoType::Sine:
|
2023-07-20 20:41:53 +00:00
|
|
|
actualValues[i] = std::sin(phase) * 0.5 + 0.5;
|
|
|
|
actualValues[i] = actualValues[i] * (maxValue - minValue) + minValue;
|
|
|
|
break;
|
2023-07-20 20:54:21 +00:00
|
|
|
case LfoType::Square:
|
2023-07-20 20:41:53 +00:00
|
|
|
actualValues[i] = (percentage < 0.5) ? maxValue : minValue;
|
|
|
|
break;
|
2023-07-20 20:54:21 +00:00
|
|
|
case LfoType::Seesaw:
|
2023-07-20 20:41:53 +00:00
|
|
|
// 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;
|
2023-07-20 20:54:21 +00:00
|
|
|
case LfoType::Triangle:
|
2023-07-20 20:41:53 +00:00
|
|
|
actualValues[i] = (percentage < 0.5) ? percentage * 2 : (1 - percentage) * 2;
|
|
|
|
actualValues[i] = actualValues[i] * (maxValue - minValue) + minValue;
|
|
|
|
break;
|
2023-07-20 20:54:21 +00:00
|
|
|
case LfoType::Sawtooth:
|
2023-07-20 20:41:53 +00:00
|
|
|
actualValues[i] = percentage * (maxValue - minValue) + minValue;
|
|
|
|
break;
|
2023-07-20 20:54:21 +00:00
|
|
|
case LfoType::ReverseSawtooth:
|
2023-07-20 20:41:53 +00:00
|
|
|
actualValues[i] = (1 - percentage) * (maxValue - minValue) + minValue;
|
|
|
|
break;
|
2023-07-20 20:54:21 +00:00
|
|
|
case LfoType::Noise:
|
2023-07-21 10:08:55 +00:00
|
|
|
actualValues[i] = ((float)rand() / RAND_MAX) * (maxValue - minValue) + minValue;
|
2023-07-20 20:54:21 +00:00
|
|
|
break;
|
2023-07-20 20:41:53 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-07-05 11:02:28 +00:00
|
|
|
void Effect::apply() {
|
|
|
|
apply(0, Vector2());
|
2023-03-28 12:44:46 +00:00
|
|
|
}
|
|
|
|
|
2023-07-11 12:32:52 +00:00
|
|
|
double Effect::getValue(int index) {
|
2023-07-18 18:20:54 +00:00
|
|
|
return parameters[index]->getValueUnnormalised();
|
2023-07-11 12:32:52 +00:00
|
|
|
}
|
|
|
|
|
2023-03-28 12:44:46 +00:00
|
|
|
double Effect::getValue() {
|
2023-07-11 12:32:52 +00:00
|
|
|
return getValue(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Effect::setValue(int index, double value) {
|
2023-07-18 18:20:54 +00:00
|
|
|
parameters[index]->setUnnormalisedValueNotifyingHost(value);
|
2023-03-28 12:44:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Effect::setValue(double value) {
|
2023-07-11 12:32:52 +00:00
|
|
|
setValue(0, value);
|
2023-03-28 12:44:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Effect::getPrecedence() {
|
|
|
|
return precedence;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Effect::setPrecedence(int precedence) {
|
|
|
|
this->precedence = precedence;
|
|
|
|
}
|
|
|
|
|
2023-07-18 17:28:09 +00:00
|
|
|
void Effect::addListener(int index, juce::AudioProcessorParameter::Listener* listener) {
|
2023-07-18 18:20:54 +00:00
|
|
|
parameters[index]->addListener(listener);
|
2023-07-21 10:08:55 +00:00
|
|
|
if (parameters[index]->lfo != nullptr) {
|
|
|
|
parameters[index]->lfo->addListener(listener);
|
|
|
|
}
|
|
|
|
if (parameters[index]->lfoRate != nullptr) {
|
|
|
|
parameters[index]->lfoRate->addListener(listener);
|
|
|
|
}
|
2023-07-18 18:20:54 +00:00
|
|
|
if (enabled != nullptr) {
|
|
|
|
enabled->addListener(listener);
|
|
|
|
}
|
2023-07-18 17:28:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Effect::removeListener(int index, juce::AudioProcessorParameter::Listener* listener) {
|
2023-07-18 18:20:54 +00:00
|
|
|
if (enabled != nullptr) {
|
|
|
|
enabled->removeListener(listener);
|
|
|
|
}
|
2023-07-21 10:08:55 +00:00
|
|
|
if (parameters[index]->lfoRate != nullptr) {
|
|
|
|
parameters[index]->lfoRate->removeListener(listener);
|
|
|
|
}
|
|
|
|
if (parameters[index]->lfo != nullptr) {
|
|
|
|
parameters[index]->lfo->removeListener(listener);
|
|
|
|
}
|
2023-07-20 19:01:09 +00:00
|
|
|
parameters[index]->removeListener(listener);
|
2023-07-18 18:20:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Effect::markEnableable(bool enable) {
|
|
|
|
if (enabled != nullptr) {
|
|
|
|
enabled->setValue(enable);
|
|
|
|
} else {
|
|
|
|
enabled = new BooleanParameter(getName() + " Enabled", getId() + "Enabled", enable);
|
|
|
|
}
|
2023-07-18 17:28:09 +00:00
|
|
|
}
|
|
|
|
|
2023-07-11 12:32:52 +00:00
|
|
|
juce::String Effect::getId() {
|
2023-07-21 10:08:55 +00:00
|
|
|
return parameters[0]->paramID;
|
2023-03-28 12:44:46 +00:00
|
|
|
}
|
2023-03-25 20:24:10 +00:00
|
|
|
|
2023-07-11 12:32:52 +00:00
|
|
|
juce::String Effect::getName() {
|
2023-07-18 18:20:54 +00:00
|
|
|
return parameters[0]->name;
|
2023-03-25 20:24:10 +00:00
|
|
|
}
|