kopia lustrzana https://github.com/jameshball/osci-render
Add LFO and LFO Rate as parameters
rodzic
e4bc512a66
commit
08458a4251
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {}
|
||||
};
|
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue