kopia lustrzana https://github.com/jameshball/osci-render
Add animation in Effect
rodzic
08458a4251
commit
7b38df4031
|
@ -1,30 +1,79 @@
|
||||||
#include "Effect.h"
|
#include "Effect.h"
|
||||||
|
#include <numbers>
|
||||||
|
|
||||||
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectParameter*> parameters) : effectApplication(effectApplication), parameters(parameters), enabled(nullptr) {
|
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectParameter*> parameters) : effectApplication(effectApplication), parameters(parameters), enabled(nullptr) {
|
||||||
smoothValues = std::vector<double>(parameters.size(), 0.0);
|
actualValues = std::vector<double>(parameters.size(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, EffectParameter* parameter) : Effect(effectApplication, std::vector<EffectParameter*>{parameter}) {}
|
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, EffectParameter* parameter) : Effect(effectApplication, std::vector<EffectParameter*>{parameter}) {}
|
||||||
|
|
||||||
Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, std::vector<EffectParameter*> parameters) : application(application), parameters(parameters), enabled(nullptr) {
|
Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, std::vector<EffectParameter*> parameters) : application(application), parameters(parameters), enabled(nullptr) {
|
||||||
smoothValues = std::vector<double>(parameters.size(), 0.0);
|
actualValues = std::vector<double>(parameters.size(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, EffectParameter* parameter) : Effect(application, std::vector<EffectParameter*>{parameter}) {}
|
Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, EffectParameter* parameter) : Effect(application, std::vector<EffectParameter*>{parameter}) {}
|
||||||
|
|
||||||
Vector2 Effect::apply(int index, Vector2 input) {
|
Vector2 Effect::apply(int index, Vector2 input) {
|
||||||
for (int i = 0; i < parameters.size(); i++) {
|
animateValues();
|
||||||
double weight = parameters[i]->smoothValueChange ? 0.0005 : 1.0;
|
|
||||||
smoothValues[i] = (1.0 - weight) * smoothValues[i] + weight * parameters[i]->getValueUnnormalised();
|
|
||||||
}
|
|
||||||
if (application) {
|
if (application) {
|
||||||
return application(index, input, smoothValues, sampleRate);
|
return application(index, input, actualValues, sampleRate);
|
||||||
} else if (effectApplication != nullptr) {
|
} else if (effectApplication != nullptr) {
|
||||||
return effectApplication->apply(index, input, smoothValues, sampleRate);
|
return effectApplication->apply(index, input, actualValues, sampleRate);
|
||||||
}
|
}
|
||||||
return input;
|
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<int>(LfoType::Sine):
|
||||||
|
actualValues[i] = std::sin(phase) * 0.5 + 0.5;
|
||||||
|
actualValues[i] = actualValues[i] * (maxValue - minValue) + minValue;
|
||||||
|
break;
|
||||||
|
case static_cast<int>(LfoType::Square):
|
||||||
|
actualValues[i] = (percentage < 0.5) ? maxValue : minValue;
|
||||||
|
break;
|
||||||
|
case static_cast<int>(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<int>(LfoType::Triangle):
|
||||||
|
actualValues[i] = (percentage < 0.5) ? percentage * 2 : (1 - percentage) * 2;
|
||||||
|
actualValues[i] = actualValues[i] * (maxValue - minValue) + minValue;
|
||||||
|
break;
|
||||||
|
case static_cast<int>(LfoType::Sawtooth):
|
||||||
|
actualValues[i] = percentage * (maxValue - minValue) + minValue;
|
||||||
|
break;
|
||||||
|
case static_cast<int>(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() {
|
void Effect::apply() {
|
||||||
apply(0, Vector2());
|
apply(0, Vector2());
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ public:
|
||||||
Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, EffectParameter* parameter);
|
Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, EffectParameter* parameter);
|
||||||
|
|
||||||
Vector2 apply(int index, Vector2 input);
|
Vector2 apply(int index, Vector2 input);
|
||||||
|
|
||||||
void apply();
|
void apply();
|
||||||
double getValue(int index);
|
double getValue(int index);
|
||||||
double getValue();
|
double getValue();
|
||||||
|
@ -33,11 +34,13 @@ public:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
juce::SpinLock listenerLock;
|
juce::SpinLock listenerLock;
|
||||||
std::vector<double> smoothValues;
|
std::vector<double> actualValues;
|
||||||
double frequency = 1.0;
|
|
||||||
int precedence = -1;
|
int precedence = -1;
|
||||||
int sampleRate = 192000;
|
int sampleRate = 192000;
|
||||||
std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application;
|
std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application;
|
||||||
|
|
||||||
std::shared_ptr<EffectApplication> effectApplication;
|
std::shared_ptr<EffectApplication> effectApplication;
|
||||||
|
|
||||||
|
void animateValues();
|
||||||
|
float nextPhase(EffectParameter* parameter);
|
||||||
};
|
};
|
|
@ -222,6 +222,7 @@ public:
|
||||||
std::atomic<bool> smoothValueChange = true;
|
std::atomic<bool> smoothValueChange = true;
|
||||||
IntParameter* lfo = new IntParameter(name + " LFO", id + "Lfo", 1, 1, 8);
|
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");
|
FloatParameter* lfoRate = new FloatParameter(name + " LFO Rate", id + "LfoRate", 1.0f, 0.0f, 100.0f, 0.1f, "Hz");
|
||||||
|
std::atomic<float> phase = 0.0f;
|
||||||
|
|
||||||
std::vector<juce::AudioProcessorParameter*> getParameters() {
|
std::vector<juce::AudioProcessorParameter*> getParameters() {
|
||||||
return { this, lfo, lfoRate };
|
return { this, lfo, lfoRate };
|
||||||
|
|
Ładowanie…
Reference in New Issue