kopia lustrzana https://github.com/jameshball/osci-render
Merge pull request #43 from jameshball/audio-plugin-parameters
Audio plugin parameterspull/170/head
commit
b4e3eceb46
|
@ -37,39 +37,39 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
||||||
|
|
||||||
allEffects.push_back(std::make_shared<Effect>(
|
allEffects.push_back(std::make_shared<Effect>(
|
||||||
std::make_shared<BitCrushEffect>(),
|
std::make_shared<BitCrushEffect>(),
|
||||||
std::vector<EffectDetails>(1, { "Bit Crush", "bitCrush", 0.0, 0.0, 1.0, 0.001, true })
|
std::vector<EffectParameter>(1, { "Bit Crush", "bitCrush", 0.0, 0.0, 1.0 })
|
||||||
));
|
));
|
||||||
allEffects.push_back(std::make_shared<Effect>(
|
allEffects.push_back(std::make_shared<Effect>(
|
||||||
std::make_shared<BulgeEffect>(),
|
std::make_shared<BulgeEffect>(),
|
||||||
std::vector<EffectDetails>(1, { "Bulge", "bulge", 0.0, 0.0, 1.0, 0.001, true })
|
std::vector<EffectParameter>(1, { "Bulge", "bulge", 0.0, 0.0, 1.0 })
|
||||||
));
|
));
|
||||||
allEffects.push_back(std::make_shared<Effect>(
|
allEffects.push_back(std::make_shared<Effect>(
|
||||||
std::make_shared<RotateEffect>(),
|
std::make_shared<RotateEffect>(),
|
||||||
std::vector<EffectDetails>(1, { "2D Rotate Speed", "rotateSpeed", 0.0, 0.0, 1.0, 0.001, true })
|
std::vector<EffectParameter>(1, { "2D Rotate Speed", "rotateSpeed", 0.0, 0.0, 1.0 })
|
||||||
));
|
));
|
||||||
allEffects.push_back(std::make_shared<Effect>(
|
allEffects.push_back(std::make_shared<Effect>(
|
||||||
std::make_shared<VectorCancellingEffect>(),
|
std::make_shared<VectorCancellingEffect>(),
|
||||||
std::vector<EffectDetails>(1, { "Vector cancelling", "vectorCancelling", 0.0, 0.0, 1.0, 0.001, true })
|
std::vector<EffectParameter>(1, { "Vector cancelling", "vectorCancelling", 0.0, 0.0, 1.0 })
|
||||||
));
|
));
|
||||||
allEffects.push_back(std::make_shared<Effect>(
|
allEffects.push_back(std::make_shared<Effect>(
|
||||||
std::make_shared<DistortEffect>(true),
|
std::make_shared<DistortEffect>(true),
|
||||||
std::vector<EffectDetails>(1, { "Vertical shift", "verticalDistort", 0.0, 0.0, 1.0, 0.001, true })
|
std::vector<EffectParameter>(1, { "Vertical shift", "verticalDistort", 0.0, 0.0, 1.0 })
|
||||||
));
|
));
|
||||||
allEffects.push_back(std::make_shared<Effect>(
|
allEffects.push_back(std::make_shared<Effect>(
|
||||||
std::make_shared<DistortEffect>(false),
|
std::make_shared<DistortEffect>(false),
|
||||||
std::vector<EffectDetails>(1, { "Horizontal shift", "horizontalDistort", 0.0, 0.0, 1.0, 0.001, true })
|
std::vector<EffectParameter>(1, { "Horizontal shift", "horizontalDistort", 0.0, 0.0, 1.0 })
|
||||||
));
|
));
|
||||||
allEffects.push_back(std::make_shared<Effect>(
|
allEffects.push_back(std::make_shared<Effect>(
|
||||||
std::make_shared<SmoothEffect>(),
|
std::make_shared<SmoothEffect>(),
|
||||||
std::vector<EffectDetails>(1, { "Smoothing", "smoothing", 0.0, 0.0, 1.0, 0.001, true })
|
std::vector<EffectParameter>(1, { "Smoothing", "smoothing", 0.0, 0.0, 1.0 })
|
||||||
));
|
));
|
||||||
allEffects.push_back(std::make_shared<Effect>(
|
allEffects.push_back(std::make_shared<Effect>(
|
||||||
wobbleEffect,
|
wobbleEffect,
|
||||||
std::vector<EffectDetails>(1, { "Wobble", "wobble", 0.0, 0.0, 1.0, 0.001, true })
|
std::vector<EffectParameter>(1, { "Wobble", "wobble", 0.0, 0.0, 1.0 })
|
||||||
));
|
));
|
||||||
allEffects.push_back(std::make_shared<Effect>(
|
allEffects.push_back(std::make_shared<Effect>(
|
||||||
delayEffect,
|
delayEffect,
|
||||||
std::vector<EffectDetails>{{ "Delay Decay", "delayDecay", 0.0, 0.0, 1.0, 0.001, true }, { "Delay Length", "delayEchoLength", 0.5, 0.0, 1.0, 0.001, true }}
|
std::vector<EffectParameter>{{ "Delay Decay", "delayDecay", 0.0, 0.0, 1.0 }, { "Delay Length", "delayEchoLength", 0.5, 0.0, 1.0 }}
|
||||||
));
|
));
|
||||||
allEffects.push_back(traceMax);
|
allEffects.push_back(traceMax);
|
||||||
allEffects.push_back(traceMin);
|
allEffects.push_back(traceMin);
|
||||||
|
@ -86,6 +86,16 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
addLuaSlider();
|
addLuaSlider();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto effects = allEffects;
|
||||||
|
effects.insert(effects.end(), permanentEffects.begin(), permanentEffects.end());
|
||||||
|
effects.insert(effects.end(), luaEffects.begin(), luaEffects.end());
|
||||||
|
|
||||||
|
for (auto effect : effects) {
|
||||||
|
for (auto& parameter : effect->parameters) {
|
||||||
|
addParameter(¶meter);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OscirenderAudioProcessor::~OscirenderAudioProcessor() {}
|
OscirenderAudioProcessor::~OscirenderAudioProcessor() {}
|
||||||
|
@ -189,7 +199,7 @@ void OscirenderAudioProcessor::addLuaSlider() {
|
||||||
|
|
||||||
luaEffects.push_back(std::make_shared<Effect>(
|
luaEffects.push_back(std::make_shared<Effect>(
|
||||||
std::make_shared<LuaEffect>(sliderName, *this),
|
std::make_shared<LuaEffect>(sliderName, *this),
|
||||||
std::vector<EffectDetails>(1, { "Lua " + sliderName, "lua" + sliderName, 0.0, 0.0, 1.0, 0.001, false })
|
std::vector<EffectParameter>(1, { "Lua " + sliderName, "lua" + sliderName, 0.0, 0.0, 1.0, 0.001, false })
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,21 +79,21 @@ public:
|
||||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||||
frequency = values[0];
|
frequency = values[0];
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Frequency", "frequency", 440.0, 0.0, 12000.0, 0.1, true })
|
}, std::vector<EffectParameter>(1, { "Frequency", "frequency", 440.0, 0.0, 12000.0, 0.1 })
|
||||||
);
|
);
|
||||||
|
|
||||||
std::shared_ptr<Effect> volumeEffect = std::make_shared<Effect>(
|
std::shared_ptr<Effect> volumeEffect = std::make_shared<Effect>(
|
||||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||||
volume = values[0];
|
volume = values[0];
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Volume", "volume", 1.0, 0.0, 3.0, 0.001, true })
|
}, std::vector<EffectParameter>(1, { "Volume", "volume", 1.0, 0.0, 3.0 })
|
||||||
);
|
);
|
||||||
|
|
||||||
std::shared_ptr<Effect> thresholdEffect = std::make_shared<Effect>(
|
std::shared_ptr<Effect> thresholdEffect = std::make_shared<Effect>(
|
||||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||||
threshold = values[0];
|
threshold = values[0];
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Threshold", "threshold", 3.0, 0.0, 3.0, 0.001, true })
|
}, std::vector<EffectParameter>(1, { "Threshold", "threshold", 3.0, 0.0, 3.0 })
|
||||||
);
|
);
|
||||||
|
|
||||||
std::shared_ptr<Effect> focalLength = std::make_shared<Effect>(
|
std::shared_ptr<Effect> focalLength = std::make_shared<Effect>(
|
||||||
|
@ -104,7 +104,7 @@ public:
|
||||||
camera->setFocalLength(values[0]);
|
camera->setFocalLength(values[0]);
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Focal length", "focalLength", 1.0, 0.0, 2.0, 0.001, true })
|
}, std::vector<EffectParameter>(1, { "Focal length", "focalLength", 1.0, 0.0, 2.0 })
|
||||||
);
|
);
|
||||||
std::shared_ptr<Effect> rotateX = std::make_shared<Effect>(
|
std::shared_ptr<Effect> rotateX = std::make_shared<Effect>(
|
||||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||||
|
@ -114,7 +114,7 @@ public:
|
||||||
obj->setBaseRotationX(values[0] * std::numbers::pi);
|
obj->setBaseRotationX(values[0] * std::numbers::pi);
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Rotate x", "rotateX", 1.0, -1.0, 1.0, 0.001, true })
|
}, std::vector<EffectParameter>(1, { "Rotate x", "rotateX", 1.0, -1.0, 1.0 })
|
||||||
);
|
);
|
||||||
std::shared_ptr<Effect> rotateY = std::make_shared<Effect>(
|
std::shared_ptr<Effect> rotateY = std::make_shared<Effect>(
|
||||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||||
|
@ -124,7 +124,7 @@ public:
|
||||||
obj->setBaseRotationY(values[0] * std::numbers::pi);
|
obj->setBaseRotationY(values[0] * std::numbers::pi);
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Rotate y", "rotateY", 1.0, -1.0, 1.0, 0.001, true })
|
}, std::vector<EffectParameter>(1, { "Rotate y", "rotateY", 1.0, -1.0, 1.0 })
|
||||||
);
|
);
|
||||||
std::shared_ptr<Effect> rotateZ = std::make_shared<Effect>(
|
std::shared_ptr<Effect> rotateZ = std::make_shared<Effect>(
|
||||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||||
|
@ -134,7 +134,7 @@ public:
|
||||||
obj->setBaseRotationZ(values[0] * std::numbers::pi);
|
obj->setBaseRotationZ(values[0] * std::numbers::pi);
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Rotate z", "rotateZ", 0.0, -1.0, 1.0, 0.001, true })
|
}, std::vector<EffectParameter>(1, { "Rotate z", "rotateZ", 0.0, -1.0, 1.0 })
|
||||||
);
|
);
|
||||||
std::shared_ptr<Effect> currentRotateX = std::make_shared<Effect>(
|
std::shared_ptr<Effect> currentRotateX = std::make_shared<Effect>(
|
||||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||||
|
@ -144,7 +144,7 @@ public:
|
||||||
obj->setCurrentRotationX(values[0] * std::numbers::pi);
|
obj->setCurrentRotationX(values[0] * std::numbers::pi);
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Current Rotate x", "currentRotateX", 0.0, 0.0, 1.0, 0.001, false })
|
}, std::vector<EffectParameter>(1, { "Current Rotate x", "currentRotateX", 0.0, 0.0, 1.0, 0.001, false })
|
||||||
);
|
);
|
||||||
std::shared_ptr<Effect> currentRotateY = std::make_shared<Effect>(
|
std::shared_ptr<Effect> currentRotateY = std::make_shared<Effect>(
|
||||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||||
|
@ -154,7 +154,7 @@ public:
|
||||||
obj->setCurrentRotationY(values[0] * std::numbers::pi);
|
obj->setCurrentRotationY(values[0] * std::numbers::pi);
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Current Rotate y", "currentRotateY", 0.0, 0.0, 1.0, 0.001, false })
|
}, std::vector<EffectParameter>(1, { "Current Rotate y", "currentRotateY", 0.0, 0.0, 1.0, 0.001, false })
|
||||||
);
|
);
|
||||||
std::shared_ptr<Effect> currentRotateZ = std::make_shared<Effect>(
|
std::shared_ptr<Effect> currentRotateZ = std::make_shared<Effect>(
|
||||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||||
|
@ -164,7 +164,7 @@ public:
|
||||||
obj->setCurrentRotationZ(values[0] * std::numbers::pi);
|
obj->setCurrentRotationZ(values[0] * std::numbers::pi);
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Current Rotate z", "currentRotateZ", 0.0, 0.0, 1.0, 0.001, false })
|
}, std::vector<EffectParameter>(1, { "Current Rotate z", "currentRotateZ", 0.0, 0.0, 1.0, 0.001, false })
|
||||||
);
|
);
|
||||||
std::shared_ptr<Effect> rotateSpeed = std::make_shared<Effect>(
|
std::shared_ptr<Effect> rotateSpeed = std::make_shared<Effect>(
|
||||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||||
|
@ -174,7 +174,7 @@ public:
|
||||||
obj->setRotationSpeed(values[0]);
|
obj->setRotationSpeed(values[0]);
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Rotate speed", "rotateSpeed", 0.0, -1.0, 1.0, 0.001, true })
|
}, std::vector<EffectParameter>(1, { "Rotate speed", "rotateSpeed", 0.0, -1.0, 1.0 })
|
||||||
);
|
);
|
||||||
std::atomic<bool> fixedRotateX = false;
|
std::atomic<bool> fixedRotateX = false;
|
||||||
std::atomic<bool> fixedRotateY = false;
|
std::atomic<bool> fixedRotateY = false;
|
||||||
|
@ -236,14 +236,14 @@ private:
|
||||||
traceMaxValue = values[0];
|
traceMaxValue = values[0];
|
||||||
traceMaxEnabled = true;
|
traceMaxEnabled = true;
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Trace max", "traceMax", 1.0, 0.0, 1.0, 0.001, true })
|
}, std::vector<EffectParameter>(1, { "Trace max", "traceMax", 1.0, 0.0, 1.0 })
|
||||||
);
|
);
|
||||||
std::shared_ptr<Effect> traceMin = std::make_shared<Effect>(
|
std::shared_ptr<Effect> traceMin = std::make_shared<Effect>(
|
||||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||||
traceMinValue = values[0];
|
traceMinValue = values[0];
|
||||||
traceMinEnabled = true;
|
traceMinEnabled = true;
|
||||||
return input;
|
return input;
|
||||||
}, std::vector<EffectDetails>(1, { "Trace min", "traceMin", 0.0, 0.0, 1.0, 0.001, true })
|
}, std::vector<EffectParameter>(1, { "Trace min", "traceMin", 0.0, 0.0, 1.0 })
|
||||||
);
|
);
|
||||||
const double MIN_TRACE = 0.005;
|
const double MIN_TRACE = 0.005;
|
||||||
double traceMaxValue = traceMax->getValue();
|
double traceMaxValue = traceMax->getValue();
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
#include "Effect.h"
|
#include "Effect.h"
|
||||||
|
|
||||||
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectDetails> details) : effectApplication(effectApplication), details(details) {
|
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectParameter> parameters) : effectApplication(effectApplication), parameters(parameters) {
|
||||||
smoothValues = std::vector<double>(details.size(), 0.0);
|
smoothValues = std::vector<double>(parameters.size(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, EffectDetails details) : Effect(effectApplication, std::vector<EffectDetails>{details}) {}
|
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<EffectDetails> details) : application(application), details(details) {
|
Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, std::vector<EffectParameter> parameters) : application(application), parameters(parameters) {
|
||||||
smoothValues = std::vector<double>(details.size(), 0.0);
|
smoothValues = std::vector<double>(parameters.size(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, EffectDetails details) : Effect(application, std::vector<EffectDetails>{details}) {}
|
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 < details.size(); i++) {
|
for (int i = 0; i < parameters.size(); i++) {
|
||||||
double weight = details[i].smoothValueChange ? 0.0005 : 1.0;
|
double weight = parameters[i].smoothValueChange ? 0.0005 : 1.0;
|
||||||
smoothValues[i] = (1.0 - weight) * smoothValues[i] + weight * details[i].value;
|
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, smoothValues, sampleRate);
|
||||||
|
@ -30,7 +30,7 @@ void Effect::apply() {
|
||||||
}
|
}
|
||||||
|
|
||||||
double Effect::getValue(int index) {
|
double Effect::getValue(int index) {
|
||||||
return details[index].value;
|
return parameters[index].getValueUnnormalised();
|
||||||
}
|
}
|
||||||
|
|
||||||
double Effect::getValue() {
|
double Effect::getValue() {
|
||||||
|
@ -38,7 +38,7 @@ double Effect::getValue() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Effect::setValue(int index, double value) {
|
void Effect::setValue(int index, double value) {
|
||||||
details[index].value = value;
|
parameters[index].setUnnormalisedValueNotifyingHost(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Effect::setValue(double value) {
|
void Effect::setValue(double value) {
|
||||||
|
@ -54,9 +54,9 @@ void Effect::setPrecedence(int precedence) {
|
||||||
}
|
}
|
||||||
|
|
||||||
juce::String Effect::getId() {
|
juce::String Effect::getId() {
|
||||||
return details[0].id;
|
return parameters[0].id;
|
||||||
}
|
}
|
||||||
|
|
||||||
juce::String Effect::getName() {
|
juce::String Effect::getName() {
|
||||||
return details[0].name;
|
return parameters[0].name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
|
|
||||||
class Effect {
|
class Effect {
|
||||||
public:
|
public:
|
||||||
Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectDetails> details);
|
Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectParameter> parameters);
|
||||||
Effect(std::shared_ptr<EffectApplication> effectApplication, EffectDetails details);
|
Effect(std::shared_ptr<EffectApplication> effectApplication, EffectParameter parameter);
|
||||||
Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, std::vector<EffectDetails> details);
|
Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, std::vector<EffectParameter> parameters);
|
||||||
Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, EffectDetails details);
|
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();
|
||||||
|
@ -21,7 +21,7 @@ public:
|
||||||
juce::String getId();
|
juce::String getId();
|
||||||
juce::String getName();
|
juce::String getName();
|
||||||
|
|
||||||
std::vector<EffectDetails> details;
|
std::vector<EffectParameter> parameters;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -2,20 +2,21 @@
|
||||||
#include "../shape/Vector2.h"
|
#include "../shape/Vector2.h"
|
||||||
#include <JuceHeader.h>
|
#include <JuceHeader.h>
|
||||||
|
|
||||||
struct EffectDetails {
|
class EffectParameter : public juce::AudioProcessorParameter {
|
||||||
|
public:
|
||||||
juce::String name;
|
juce::String name;
|
||||||
juce::String id;
|
juce::String id;
|
||||||
std::atomic<double> value = 0.0;
|
|
||||||
std::atomic<double> min = 0.0;
|
std::atomic<float> min = 0.0;
|
||||||
std::atomic<double> max = 1.0;
|
std::atomic<float> max = 1.0;
|
||||||
std::atomic<double> step = 0.001;
|
std::atomic<float> step = 0.001;
|
||||||
std::atomic<bool> smoothValueChange = true;
|
std::atomic<bool> smoothValueChange = true;
|
||||||
|
|
||||||
EffectDetails(juce::String name, juce::String id, double value, double min, double max, double step, bool smoothValueChange) : name(name), id(id), value(value), min(min), max(max), step(step), smoothValueChange(smoothValueChange) {}
|
EffectParameter(juce::String name, juce::String id, float value, float min, float max, float step = 0.001, bool smoothValueChange = true) : name(name), id(id), value(value), min(min), max(max), step(step), smoothValueChange(smoothValueChange) {}
|
||||||
|
|
||||||
// COPY CONSTRUCTOR SHOULD ONLY BE USED BEFORE
|
// COPY CONSTRUCTOR SHOULD ONLY BE USED BEFORE
|
||||||
// THE OBJECT IS USED IN MULTIPLE THREADS
|
// THE OBJECT IS USED IN MULTIPLE THREADS
|
||||||
EffectDetails(const EffectDetails& other) {
|
EffectParameter(const EffectParameter& other) {
|
||||||
name = other.name;
|
name = other.name;
|
||||||
id = other.id;
|
id = other.id;
|
||||||
value.store(other.value.load());
|
value.store(other.value.load());
|
||||||
|
@ -24,6 +25,96 @@ struct EffectDetails {
|
||||||
step.store(other.step.load());
|
step.store(other.step.load());
|
||||||
smoothValueChange.store(other.smoothValueChange.load());
|
smoothValueChange.store(other.smoothValueChange.load());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
juce::String getName(int maximumStringLength) const override {
|
||||||
|
return name.substring(0, maximumStringLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
juce::String getLabel() const override {
|
||||||
|
return juce::String();
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns value in range [0, 1]
|
||||||
|
float getNormalisedValue(float value) const {
|
||||||
|
// clip value to valid range
|
||||||
|
auto min = this->min.load();
|
||||||
|
auto max = this->max.load();
|
||||||
|
value = juce::jlimit(min, max, value);
|
||||||
|
// normalize value to range [0, 1]
|
||||||
|
return (value - min) / (max - min);
|
||||||
|
}
|
||||||
|
|
||||||
|
float getUnnormalisedValue(float value) const {
|
||||||
|
value = juce::jlimit(0.0f, 1.0f, value);
|
||||||
|
auto min = this->min.load();
|
||||||
|
auto max = this->max.load();
|
||||||
|
return min + value * (max - min);
|
||||||
|
}
|
||||||
|
|
||||||
|
float getValue() const override {
|
||||||
|
return getNormalisedValue(value.load());
|
||||||
|
}
|
||||||
|
|
||||||
|
float getValueUnnormalised() const {
|
||||||
|
return value.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValue(float newValue) override {
|
||||||
|
value = getUnnormalisedValue(newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValueUnnormalised(float newValue) {
|
||||||
|
value = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUnnormalisedValueNotifyingHost(float newValue) {
|
||||||
|
setValueNotifyingHost(getNormalisedValue(newValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
float getDefaultValue() const override {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getNumSteps() const override {
|
||||||
|
return (max.load() - min.load()) / step.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDiscrete() const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isBoolean() const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isOrientationInverted() const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
juce::String getText(float value, int maximumStringLength) const override {
|
||||||
|
auto string = juce::String(getUnnormalisedValue(value), 3);
|
||||||
|
return string.substring(0, maximumStringLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
float getValueForText(const juce::String& text) const override {
|
||||||
|
return getNormalisedValue(text.getFloatValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isAutomatable() const override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isMetaParameter() const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
juce::AudioProcessorParameter::Category getCategory() const override {
|
||||||
|
return juce::AudioProcessorParameter::genericParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// value is not necessarily in the range [min, max] so effect applications may need to clip to a valid range
|
||||||
|
std::atomic<float> value = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EffectApplication {
|
class EffectApplication {
|
||||||
|
|
|
@ -18,42 +18,42 @@ void EffectComponent::componentSetup() {
|
||||||
addAndMakeVisible(slider);
|
addAndMakeVisible(slider);
|
||||||
addAndMakeVisible(selected);
|
addAndMakeVisible(selected);
|
||||||
|
|
||||||
EffectDetails details = effect.details[index];
|
EffectParameter& parameter = effect.parameters[index];
|
||||||
|
|
||||||
slider.setRange(details.min, details.max, details.step);
|
slider.setRange(parameter.min, parameter.max, parameter.step);
|
||||||
slider.setValue(details.value, juce::dontSendNotification);
|
slider.setValue(parameter.getValueUnnormalised(), juce::dontSendNotification);
|
||||||
|
|
||||||
slider.setSliderStyle(juce::Slider::LinearHorizontal);
|
slider.setSliderStyle(juce::Slider::LinearHorizontal);
|
||||||
slider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 90, slider.getTextBoxHeight());
|
slider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 90, slider.getTextBoxHeight());
|
||||||
|
|
||||||
selected.setToggleState(false, juce::dontSendNotification);
|
selected.setToggleState(false, juce::dontSendNotification);
|
||||||
|
|
||||||
min.textBox.setValue(details.min, juce::dontSendNotification);
|
min.textBox.setValue(parameter.min, juce::dontSendNotification);
|
||||||
max.textBox.setValue(details.max, juce::dontSendNotification);
|
max.textBox.setValue(parameter.max, juce::dontSendNotification);
|
||||||
|
|
||||||
min.textBox.onValueChange = [this]() {
|
min.textBox.onValueChange = [this]() {
|
||||||
double minValue = min.textBox.getValue();
|
double minValue = min.textBox.getValue();
|
||||||
double maxValue = max.textBox.getValue();
|
double maxValue = max.textBox.getValue();
|
||||||
if (minValue >= maxValue) {
|
if (minValue >= maxValue) {
|
||||||
minValue = maxValue - effect.details[index].step;
|
minValue = maxValue - effect.parameters[index].step;
|
||||||
min.textBox.setValue(minValue, juce::dontSendNotification);
|
min.textBox.setValue(minValue, juce::dontSendNotification);
|
||||||
}
|
}
|
||||||
effect.details[index].min = minValue;
|
effect.parameters[index].min = minValue;
|
||||||
slider.setRange(effect.details[index].min, effect.details[index].max, effect.details[index].step);
|
slider.setRange(effect.parameters[index].min, effect.parameters[index].max, effect.parameters[index].step);
|
||||||
};
|
};
|
||||||
|
|
||||||
max.textBox.onValueChange = [this]() {
|
max.textBox.onValueChange = [this]() {
|
||||||
double minValue = min.textBox.getValue();
|
double minValue = min.textBox.getValue();
|
||||||
double maxValue = max.textBox.getValue();
|
double maxValue = max.textBox.getValue();
|
||||||
if (maxValue <= minValue) {
|
if (maxValue <= minValue) {
|
||||||
maxValue = minValue + effect.details[index].step;
|
maxValue = minValue + effect.parameters[index].step;
|
||||||
max.textBox.setValue(maxValue, juce::dontSendNotification);
|
max.textBox.setValue(maxValue, juce::dontSendNotification);
|
||||||
}
|
}
|
||||||
effect.details[index].max = maxValue;
|
effect.parameters[index].max = maxValue;
|
||||||
slider.setRange(effect.details[index].min, effect.details[index].max, effect.details[index].step);
|
slider.setRange(effect.parameters[index].min, effect.parameters[index].max, effect.parameters[index].step);
|
||||||
};
|
};
|
||||||
|
|
||||||
popupLabel.setText(details.name + " Settings", juce::dontSendNotification);
|
popupLabel.setText(parameter.name + " Settings", juce::dontSendNotification);
|
||||||
popupLabel.setJustificationType(juce::Justification::centred);
|
popupLabel.setJustificationType(juce::Justification::centred);
|
||||||
popupLabel.setFont(juce::Font(14.0f, juce::Font::bold));
|
popupLabel.setFont(juce::Font(14.0f, juce::Font::bold));
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ void EffectComponent::resized() {
|
||||||
void EffectComponent::paint(juce::Graphics& g) {
|
void EffectComponent::paint(juce::Graphics& g) {
|
||||||
g.fillAll(juce::Colours::black);
|
g.fillAll(juce::Colours::black);
|
||||||
g.setColour(juce::Colours::white);
|
g.setColour(juce::Colours::white);
|
||||||
g.drawText(effect.details[index].name, textBounds, juce::Justification::left);
|
g.drawText(effect.parameters[index].name, textBounds, juce::Justification::left);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectComponent::mouseDown(const juce::MouseEvent& event) {
|
void EffectComponent::mouseDown(const juce::MouseEvent& event) {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#include "EffectsListComponent.h"
|
#include "EffectsListComponent.h"
|
||||||
|
|
||||||
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<Effect> effect) : DraggableListBoxItem(lb, data, rn), effect(effect) {
|
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<Effect> effect) : DraggableListBoxItem(lb, data, rn), effect(effect) {
|
||||||
auto details = effect->details;
|
auto parameters = effect->parameters;
|
||||||
for (int i = 0; i < details.size(); i++) {
|
for (int i = 0; i < parameters.size(); i++) {
|
||||||
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(*effect, i, i == 0);
|
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(*effect, i, i == 0);
|
||||||
// using weak_ptr to avoid circular reference and memory leak
|
// using weak_ptr to avoid circular reference and memory leak
|
||||||
std::weak_ptr<EffectComponent> weakEffectComponent = effectComponent;
|
std::weak_ptr<EffectComponent> weakEffectComponent = effectComponent;
|
||||||
effectComponent->slider.setValue(details[i].value, juce::dontSendNotification);
|
effectComponent->slider.setValue(parameters[i].getValueUnnormalised(), juce::dontSendNotification);
|
||||||
effectComponent->slider.onValueChange = [this, i, weakEffectComponent] {
|
effectComponent->slider.onValueChange = [this, i, weakEffectComponent] {
|
||||||
if (auto effectComponent = weakEffectComponent.lock()) {
|
if (auto effectComponent = weakEffectComponent.lock()) {
|
||||||
this->effect->setValue(i, effectComponent->slider.getValue());
|
this->effect->setValue(i, effectComponent->slider.getValue());
|
||||||
|
@ -81,7 +81,7 @@ void EffectsListComponent::resized() {
|
||||||
|
|
||||||
int EffectsListBoxModel::getRowHeight(int row) {
|
int EffectsListBoxModel::getRowHeight(int row) {
|
||||||
auto data = (AudioEffectListBoxItemData&)modelData;
|
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||||
return data.getEffect(row)->details.size() * 30;
|
return data.getEffect(row)->parameters.size() * 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EffectsListBoxModel::hasVariableHeightRows() const {
|
bool EffectsListBoxModel::hasVariableHeightRows() const {
|
||||||
|
|
Ładowanie…
Reference in New Issue