Add LFO and LFO Rate as parameters

pull/170/head
James Ball 2023-07-20 20:01:09 +01:00
rodzic e4bc512a66
commit 08458a4251
4 zmienionych plików z 175 dodań i 55 usunięć

Wyświetl plik

@ -106,8 +106,11 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
effects.insert(effects.end(), luaEffects.begin(), luaEffects.end());
for (auto effect : effects) {
for (auto parameter : effect->parameters) {
addParameter(parameter);
for (auto effectParameter : effect->parameters) {
auto parameters = effectParameter->getParameters();
for (auto parameter : parameters) {
addParameter(parameter);
}
}
}
}

Wyświetl plik

@ -55,16 +55,20 @@ void Effect::setPrecedence(int precedence) {
void Effect::addListener(int index, juce::AudioProcessorParameter::Listener* listener) {
parameters[index]->addListener(listener);
parameters[index]->lfo->addListener(listener);
parameters[index]->lfoRate->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);
}
parameters[index]->lfoRate->removeListener(listener);
parameters[index]->lfo->removeListener(listener);
parameters[index]->removeListener(listener);
}
void Effect::markEnableable(bool enable) {

Wyświetl plik

@ -2,94 +2,81 @@
#include "../shape/Vector2.h"
#include <JuceHeader.h>
enum class LfoType : int {
Static = 1,
Sine = 2,
Square = 3,
Seesaw = 4,
Triangle = 5,
Sawtooth = 6,
ReverseSawtooth = 7,
Noise = 8
};
class EffectParameter : public juce::AudioProcessorParameter {
class FloatParameter : 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;
std::atomic<LfoType> lfoType = LfoType::Static;
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) {}
FloatParameter(juce::String name, juce::String id, float value, float min, float max, float step = 0.001, juce::String label = "") : name(name), id(id), value(value), min(min), max(max), step(step), label(label) {}
juce::String getName(int maximumStringLength) const override {
return name.substring(0, maximumStringLength);
}
juce::String getLabel() const override {
return juce::String();
}
return label;
}
// 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();
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);
}
return (value - min) / (max - min);
}
float getUnnormalisedValue(float value) const {
value = juce::jlimit(0.0f, 1.0f, value);
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();
}
return value.load();
}
void setValue(float newValue) override {
value = getUnnormalisedValue(newValue);
}
}
void setValueUnnormalised(float newValue) {
value = newValue;
}
value = newValue;
}
void setUnnormalisedValueNotifyingHost(float newValue) {
setValueNotifyingHost(getNormalisedValue(newValue));
}
setValueNotifyingHost(getNormalisedValue(newValue));
}
float getDefaultValue() const override {
return 0.0f;
}
return 0.0f;
}
int getNumSteps() const override {
return (max.load() - min.load()) / step.load();
}
return (max.load() - min.load()) / step.load();
}
bool isDiscrete() const override {
return false;
}
return false;
}
bool isBoolean() const override {
return false;
}
return false;
}
bool isOrientationInverted() const override {
return false;
}
return false;
}
juce::String getText(float value, int maximumStringLength) const override {
auto string = juce::String(getUnnormalisedValue(value), 3);
@ -97,22 +84,148 @@ public:
}
float getValueForText(const juce::String& text) const override {
return getNormalisedValue(text.getFloatValue());
}
return getNormalisedValue(text.getFloatValue());
}
bool isAutomatable() const override {
return true;
}
return true;
}
bool isMetaParameter() const override {
return false;
}
return false;
}
juce::AudioProcessorParameter::Category getCategory() const override {
return juce::AudioProcessorParameter::genericParameter;
}
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;
juce::String label;
};
class IntParameter : public juce::AudioProcessorParameter {
public:
juce::String name;
juce::String id;
std::atomic<int> min = 0;
std::atomic<int> max = 10;
IntParameter(juce::String name, juce::String id, int value, int min, int max) : name(name), id(id), value(value), min(min), max(max) {}
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, (int) 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;
}
int getNumSteps() const override {
return max.load() - min.load() + 1;
}
bool isDiscrete() const override {
return true;
}
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((int) getUnnormalisedValue(value));
return string.substring(0, maximumStringLength);
}
float getValueForText(const juce::String& text) const override {
return getNormalisedValue(text.getIntValue());
}
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<int> value = 0;
};
enum class LfoType : int {
Static = 1,
Sine = 2,
Square = 3,
Seesaw = 4,
Triangle = 5,
Sawtooth = 6,
ReverseSawtooth = 7,
Noise = 8
};
class EffectParameter : public FloatParameter {
public:
std::atomic<bool> smoothValueChange = true;
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");
std::vector<juce::AudioProcessorParameter*> getParameters() {
return { this, lfo, lfoRate };
}
EffectParameter(juce::String name, juce::String id, float value, float min, float max, float step = 0.001, bool smoothValueChange = true) : FloatParameter(name, id, value, min, max, step), smoothValueChange(smoothValueChange) {}
};

Wyświetl plik

@ -42,11 +42,11 @@ void EffectComponent::setupComponent() {
bool enabled = effect.enabled == nullptr || effect.enabled->getValue();
selected.setToggleState(enabled, juce::dontSendNotification);
lfo.setSelectedId(static_cast<int>(parameter->lfoType.load()), juce::dontSendNotification);
lfo.setSelectedId(parameter->lfo->getValueUnnormalised(), juce::dontSendNotification);
lfo.onChange = [this]() {
if (lfo.getSelectedId() != 0) {
effect.parameters[index]->lfoType = static_cast<LfoType>(lfo.getSelectedId());
effect.parameters[index]->lfo->setUnnormalisedValueNotifyingHost(lfo.getSelectedId());
}
};