kopia lustrzana https://github.com/jameshball/osci-render
Merge pull request #44 from jameshball/audio-plugin-parameters
Complete audio plugin parameter implementationpull/170/head
commit
4b40e650c0
|
@ -18,8 +18,8 @@ EffectsComponent::EffectsComponent(OscirenderAudioProcessor& p) : audioProcessor
|
|||
|
||||
{
|
||||
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
|
||||
for (int i = 0; i < audioProcessor.allEffects.size(); i++) {
|
||||
auto effect = audioProcessor.allEffects[i];
|
||||
for (int i = 0; i < audioProcessor.toggleableEffects.size(); i++) {
|
||||
auto effect = audioProcessor.toggleableEffects[i];
|
||||
effect->setValue(effect->getValue());
|
||||
itemData.data.push_back(effect);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "audio/BitCrushEffect.h"
|
||||
#include "audio/BulgeEffect.h"
|
||||
#include "audio/LuaEffect.h"
|
||||
#include "audio/EffectParameter.h"
|
||||
|
||||
//==============================================================================
|
||||
OscirenderAudioProcessor::OscirenderAudioProcessor()
|
||||
|
@ -35,44 +36,50 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
|
||||
juce::SpinLock::ScopedLockType lock(effectsLock);
|
||||
|
||||
allEffects.push_back(std::make_shared<Effect>(
|
||||
toggleableEffects.push_back(std::make_shared<Effect>(
|
||||
std::make_shared<BitCrushEffect>(),
|
||||
std::vector<EffectParameter>(1, { "Bit Crush", "bitCrush", 0.0, 0.0, 1.0 })
|
||||
new EffectParameter("Bit Crush", "bitCrush", 0.0, 0.0, 1.0)
|
||||
));
|
||||
allEffects.push_back(std::make_shared<Effect>(
|
||||
toggleableEffects.push_back(std::make_shared<Effect>(
|
||||
std::make_shared<BulgeEffect>(),
|
||||
std::vector<EffectParameter>(1, { "Bulge", "bulge", 0.0, 0.0, 1.0 })
|
||||
new EffectParameter("Bulge", "bulge", 0.0, 0.0, 1.0)
|
||||
));
|
||||
allEffects.push_back(std::make_shared<Effect>(
|
||||
toggleableEffects.push_back(std::make_shared<Effect>(
|
||||
std::make_shared<RotateEffect>(),
|
||||
std::vector<EffectParameter>(1, { "2D Rotate Speed", "rotateSpeed", 0.0, 0.0, 1.0 })
|
||||
new EffectParameter("2D Rotate Speed", "rotateSpeed", 0.0, 0.0, 1.0)
|
||||
));
|
||||
allEffects.push_back(std::make_shared<Effect>(
|
||||
toggleableEffects.push_back(std::make_shared<Effect>(
|
||||
std::make_shared<VectorCancellingEffect>(),
|
||||
std::vector<EffectParameter>(1, { "Vector cancelling", "vectorCancelling", 0.0, 0.0, 1.0 })
|
||||
new EffectParameter("Vector cancelling", "vectorCancelling", 0.0, 0.0, 1.0)
|
||||
));
|
||||
allEffects.push_back(std::make_shared<Effect>(
|
||||
toggleableEffects.push_back(std::make_shared<Effect>(
|
||||
std::make_shared<DistortEffect>(true),
|
||||
std::vector<EffectParameter>(1, { "Vertical shift", "verticalDistort", 0.0, 0.0, 1.0 })
|
||||
new EffectParameter("Vertical shift", "verticalDistort", 0.0, 0.0, 1.0)
|
||||
));
|
||||
allEffects.push_back(std::make_shared<Effect>(
|
||||
toggleableEffects.push_back(std::make_shared<Effect>(
|
||||
std::make_shared<DistortEffect>(false),
|
||||
std::vector<EffectParameter>(1, { "Horizontal shift", "horizontalDistort", 0.0, 0.0, 1.0 })
|
||||
new EffectParameter("Horizontal shift", "horizontalDistort", 0.0, 0.0, 1.0)
|
||||
));
|
||||
allEffects.push_back(std::make_shared<Effect>(
|
||||
toggleableEffects.push_back(std::make_shared<Effect>(
|
||||
std::make_shared<SmoothEffect>(),
|
||||
std::vector<EffectParameter>(1, { "Smoothing", "smoothing", 0.0, 0.0, 1.0 })
|
||||
new EffectParameter("Smoothing", "smoothing", 0.0, 0.0, 1.0)
|
||||
));
|
||||
allEffects.push_back(std::make_shared<Effect>(
|
||||
toggleableEffects.push_back(std::make_shared<Effect>(
|
||||
wobbleEffect,
|
||||
std::vector<EffectParameter>(1, { "Wobble", "wobble", 0.0, 0.0, 1.0 })
|
||||
new EffectParameter("Wobble", "wobble", 0.0, 0.0, 1.0)
|
||||
));
|
||||
allEffects.push_back(std::make_shared<Effect>(
|
||||
toggleableEffects.push_back(std::make_shared<Effect>(
|
||||
delayEffect,
|
||||
std::vector<EffectParameter>{{ "Delay Decay", "delayDecay", 0.0, 0.0, 1.0 }, { "Delay Length", "delayEchoLength", 0.5, 0.0, 1.0 }}
|
||||
std::vector<EffectParameter*>{new EffectParameter("Delay Decay", "delayDecay", 0.0, 0.0, 1.0), new EffectParameter("Delay Length", "delayEchoLength", 0.5, 0.0, 1.0)}
|
||||
));
|
||||
allEffects.push_back(traceMax);
|
||||
allEffects.push_back(traceMin);
|
||||
toggleableEffects.push_back(traceMax);
|
||||
toggleableEffects.push_back(traceMin);
|
||||
|
||||
for (auto& effect : toggleableEffects) {
|
||||
effect->markEnableable(false);
|
||||
addParameter(effect->enabled);
|
||||
effect->enabled->setValueNotifyingHost(false);
|
||||
}
|
||||
|
||||
permanentEffects.push_back(frequencyEffect);
|
||||
permanentEffects.push_back(volumeEffect);
|
||||
|
@ -87,19 +94,29 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
addLuaSlider();
|
||||
}
|
||||
|
||||
auto effects = allEffects;
|
||||
auto effects = toggleableEffects;
|
||||
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);
|
||||
for (auto parameter : effect->parameters) {
|
||||
addParameter(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
hiddenEffects.push_back(currentRotateX);
|
||||
hiddenEffects.push_back(currentRotateY);
|
||||
hiddenEffects.push_back(currentRotateZ);
|
||||
}
|
||||
|
||||
OscirenderAudioProcessor::~OscirenderAudioProcessor() {
|
||||
for (auto effect : hiddenEffects) {
|
||||
for (auto parameter : effect->parameters) {
|
||||
delete parameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OscirenderAudioProcessor::~OscirenderAudioProcessor() {}
|
||||
|
||||
const juce::String OscirenderAudioProcessor::getName() const {
|
||||
return JucePlugin_Name;
|
||||
}
|
||||
|
@ -199,7 +216,7 @@ void OscirenderAudioProcessor::addLuaSlider() {
|
|||
|
||||
luaEffects.push_back(std::make_shared<Effect>(
|
||||
std::make_shared<LuaEffect>(sliderName, *this),
|
||||
std::vector<EffectParameter>(1, { "Lua " + sliderName, "lua" + sliderName, 0.0, 0.0, 1.0, 0.001, false })
|
||||
new EffectParameter("Lua " + sliderName, "lua" + sliderName, 0.0, 0.0, 1.0, 0.001, false)
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -219,43 +236,12 @@ void OscirenderAudioProcessor::updateObjValues() {
|
|||
rotateSpeed->apply();
|
||||
}
|
||||
|
||||
// effectsLock MUST be held when calling this
|
||||
void OscirenderAudioProcessor::enableEffect(std::shared_ptr<Effect> effect) {
|
||||
// remove any existing effects with the same id
|
||||
for (auto it = enabledEffects.begin(); it != enabledEffects.end();) {
|
||||
if ((*it)->getId() == effect->getId()) {
|
||||
it = enabledEffects.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
// insert according to precedence (sorts from lowest to highest precedence)
|
||||
auto it = enabledEffects.begin();
|
||||
while (it != enabledEffects.end() && (*it)->getPrecedence() <= effect->getPrecedence()) {
|
||||
it++;
|
||||
}
|
||||
enabledEffects.insert(it, effect);
|
||||
}
|
||||
|
||||
// effectsLock MUST be held when calling this
|
||||
void OscirenderAudioProcessor::disableEffect(std::shared_ptr<Effect> effect) {
|
||||
// remove any existing effects with the same id
|
||||
for (auto it = enabledEffects.begin(); it != enabledEffects.end();) {
|
||||
if ((*it)->getId() == effect->getId()) {
|
||||
it = enabledEffects.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// effectsLock MUST be held when calling this
|
||||
void OscirenderAudioProcessor::updateEffectPrecedence() {
|
||||
auto sortFunc = [](std::shared_ptr<Effect> a, std::shared_ptr<Effect> b) {
|
||||
return a->getPrecedence() < b->getPrecedence();
|
||||
};
|
||||
std::sort(enabledEffects.begin(), enabledEffects.end(), sortFunc);
|
||||
std::sort(allEffects.begin(), allEffects.end(), sortFunc);
|
||||
std::sort(toggleableEffects.begin(), toggleableEffects.end(), sortFunc);
|
||||
}
|
||||
|
||||
// parsersLock AND effectsLock must be locked before calling this function
|
||||
|
@ -465,8 +451,10 @@ void OscirenderAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, ju
|
|||
|
||||
{
|
||||
juce::SpinLock::ScopedLockType lock(effectsLock);
|
||||
for (auto& effect : enabledEffects) {
|
||||
channels = effect->apply(sample, channels);
|
||||
for (auto& effect : toggleableEffects) {
|
||||
if (effect->enabled->getValue()) {
|
||||
channels = effect->apply(sample, channels);
|
||||
}
|
||||
}
|
||||
for (auto& effect : permanentEffects) {
|
||||
channels = effect->apply(sample, channels);
|
||||
|
|
|
@ -71,29 +71,28 @@ public:
|
|||
std::atomic<double> currentSampleRate = 0.0;
|
||||
|
||||
juce::SpinLock effectsLock;
|
||||
std::vector<std::shared_ptr<Effect>> allEffects;
|
||||
std::vector<std::shared_ptr<Effect>> enabledEffects;
|
||||
std::vector<std::shared_ptr<Effect>> toggleableEffects;
|
||||
std::vector<std::shared_ptr<Effect>> luaEffects;
|
||||
|
||||
std::shared_ptr<Effect> frequencyEffect = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
frequency = values[0];
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Frequency", "frequency", 440.0, 0.0, 12000.0, 0.1 })
|
||||
}, new EffectParameter("Frequency", "frequency", 440.0, 0.0, 12000.0, 0.1)
|
||||
);
|
||||
|
||||
std::shared_ptr<Effect> volumeEffect = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
volume = values[0];
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Volume", "volume", 1.0, 0.0, 3.0 })
|
||||
}, new EffectParameter("Volume", "volume", 1.0, 0.0, 3.0)
|
||||
);
|
||||
|
||||
std::shared_ptr<Effect> thresholdEffect = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
threshold = values[0];
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Threshold", "threshold", 3.0, 0.0, 3.0 })
|
||||
}, new EffectParameter("Threshold", "threshold", 1.0, 0.0, 1.0)
|
||||
);
|
||||
|
||||
std::shared_ptr<Effect> focalLength = std::make_shared<Effect>(
|
||||
|
@ -104,7 +103,7 @@ public:
|
|||
camera->setFocalLength(values[0]);
|
||||
}
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Focal length", "focalLength", 1.0, 0.0, 2.0 })
|
||||
}, new EffectParameter("Focal length", "focalLength", 1.0, 0.0, 2.0)
|
||||
);
|
||||
std::shared_ptr<Effect> rotateX = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
|
@ -114,7 +113,7 @@ public:
|
|||
obj->setBaseRotationX(values[0] * std::numbers::pi);
|
||||
}
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Rotate x", "rotateX", 1.0, -1.0, 1.0 })
|
||||
}, new EffectParameter("Rotate x", "rotateX", 1.0, -1.0, 1.0)
|
||||
);
|
||||
std::shared_ptr<Effect> rotateY = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
|
@ -124,7 +123,7 @@ public:
|
|||
obj->setBaseRotationY(values[0] * std::numbers::pi);
|
||||
}
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Rotate y", "rotateY", 1.0, -1.0, 1.0 })
|
||||
}, new EffectParameter("Rotate y", "rotateY", 1.0, -1.0, 1.0)
|
||||
);
|
||||
std::shared_ptr<Effect> rotateZ = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
|
@ -134,7 +133,7 @@ public:
|
|||
obj->setBaseRotationZ(values[0] * std::numbers::pi);
|
||||
}
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Rotate z", "rotateZ", 0.0, -1.0, 1.0 })
|
||||
}, new EffectParameter("Rotate z", "rotateZ", 0.0, -1.0, 1.0)
|
||||
);
|
||||
std::shared_ptr<Effect> currentRotateX = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
|
@ -144,7 +143,7 @@ public:
|
|||
obj->setCurrentRotationX(values[0] * std::numbers::pi);
|
||||
}
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Current Rotate x", "currentRotateX", 0.0, 0.0, 1.0, 0.001, false })
|
||||
}, new EffectParameter("Current Rotate x", "currentRotateX", 0.0, 0.0, 1.0, 0.001, false)
|
||||
);
|
||||
std::shared_ptr<Effect> currentRotateY = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
|
@ -154,7 +153,7 @@ public:
|
|||
obj->setCurrentRotationY(values[0] * std::numbers::pi);
|
||||
}
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Current Rotate y", "currentRotateY", 0.0, 0.0, 1.0, 0.001, false })
|
||||
}, new EffectParameter("Current Rotate y", "currentRotateY", 0.0, 0.0, 1.0, 0.001, false)
|
||||
);
|
||||
std::shared_ptr<Effect> currentRotateZ = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
|
@ -164,7 +163,7 @@ public:
|
|||
obj->setCurrentRotationZ(values[0] * std::numbers::pi);
|
||||
}
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Current Rotate z", "currentRotateZ", 0.0, 0.0, 1.0, 0.001, false })
|
||||
}, new EffectParameter("Current Rotate z", "currentRotateZ", 0.0, 0.0, 1.0, 0.001, false)
|
||||
);
|
||||
std::shared_ptr<Effect> rotateSpeed = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
|
@ -174,7 +173,7 @@ public:
|
|||
obj->setRotationSpeed(values[0]);
|
||||
}
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Rotate speed", "rotateSpeed", 0.0, -1.0, 1.0 })
|
||||
}, new EffectParameter("Rotate speed", "rotateSpeed", 0.0, -1.0, 1.0)
|
||||
);
|
||||
std::atomic<bool> fixedRotateX = false;
|
||||
std::atomic<bool> fixedRotateY = false;
|
||||
|
@ -197,8 +196,6 @@ public:
|
|||
|
||||
void addLuaSlider();
|
||||
void addFrame(std::vector<std::unique_ptr<Shape>> frame, int fileIndex) override;
|
||||
void enableEffect(std::shared_ptr<Effect> effect);
|
||||
void disableEffect(std::shared_ptr<Effect> effect);
|
||||
void updateEffectPrecedence();
|
||||
void updateFileBlock(int index, std::shared_ptr<juce::MemoryBlock> block);
|
||||
void addFile(juce::File file);
|
||||
|
@ -230,20 +227,23 @@ private:
|
|||
bool invalidateFrameBuffer = false;
|
||||
|
||||
std::vector<std::shared_ptr<Effect>> permanentEffects;
|
||||
// any effects that are not added as a plugin parameter must be deleted manually
|
||||
// as JUCE will not delete them upon destruction of the AudioProcessor
|
||||
std::vector<std::shared_ptr<Effect>> hiddenEffects;
|
||||
|
||||
std::shared_ptr<Effect> traceMax = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
traceMaxValue = values[0];
|
||||
traceMaxEnabled = true;
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Trace max", "traceMax", 1.0, 0.0, 1.0 })
|
||||
}, new EffectParameter("Trace max", "traceMax", 1.0, 0.0, 1.0)
|
||||
);
|
||||
std::shared_ptr<Effect> traceMin = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
traceMinValue = values[0];
|
||||
traceMinEnabled = true;
|
||||
return input;
|
||||
}, std::vector<EffectParameter>(1, { "Trace min", "traceMin", 0.0, 0.0, 1.0 })
|
||||
}, new EffectParameter("Trace min", "traceMin", 0.0, 0.0, 1.0)
|
||||
);
|
||||
const double MIN_TRACE = 0.005;
|
||||
double traceMaxValue = traceMax->getValue();
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
#pragma once
|
||||
#include "../shape/Vector2.h"
|
||||
#include <JuceHeader.h>
|
||||
|
||||
class BooleanParameter : public juce::AudioProcessorParameter {
|
||||
public:
|
||||
juce::String name;
|
||||
juce::String id;
|
||||
|
||||
BooleanParameter(juce::String name, juce::String id, bool value) : name(name), id(id), value(value) {}
|
||||
|
||||
// COPY CONSTRUCTOR SHOULD ONLY BE USED BEFORE
|
||||
// THE OBJECT IS USED IN MULTIPLE THREADS
|
||||
BooleanParameter(const BooleanParameter& other) {
|
||||
name = other.name;
|
||||
id = other.id;
|
||||
value.store(other.value.load());
|
||||
}
|
||||
|
||||
juce::String getName(int maximumStringLength) const override {
|
||||
return name.substring(0, maximumStringLength);
|
||||
}
|
||||
|
||||
juce::String getLabel() const override {
|
||||
return juce::String();
|
||||
}
|
||||
|
||||
float getValue() const override {
|
||||
return value.load();
|
||||
}
|
||||
|
||||
void setValue(float newValue) override {
|
||||
value.store(newValue >= 0.5f);
|
||||
}
|
||||
|
||||
float getDefaultValue() const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
int getNumSteps() const override {
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool isDiscrete() const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isBoolean() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isOrientationInverted() const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
juce::String getText(float value, int maximumStringLength) const override {
|
||||
juce::String string = value ? "true" : "false";
|
||||
return string.substring(0, maximumStringLength);
|
||||
}
|
||||
|
||||
float getValueForText(const juce::String& text) const override {
|
||||
return text.length() > 0 && text.toLowerCase()[0] == 't';
|
||||
}
|
||||
|
||||
bool isAutomatable() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isMetaParameter() const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
juce::AudioProcessorParameter::Category getCategory() const override {
|
||||
return juce::AudioProcessorParameter::genericParameter;
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<bool> value = false;
|
||||
};
|
|
@ -1,21 +1,21 @@
|
|||
#include "Effect.h"
|
||||
|
||||
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectParameter> parameters) : effectApplication(effectApplication), parameters(parameters) {
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
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();
|
||||
double weight = parameters[i]->smoothValueChange ? 0.0005 : 1.0;
|
||||
smoothValues[i] = (1.0 - weight) * smoothValues[i] + weight * parameters[i]->getValueUnnormalised();
|
||||
}
|
||||
if (application) {
|
||||
return application(index, input, smoothValues, sampleRate);
|
||||
|
@ -30,7 +30,7 @@ void Effect::apply() {
|
|||
}
|
||||
|
||||
double Effect::getValue(int index) {
|
||||
return parameters[index].getValueUnnormalised();
|
||||
return parameters[index]->getValueUnnormalised();
|
||||
}
|
||||
|
||||
double Effect::getValue() {
|
||||
|
@ -38,7 +38,7 @@ double Effect::getValue() {
|
|||
}
|
||||
|
||||
void Effect::setValue(int index, double value) {
|
||||
parameters[index].setUnnormalisedValueNotifyingHost(value);
|
||||
parameters[index]->setUnnormalisedValueNotifyingHost(value);
|
||||
}
|
||||
|
||||
void Effect::setValue(double value) {
|
||||
|
@ -53,10 +53,32 @@ void Effect::setPrecedence(int precedence) {
|
|||
this->precedence = precedence;
|
||||
}
|
||||
|
||||
void Effect::addListener(int index, juce::AudioProcessorParameter::Listener* listener) {
|
||||
parameters[index]->addListener(listener);
|
||||
if (enabled != nullptr) {
|
||||
enabled->addListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
void Effect::removeListener(int index, juce::AudioProcessorParameter::Listener* listener) {
|
||||
parameters[index]->removeListener(listener);
|
||||
if (enabled != nullptr) {
|
||||
enabled->removeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
void Effect::markEnableable(bool enable) {
|
||||
if (enabled != nullptr) {
|
||||
enabled->setValue(enable);
|
||||
} else {
|
||||
enabled = new BooleanParameter(getName() + " Enabled", getId() + "Enabled", enable);
|
||||
}
|
||||
}
|
||||
|
||||
juce::String Effect::getId() {
|
||||
return parameters[0].id;
|
||||
return parameters[0]->id;
|
||||
}
|
||||
|
||||
juce::String Effect::getName() {
|
||||
return parameters[0].name;
|
||||
return parameters[0]->name;
|
||||
}
|
||||
|
|
|
@ -2,13 +2,16 @@
|
|||
#include "../shape/Vector2.h"
|
||||
#include <JuceHeader.h>
|
||||
#include "EffectApplication.h"
|
||||
#include "EffectParameter.h"
|
||||
#include "BooleanParameter.h"
|
||||
|
||||
|
||||
class Effect {
|
||||
public:
|
||||
Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectParameter> parameters);
|
||||
Effect(std::shared_ptr<EffectApplication> effectApplication, EffectParameter parameter);
|
||||
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, EffectParameter parameter);
|
||||
Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectParameter*> parameters);
|
||||
Effect(std::shared_ptr<EffectApplication> effectApplication, EffectParameter* parameter);
|
||||
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, EffectParameter* parameter);
|
||||
|
||||
Vector2 apply(int index, Vector2 input);
|
||||
void apply();
|
||||
|
@ -18,13 +21,18 @@ public:
|
|||
void setValue(double value);
|
||||
int getPrecedence();
|
||||
void setPrecedence(int precedence);
|
||||
void addListener(int index, juce::AudioProcessorParameter::Listener* listener);
|
||||
void removeListener(int index, juce::AudioProcessorParameter::Listener* listener);
|
||||
void markEnableable(bool enabled);
|
||||
juce::String getId();
|
||||
juce::String getName();
|
||||
|
||||
std::vector<EffectParameter> parameters;
|
||||
std::vector<EffectParameter*> parameters;
|
||||
BooleanParameter* enabled;
|
||||
|
||||
private:
|
||||
|
||||
juce::SpinLock listenerLock;
|
||||
std::vector<double> smoothValues;
|
||||
double frequency = 1.0;
|
||||
int precedence = -1;
|
||||
|
|
|
@ -2,121 +2,6 @@
|
|||
#include "../shape/Vector2.h"
|
||||
#include <JuceHeader.h>
|
||||
|
||||
class EffectParameter : public juce::AudioProcessorParameter {
|
||||
public:
|
||||
juce::String name;
|
||||
juce::String id;
|
||||
|
||||
std::atomic<float> min = 0.0;
|
||||
std::atomic<float> max = 1.0;
|
||||
std::atomic<float> step = 0.001;
|
||||
std::atomic<bool> smoothValueChange = true;
|
||||
|
||||
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
|
||||
// THE OBJECT IS USED IN MULTIPLE THREADS
|
||||
EffectParameter(const EffectParameter& other) {
|
||||
name = other.name;
|
||||
id = other.id;
|
||||
value.store(other.value.load());
|
||||
min.store(other.min.load());
|
||||
max.store(other.max.load());
|
||||
step.store(other.step.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 {
|
||||
public:
|
||||
EffectApplication() {};
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
#pragma once
|
||||
#include "../shape/Vector2.h"
|
||||
#include <JuceHeader.h>
|
||||
|
||||
class EffectParameter : public juce::AudioProcessorParameter {
|
||||
public:
|
||||
juce::String name;
|
||||
juce::String id;
|
||||
|
||||
std::atomic<float> min = 0.0;
|
||||
std::atomic<float> max = 1.0;
|
||||
std::atomic<float> step = 0.001;
|
||||
std::atomic<bool> smoothValueChange = true;
|
||||
|
||||
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) {}
|
||||
|
||||
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;
|
||||
};
|
|
@ -1,7 +1,10 @@
|
|||
#include "EffectComponent.h"
|
||||
|
||||
EffectComponent::EffectComponent(Effect& effect, int index) : effect(effect), index(index) {
|
||||
componentSetup();
|
||||
addAndMakeVisible(slider);
|
||||
addAndMakeVisible(selected);
|
||||
effect.addListener(index, this);
|
||||
setupComponent();
|
||||
}
|
||||
|
||||
EffectComponent::EffectComponent(Effect& effect, int index, bool checkboxVisible) : EffectComponent(effect, index) {
|
||||
|
@ -14,52 +17,52 @@ EffectComponent::EffectComponent(Effect& effect, bool checkboxVisible) : EffectC
|
|||
setCheckboxVisible(checkboxVisible);
|
||||
}
|
||||
|
||||
void EffectComponent::componentSetup() {
|
||||
addAndMakeVisible(slider);
|
||||
addAndMakeVisible(selected);
|
||||
void EffectComponent::setupComponent() {
|
||||
EffectParameter* parameter = effect.parameters[index];
|
||||
|
||||
EffectParameter& parameter = effect.parameters[index];
|
||||
|
||||
slider.setRange(parameter.min, parameter.max, parameter.step);
|
||||
slider.setValue(parameter.getValueUnnormalised(), juce::dontSendNotification);
|
||||
slider.setRange(parameter->min, parameter->max, parameter->step);
|
||||
slider.setValue(parameter->getValueUnnormalised(), juce::dontSendNotification);
|
||||
|
||||
slider.setSliderStyle(juce::Slider::LinearHorizontal);
|
||||
slider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 90, slider.getTextBoxHeight());
|
||||
|
||||
selected.setToggleState(false, juce::dontSendNotification);
|
||||
bool enabled = effect.enabled == nullptr || effect.enabled->getValue();
|
||||
selected.setToggleState(enabled, juce::dontSendNotification);
|
||||
|
||||
min.textBox.setValue(parameter.min, juce::dontSendNotification);
|
||||
max.textBox.setValue(parameter.max, juce::dontSendNotification);
|
||||
min.textBox.setValue(parameter->min, juce::dontSendNotification);
|
||||
max.textBox.setValue(parameter->max, juce::dontSendNotification);
|
||||
|
||||
min.textBox.onValueChange = [this]() {
|
||||
double minValue = min.textBox.getValue();
|
||||
double maxValue = max.textBox.getValue();
|
||||
if (minValue >= maxValue) {
|
||||
minValue = maxValue - effect.parameters[index].step;
|
||||
minValue = maxValue - effect.parameters[index]->step;
|
||||
min.textBox.setValue(minValue, juce::dontSendNotification);
|
||||
}
|
||||
effect.parameters[index].min = minValue;
|
||||
slider.setRange(effect.parameters[index].min, effect.parameters[index].max, effect.parameters[index].step);
|
||||
effect.parameters[index]->min = minValue;
|
||||
slider.setRange(effect.parameters[index]->min, effect.parameters[index]->max, effect.parameters[index]->step);
|
||||
};
|
||||
|
||||
max.textBox.onValueChange = [this]() {
|
||||
double minValue = min.textBox.getValue();
|
||||
double maxValue = max.textBox.getValue();
|
||||
if (maxValue <= minValue) {
|
||||
maxValue = minValue + effect.parameters[index].step;
|
||||
maxValue = minValue + effect.parameters[index]->step;
|
||||
max.textBox.setValue(maxValue, juce::dontSendNotification);
|
||||
}
|
||||
effect.parameters[index].max = maxValue;
|
||||
slider.setRange(effect.parameters[index].min, effect.parameters[index].max, effect.parameters[index].step);
|
||||
effect.parameters[index]->max = maxValue;
|
||||
slider.setRange(effect.parameters[index]->min, effect.parameters[index]->max, effect.parameters[index]->step);
|
||||
};
|
||||
|
||||
popupLabel.setText(parameter.name + " Settings", juce::dontSendNotification);
|
||||
popupLabel.setText(parameter->name + " Settings", juce::dontSendNotification);
|
||||
popupLabel.setJustificationType(juce::Justification::centred);
|
||||
popupLabel.setFont(juce::Font(14.0f, juce::Font::bold));
|
||||
}
|
||||
|
||||
|
||||
EffectComponent::~EffectComponent() {}
|
||||
EffectComponent::~EffectComponent() {
|
||||
effect.removeListener(index, this);
|
||||
}
|
||||
|
||||
void EffectComponent::resized() {
|
||||
auto sliderRight = getWidth() - 160;
|
||||
|
@ -82,7 +85,7 @@ void EffectComponent::resized() {
|
|||
void EffectComponent::paint(juce::Graphics& g) {
|
||||
g.fillAll(juce::Colours::black);
|
||||
g.setColour(juce::Colours::white);
|
||||
g.drawText(effect.parameters[index].name, textBounds, juce::Justification::left);
|
||||
g.drawText(effect.parameters[index]->name, textBounds, juce::Justification::left);
|
||||
}
|
||||
|
||||
void EffectComponent::mouseDown(const juce::MouseEvent& event) {
|
||||
|
@ -97,6 +100,16 @@ void EffectComponent::mouseDown(const juce::MouseEvent& event) {
|
|||
}
|
||||
}
|
||||
|
||||
void EffectComponent::parameterValueChanged(int parameterIndex, float newValue) {
|
||||
triggerAsyncUpdate();
|
||||
}
|
||||
|
||||
void EffectComponent::parameterGestureChanged(int parameterIndex, bool gestureIsStarting) {}
|
||||
|
||||
void EffectComponent::handleAsyncUpdate() {
|
||||
setupComponent();
|
||||
}
|
||||
|
||||
void EffectComponent::setComponent(std::shared_ptr<juce::Component> component) {
|
||||
this->component = component;
|
||||
addAndMakeVisible(component.get());
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "LabelledTextBox.h"
|
||||
|
||||
|
||||
class EffectComponent : public juce::Component {
|
||||
class EffectComponent : public juce::Component, public juce::AudioProcessorParameter::Listener, juce::AsyncUpdater {
|
||||
public:
|
||||
EffectComponent(Effect& effect, int index);
|
||||
EffectComponent(Effect& effect, int index, bool checkboxVisible);
|
||||
|
@ -16,6 +16,9 @@ public:
|
|||
void resized() override;
|
||||
void paint(juce::Graphics& g) override;
|
||||
void mouseDown(const juce::MouseEvent& event) override;
|
||||
void parameterValueChanged(int parameterIndex, float newValue) override;
|
||||
void parameterGestureChanged(int parameterIndex, bool gestureIsStarting) override;
|
||||
void handleAsyncUpdate() override;
|
||||
|
||||
void setCheckboxVisible(bool visible);
|
||||
void setComponent(std::shared_ptr<juce::Component> component);
|
||||
|
@ -26,7 +29,7 @@ public:
|
|||
juce::ToggleButton selected;
|
||||
|
||||
private:
|
||||
void componentSetup();
|
||||
void setupComponent();
|
||||
bool checkboxVisible = true;
|
||||
juce::Rectangle<int> textBounds;
|
||||
std::shared_ptr<juce::Component> component;
|
||||
|
|
|
@ -6,7 +6,7 @@ EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectList
|
|||
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(*effect, i, i == 0);
|
||||
// using weak_ptr to avoid circular reference and memory leak
|
||||
std::weak_ptr<EffectComponent> weakEffectComponent = effectComponent;
|
||||
effectComponent->slider.setValue(parameters[i].getValueUnnormalised(), juce::dontSendNotification);
|
||||
effectComponent->slider.setValue(parameters[i]->getValueUnnormalised(), juce::dontSendNotification);
|
||||
effectComponent->slider.onValueChange = [this, i, weakEffectComponent] {
|
||||
if (auto effectComponent = weakEffectComponent.lock()) {
|
||||
this->effect->setValue(i, effectComponent->slider.getValue());
|
||||
|
@ -14,19 +14,6 @@ EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectList
|
|||
};
|
||||
|
||||
if (i == 0) {
|
||||
bool isSelected = false;
|
||||
|
||||
{
|
||||
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
|
||||
// check if effect is in audioProcessor enabled effects
|
||||
for (auto processorEffect : data.audioProcessor.enabledEffects) {
|
||||
if (processorEffect->getId() == effect->getId()) {
|
||||
isSelected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
effectComponent->selected.setToggleState(isSelected, juce::dontSendNotification);
|
||||
effectComponent->selected.onClick = [this, weakEffectComponent] {
|
||||
if (auto effectComponent = weakEffectComponent.lock()) {
|
||||
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||
|
|
|
@ -74,9 +74,9 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
|||
|
||||
void setSelected(int itemIndex, bool selected) {
|
||||
if (selected) {
|
||||
audioProcessor.enableEffect(data[itemIndex]);
|
||||
data[itemIndex]->enabled->setValueNotifyingHost(true);
|
||||
} else {
|
||||
audioProcessor.disableEffect(data[itemIndex]);
|
||||
data[itemIndex]->enabled->setValueNotifyingHost(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,9 @@ VolumeComponent::VolumeComponent(OscirenderAudioProcessor& p) : audioProcessor(p
|
|||
volumeSlider.setColour(juce::Slider::ColourIds::backgroundColourId, juce::Colours::transparentWhite);
|
||||
volumeSlider.setColour(juce::Slider::ColourIds::trackColourId, juce::Colours::transparentWhite);
|
||||
volumeSlider.setOpaque(false);
|
||||
volumeSlider.setRange(0, 2, 0.001);
|
||||
volumeSlider.setValue(1);
|
||||
auto volumeParam = audioProcessor.volumeEffect->parameters[0];
|
||||
volumeSlider.setRange(volumeParam->min, volumeParam->max, volumeParam->step);
|
||||
volumeSlider.setValue(volumeParam->getValueUnnormalised());
|
||||
volumeSlider.setLookAndFeel(&thumbRadiusLookAndFeel);
|
||||
volumeSlider.setColour(juce::Slider::ColourIds::thumbColourId, juce::Colours::black);
|
||||
|
||||
|
@ -22,8 +23,9 @@ VolumeComponent::VolumeComponent(OscirenderAudioProcessor& p) : audioProcessor(p
|
|||
thresholdSlider.setColour(juce::Slider::ColourIds::backgroundColourId, juce::Colours::transparentWhite);
|
||||
thresholdSlider.setColour(juce::Slider::ColourIds::trackColourId, juce::Colours::transparentWhite);
|
||||
thresholdSlider.setOpaque(false);
|
||||
thresholdSlider.setRange(0, 1, 0.001);
|
||||
thresholdSlider.setValue(1);
|
||||
auto& thresholdParam = audioProcessor.thresholdEffect->parameters[0];
|
||||
thresholdSlider.setRange(thresholdParam->min, thresholdParam->max, thresholdParam->step);
|
||||
thresholdSlider.setValue(thresholdParam->getValueUnnormalised());
|
||||
thresholdSlider.setLookAndFeel(&thresholdLookAndFeel);
|
||||
thresholdSlider.setColour(juce::Slider::ColourIds::thumbColourId, juce::Colours::black);
|
||||
|
||||
|
@ -85,6 +87,8 @@ void VolumeComponent::paint(juce::Graphics& g) {
|
|||
|
||||
void VolumeComponent::timerCallback() {
|
||||
repaint();
|
||||
volumeSlider.setValue(audioProcessor.volumeEffect->getValue(), juce::NotificationType::dontSendNotification);
|
||||
thresholdSlider.setValue(audioProcessor.thresholdEffect->getValue(), juce::NotificationType::dontSendNotification);
|
||||
}
|
||||
|
||||
void VolumeComponent::run() {
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
file="Source/audio/BitCrushEffect.cpp"/>
|
||||
<FILE id="Bc8UeW" name="BitCrushEffect.h" compile="0" resource="0"
|
||||
file="Source/audio/BitCrushEffect.h"/>
|
||||
<FILE id="S5ChqG" name="BooleanParameter.h" compile="0" resource="0"
|
||||
file="Source/audio/BooleanParameter.h"/>
|
||||
<FILE id="ATOFA9" name="BulgeEffect.cpp" compile="1" resource="0" file="Source/audio/BulgeEffect.cpp"/>
|
||||
<FILE id="lOXxYe" name="BulgeEffect.h" compile="0" resource="0" file="Source/audio/BulgeEffect.h"/>
|
||||
<FILE id="e6SZox" name="DelayEffect.cpp" compile="1" resource="0" file="Source/audio/DelayEffect.cpp"/>
|
||||
|
@ -48,6 +50,8 @@
|
|||
file="Source/audio/EffectApplication.cpp"/>
|
||||
<FILE id="MIYJ9y" name="EffectApplication.h" compile="0" resource="0"
|
||||
file="Source/audio/EffectApplication.h"/>
|
||||
<FILE id="aE0RtD" name="EffectParameter.h" compile="0" resource="0"
|
||||
file="Source/audio/EffectParameter.h"/>
|
||||
<FILE id="uhyh7T" name="LuaEffect.cpp" compile="1" resource="0" file="Source/audio/LuaEffect.cpp"/>
|
||||
<FILE id="jqDcZq" name="LuaEffect.h" compile="0" resource="0" file="Source/audio/LuaEffect.h"/>
|
||||
<FILE id="t2bsR8" name="PitchDetector.cpp" compile="1" resource="0"
|
||||
|
|
Ładowanie…
Reference in New Issue