2023-03-28 12:44:46 +00:00
|
|
|
#pragma once
|
|
|
|
#include "../shape/Vector2.h"
|
|
|
|
#include <JuceHeader.h>
|
|
|
|
|
2023-07-17 16:16:18 +00:00
|
|
|
class EffectParameter : public juce::AudioProcessorParameter {
|
|
|
|
public:
|
2023-07-11 12:32:52 +00:00
|
|
|
juce::String name;
|
|
|
|
juce::String id;
|
2023-07-17 19:09:13 +00:00
|
|
|
|
|
|
|
std::atomic<float> min = 0.0;
|
|
|
|
std::atomic<float> max = 1.0;
|
|
|
|
std::atomic<float> step = 0.001;
|
2023-07-17 13:37:36 +00:00
|
|
|
std::atomic<bool> smoothValueChange = true;
|
|
|
|
|
2023-07-17 19:09:13 +00:00
|
|
|
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) {}
|
2023-07-17 13:37:36 +00:00
|
|
|
|
|
|
|
// COPY CONSTRUCTOR SHOULD ONLY BE USED BEFORE
|
|
|
|
// THE OBJECT IS USED IN MULTIPLE THREADS
|
2023-07-17 16:16:18 +00:00
|
|
|
EffectParameter(const EffectParameter& other) {
|
2023-07-17 13:37:36 +00:00
|
|
|
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());
|
|
|
|
}
|
2023-07-17 16:16:18 +00:00
|
|
|
|
|
|
|
juce::String getName(int maximumStringLength) const override {
|
|
|
|
return name.substring(0, maximumStringLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
juce::String getLabel() const override {
|
|
|
|
return juce::String();
|
|
|
|
}
|
2023-07-17 19:09:13 +00:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
2023-07-17 16:16:18 +00:00
|
|
|
|
|
|
|
float getValue() const override {
|
2023-07-17 19:09:13 +00:00
|
|
|
return getNormalisedValue(value.load());
|
2023-07-17 16:16:18 +00:00
|
|
|
}
|
|
|
|
|
2023-07-17 19:09:13 +00:00
|
|
|
float getValueUnnormalised() const {
|
|
|
|
return value.load();
|
|
|
|
}
|
|
|
|
|
2023-07-17 16:16:18 +00:00
|
|
|
void setValue(float newValue) override {
|
2023-07-17 19:09:13 +00:00
|
|
|
value = getUnnormalisedValue(newValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setValueUnnormalised(float newValue) {
|
|
|
|
value = newValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setUnnormalisedValueNotifyingHost(float newValue) {
|
|
|
|
setValueNotifyingHost(getNormalisedValue(newValue));
|
2023-07-17 16:16:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2023-07-17 19:09:13 +00:00
|
|
|
auto string = juce::String(getUnnormalisedValue(value), 3);
|
2023-07-17 16:16:18 +00:00
|
|
|
return string.substring(0, maximumStringLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
float getValueForText(const juce::String& text) const override {
|
2023-07-17 19:09:13 +00:00
|
|
|
return getNormalisedValue(text.getFloatValue());
|
2023-07-17 16:16:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isAutomatable() const override {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isMetaParameter() const override {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
juce::AudioProcessorParameter::Category getCategory() const override {
|
|
|
|
return juce::AudioProcessorParameter::genericParameter;
|
|
|
|
}
|
2023-07-17 19:09:13 +00:00
|
|
|
|
|
|
|
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;
|
2023-07-11 12:32:52 +00:00
|
|
|
};
|
|
|
|
|
2023-03-28 12:44:46 +00:00
|
|
|
class EffectApplication {
|
|
|
|
public:
|
|
|
|
EffectApplication() {};
|
|
|
|
|
2023-07-14 14:34:24 +00:00
|
|
|
virtual Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) = 0;
|
2023-03-28 13:33:56 +00:00
|
|
|
|
|
|
|
void resetPhase();
|
|
|
|
double nextPhase(double frequency, double sampleRate);
|
|
|
|
private:
|
|
|
|
double phase = 0.0;
|
2023-03-28 12:44:46 +00:00
|
|
|
};
|