kopia lustrzana https://github.com/jameshball/osci-render
Remove LFO support for Lua and remove 'infinite' lua sliders as you cannot dynamically add parameters
rodzic
4520771b15
commit
34adbc767d
|
@ -23,7 +23,7 @@ private:
|
|||
EffectsListBoxModel listBoxModel;
|
||||
DraggableListBox listBox;
|
||||
|
||||
EffectComponent frequency = EffectComponent(*audioProcessor.frequencyEffect, false);
|
||||
EffectComponent frequency = EffectComponent(audioProcessor, *audioProcessor.frequencyEffect, false);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectsComponent)
|
||||
};
|
|
@ -17,11 +17,11 @@ private:
|
|||
OscirenderAudioProcessor& audioProcessor;
|
||||
OscirenderAudioProcessorEditor& pluginEditor;
|
||||
|
||||
EffectComponent focalLength{*audioProcessor.focalLength, false};
|
||||
EffectComponent rotateX{*audioProcessor.rotateX, false};
|
||||
EffectComponent rotateY{*audioProcessor.rotateY, false};
|
||||
EffectComponent rotateZ{*audioProcessor.rotateZ, false};
|
||||
EffectComponent rotateSpeed{*audioProcessor.rotateSpeed, false};
|
||||
EffectComponent focalLength{audioProcessor, *audioProcessor.focalLength, false};
|
||||
EffectComponent rotateX{audioProcessor, *audioProcessor.rotateX, false};
|
||||
EffectComponent rotateY{audioProcessor, *audioProcessor.rotateY, false};
|
||||
EffectComponent rotateZ{audioProcessor, *audioProcessor.rotateZ, false};
|
||||
EffectComponent rotateSpeed{audioProcessor, *audioProcessor.rotateSpeed, false};
|
||||
|
||||
juce::TextButton resetRotation{"Reset Rotation"};
|
||||
juce::ToggleButton mouseRotate{"Rotate with Mouse (Esc to disable)"};
|
||||
|
|
|
@ -97,7 +97,7 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
permanentEffects.push_back(rotateZ);
|
||||
permanentEffects.push_back(focalLength);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
for (int i = 0; i < 26; i++) {
|
||||
addLuaSlider();
|
||||
}
|
||||
|
||||
|
@ -218,6 +218,9 @@ void OscirenderAudioProcessor::addLuaSlider() {
|
|||
std::make_shared<LuaEffect>(sliderName, *this),
|
||||
new EffectParameter("Lua " + sliderName, "lua" + sliderName, 0.0, 0.0, 1.0, 0.001, false)
|
||||
));
|
||||
|
||||
auto& effect = luaEffects.back();
|
||||
effect->parameters[0]->disableLfo();
|
||||
}
|
||||
|
||||
// effectsLock should be held when calling this
|
||||
|
|
|
@ -162,7 +162,7 @@ public:
|
|||
obj->setRotationSpeed(values[0]);
|
||||
}
|
||||
return input;
|
||||
}, new EffectParameter("Rotate Speed", "rotateSpeed", 0.0, -1.0, 1.0)
|
||||
}, new EffectParameter("Rotate Speed", "rotateSpeed3D", 0.0, -1.0, 1.0)
|
||||
);
|
||||
|
||||
std::shared_ptr<DelayEffect> delayEffect = std::make_shared<DelayEffect>();
|
||||
|
|
|
@ -28,10 +28,11 @@ void Effect::animateValues() {
|
|||
auto parameter = parameters[i];
|
||||
float minValue = parameter->min;
|
||||
float maxValue = parameter->max;
|
||||
float phase = nextPhase(parameter);
|
||||
float phase = parameter->lfo != nullptr ? nextPhase(parameter) : 0.0;
|
||||
float percentage = phase / (2 * std::numbers::pi);
|
||||
LfoType type = parameter->lfo != nullptr ? (LfoType)(int)parameter->lfo->getValueUnnormalised() : LfoType::Static;
|
||||
|
||||
switch ((LfoType)(int) parameter->lfo->getValueUnnormalised()) {
|
||||
switch (type) {
|
||||
case LfoType::Sine:
|
||||
actualValues[i] = std::sin(phase) * 0.5 + 0.5;
|
||||
actualValues[i] = actualValues[i] * (maxValue - minValue) + minValue;
|
||||
|
@ -56,11 +57,8 @@ void Effect::animateValues() {
|
|||
actualValues[i] = (1 - percentage) * (maxValue - minValue) + minValue;
|
||||
break;
|
||||
case LfoType::Noise:
|
||||
{
|
||||
float noise = (float)rand() / RAND_MAX;
|
||||
actualValues[i] = noise * (maxValue - minValue) + minValue;
|
||||
actualValues[i] = ((float)rand() / RAND_MAX) * (maxValue - minValue) + minValue;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
double weight = parameter->smoothValueChange ? 0.0005 : 1.0;
|
||||
actualValues[i] = (1.0 - weight) * actualValues[i] + weight * parameter->getValueUnnormalised();
|
||||
|
@ -110,8 +108,12 @@ 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 (parameters[index]->lfo != nullptr) {
|
||||
parameters[index]->lfo->addListener(listener);
|
||||
}
|
||||
if (parameters[index]->lfoRate != nullptr) {
|
||||
parameters[index]->lfoRate->addListener(listener);
|
||||
}
|
||||
if (enabled != nullptr) {
|
||||
enabled->addListener(listener);
|
||||
}
|
||||
|
@ -121,8 +123,12 @@ void Effect::removeListener(int index, juce::AudioProcessorParameter::Listener*
|
|||
if (enabled != nullptr) {
|
||||
enabled->removeListener(listener);
|
||||
}
|
||||
parameters[index]->lfoRate->removeListener(listener);
|
||||
parameters[index]->lfo->removeListener(listener);
|
||||
if (parameters[index]->lfoRate != nullptr) {
|
||||
parameters[index]->lfoRate->removeListener(listener);
|
||||
}
|
||||
if (parameters[index]->lfo != nullptr) {
|
||||
parameters[index]->lfo->removeListener(listener);
|
||||
}
|
||||
parameters[index]->removeListener(listener);
|
||||
}
|
||||
|
||||
|
@ -135,7 +141,7 @@ void Effect::markEnableable(bool enable) {
|
|||
}
|
||||
|
||||
juce::String Effect::getId() {
|
||||
return parameters[0]->id;
|
||||
return parameters[0]->paramID;
|
||||
}
|
||||
|
||||
juce::String Effect::getName() {
|
||||
|
|
|
@ -2,16 +2,13 @@
|
|||
#include "../shape/Vector2.h"
|
||||
#include <JuceHeader.h>
|
||||
|
||||
class FloatParameter : public juce::AudioProcessorParameter {
|
||||
class FloatParameter : public juce::AudioProcessorParameterWithID {
|
||||
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;
|
||||
|
||||
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) {}
|
||||
FloatParameter(juce::String name, juce::String id, float value, float min, float max, float step = 0.001, juce::String label = "") : juce::AudioProcessorParameterWithID(id, name), value(value), min(min), max(max), step(step), label(label) {}
|
||||
|
||||
juce::String getName(int maximumStringLength) const override {
|
||||
return name.substring(0, maximumStringLength);
|
||||
|
@ -105,15 +102,12 @@ private:
|
|||
juce::String label;
|
||||
};
|
||||
|
||||
class IntParameter : public juce::AudioProcessorParameter {
|
||||
class IntParameter : public juce::AudioProcessorParameterWithID {
|
||||
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) {}
|
||||
IntParameter(juce::String name, juce::String id, int value, int min, int max) : AudioProcessorParameterWithID(name, id), value(value), min(min), max(max) {}
|
||||
|
||||
juce::String getName(int maximumStringLength) const override {
|
||||
return name.substring(0, maximumStringLength);
|
||||
|
@ -270,13 +264,28 @@ public:
|
|||
class EffectParameter : public FloatParameter {
|
||||
public:
|
||||
std::atomic<bool> smoothValueChange = true;
|
||||
LfoTypeParameter* lfo = new LfoTypeParameter(name + " LFO", id + "Lfo", 1);
|
||||
FloatParameter* lfoRate = new FloatParameter(name + " LFO Rate", id + "LfoRate", 1.0f, 0.0f, 100.0f, 0.1f, "Hz");
|
||||
LfoTypeParameter* lfo = new LfoTypeParameter(name + " LFO", paramID + "Lfo", 1);
|
||||
FloatParameter* lfoRate = new FloatParameter(name + " LFO Rate", paramID + "LfoRate", 1.0f, 0.0f, 100.0f, 0.1f, "Hz");
|
||||
std::atomic<float> phase = 0.0f;
|
||||
|
||||
std::vector<juce::AudioProcessorParameter*> getParameters() {
|
||||
return { this, lfo, lfoRate };
|
||||
std::vector<juce::AudioProcessorParameter*> parameters;
|
||||
parameters.push_back(this);
|
||||
if (lfo != nullptr) {
|
||||
parameters.push_back(lfo);
|
||||
}
|
||||
if (lfoRate != nullptr) {
|
||||
parameters.push_back(lfoRate);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
void disableLfo() {
|
||||
delete lfo;
|
||||
delete lfoRate;
|
||||
lfo = nullptr;
|
||||
lfoRate = nullptr;
|
||||
}
|
||||
|
||||
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) {}
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
#include "EffectComponent.h"
|
||||
|
||||
EffectComponent::EffectComponent(Effect& effect, int index) : effect(effect), index(index) {
|
||||
EffectComponent::EffectComponent(OscirenderAudioProcessor& p, Effect& effect, int index) : effect(effect), index(index), audioProcessor(p) {
|
||||
addAndMakeVisible(slider);
|
||||
addAndMakeVisible(selected);
|
||||
addAndMakeVisible(lfo);
|
||||
|
@ -20,13 +20,13 @@ EffectComponent::EffectComponent(Effect& effect, int index) : effect(effect), in
|
|||
setupComponent();
|
||||
}
|
||||
|
||||
EffectComponent::EffectComponent(Effect& effect, int index, bool checkboxVisible) : EffectComponent(effect, index) {
|
||||
EffectComponent::EffectComponent(OscirenderAudioProcessor& p, Effect& effect, int index, bool checkboxVisible) : EffectComponent(p, effect, index) {
|
||||
setCheckboxVisible(checkboxVisible);
|
||||
}
|
||||
|
||||
EffectComponent::EffectComponent(Effect& effect) : EffectComponent(effect, 0) {}
|
||||
EffectComponent::EffectComponent(OscirenderAudioProcessor& p, Effect& effect) : EffectComponent(p, effect, 0) {}
|
||||
|
||||
EffectComponent::EffectComponent(Effect& effect, bool checkboxVisible) : EffectComponent(effect) {
|
||||
EffectComponent::EffectComponent(OscirenderAudioProcessor& p, Effect& effect, bool checkboxVisible) : EffectComponent(p, effect) {
|
||||
setCheckboxVisible(checkboxVisible);
|
||||
}
|
||||
|
||||
|
@ -42,14 +42,17 @@ void EffectComponent::setupComponent() {
|
|||
bool enabled = effect.enabled == nullptr || effect.enabled->getValue();
|
||||
selected.setToggleState(enabled, juce::dontSendNotification);
|
||||
|
||||
lfo.setSelectedId(parameter->lfo->getValueUnnormalised(), juce::dontSendNotification);
|
||||
|
||||
lfo.onChange = [this]() {
|
||||
if (lfo.getSelectedId() != 0) {
|
||||
effect.parameters[index]->lfo->setUnnormalisedValueNotifyingHost(lfo.getSelectedId());
|
||||
}
|
||||
};
|
||||
lfoEnabled = parameter->lfo != nullptr && parameter->lfoRate != nullptr;
|
||||
if (lfoEnabled) {
|
||||
lfo.setSelectedId(parameter->lfo->getValueUnnormalised(), juce::dontSendNotification);
|
||||
|
||||
lfo.onChange = [this]() {
|
||||
if (lfo.getSelectedId() != 0) {
|
||||
effect.parameters[index]->lfo->setUnnormalisedValueNotifyingHost(lfo.getSelectedId());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
min.textBox.setValue(parameter->min, juce::dontSendNotification);
|
||||
max.textBox.setValue(parameter->max, juce::dontSendNotification);
|
||||
|
||||
|
@ -92,7 +95,9 @@ void EffectComponent::resized() {
|
|||
component->setBounds(componentBounds);
|
||||
}
|
||||
|
||||
lfo.setBounds(bounds.removeFromRight(100).reduced(5));
|
||||
if (lfoEnabled) {
|
||||
lfo.setBounds(bounds.removeFromRight(100).reduced(5));
|
||||
}
|
||||
|
||||
auto checkboxLabel = bounds.removeFromLeft(110);
|
||||
|
||||
|
@ -132,6 +137,11 @@ void EffectComponent::parameterGestureChanged(int parameterIndex, bool gestureIs
|
|||
|
||||
void EffectComponent::handleAsyncUpdate() {
|
||||
setupComponent();
|
||||
juce::SpinLock::ScopedLockType lock1(audioProcessor.parsersLock);
|
||||
juce::SpinLock::ScopedLockType lock2(audioProcessor.effectsLock);
|
||||
if (effect.getId().contains("lua")) {
|
||||
effect.apply();
|
||||
}
|
||||
}
|
||||
|
||||
void EffectComponent::setComponent(std::shared_ptr<juce::Component> component) {
|
||||
|
|
|
@ -34,10 +34,10 @@ class SmallComboBoxArrow : public juce::LookAndFeel_V4 {
|
|||
|
||||
class EffectComponent : public juce::Component, public juce::AudioProcessorParameter::Listener, juce::AsyncUpdater {
|
||||
public:
|
||||
EffectComponent(Effect& effect, int index);
|
||||
EffectComponent(Effect& effect, int index, bool checkboxVisible);
|
||||
EffectComponent(Effect& effect);
|
||||
EffectComponent(Effect& effect, bool checkboxVisible);
|
||||
EffectComponent(OscirenderAudioProcessor& p, Effect& effect, int index);
|
||||
EffectComponent(OscirenderAudioProcessor& p, Effect& effect, int index, bool checkboxVisible);
|
||||
EffectComponent(OscirenderAudioProcessor& p, Effect& effect);
|
||||
EffectComponent(OscirenderAudioProcessor& p, Effect& effect, bool checkboxVisible);
|
||||
~EffectComponent();
|
||||
|
||||
void resized() override;
|
||||
|
@ -60,8 +60,10 @@ public:
|
|||
private:
|
||||
void setupComponent();
|
||||
bool checkboxVisible = true;
|
||||
bool lfoEnabled = true;
|
||||
juce::Rectangle<int> textBounds;
|
||||
std::shared_ptr<juce::Component> component;
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
|
||||
juce::Label popupLabel;
|
||||
LabelledTextBox min{"Min"};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<Effect> effect) : DraggableListBoxItem(lb, data, rn), effect(effect) {
|
||||
auto parameters = effect->parameters;
|
||||
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>(data.audioProcessor, *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);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "LuaListComponent.h"
|
||||
|
||||
LuaListComponent::LuaListComponent(OscirenderAudioProcessor& p, Effect& effect) {
|
||||
effectComponent = std::make_shared<EffectComponent>(effect);
|
||||
effectComponent = std::make_shared<EffectComponent>(p, effect);
|
||||
effectComponent->setCheckboxVisible(false);
|
||||
|
||||
effectComponent->slider.onValueChange = [this, &effect, &p] {
|
||||
|
@ -21,27 +21,16 @@ void LuaListComponent::resized() {
|
|||
void paintListBoxItem(int sliderNum, juce::Graphics& g, int width, int height, bool rowIsSelected) {}
|
||||
|
||||
int LuaListBoxModel::getNumRows() {
|
||||
return audioProcessor.luaEffects.size() + 1;
|
||||
return audioProcessor.luaEffects.size();
|
||||
}
|
||||
|
||||
void LuaListBoxModel::paintListBoxItem(int rowNumber, juce::Graphics& g, int width, int height, bool rowIsSelected) {}
|
||||
|
||||
juce::Component* LuaListBoxModel::refreshComponentForRow(int rowNum, bool isRowSelected, juce::Component *existingComponentToUpdate) {
|
||||
if (rowNum < getNumRows() - 1) {
|
||||
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
|
||||
std::unique_ptr<LuaListComponent> item(dynamic_cast<LuaListComponent*>(existingComponentToUpdate));
|
||||
if (juce::isPositiveAndBelow(rowNum, getNumRows())) {
|
||||
item = std::make_unique<LuaListComponent>(audioProcessor, *audioProcessor.luaEffects[rowNum]);
|
||||
}
|
||||
return item.release();
|
||||
} else {
|
||||
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
|
||||
std::unique_ptr<juce::TextButton> item(dynamic_cast<juce::TextButton*>(existingComponentToUpdate));
|
||||
item = std::make_unique<juce::TextButton>("+");
|
||||
item->onClick = [this]() {
|
||||
audioProcessor.addLuaSlider();
|
||||
listBox.updateContent();
|
||||
};
|
||||
return item.release();
|
||||
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
|
||||
std::unique_ptr<LuaListComponent> item(dynamic_cast<LuaListComponent*>(existingComponentToUpdate));
|
||||
if (juce::isPositiveAndBelow(rowNum, getNumRows())) {
|
||||
item = std::make_unique<LuaListComponent>(audioProcessor, *audioProcessor.luaEffects[rowNum]);
|
||||
}
|
||||
return item.release();
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
juce::Component* refreshComponentForRow(int sliderNum, bool isRowSelected, juce::Component *existingComponentToUpdate) override;
|
||||
|
||||
private:
|
||||
int numSliders = 5;
|
||||
int numSliders = 26;
|
||||
juce::ListBox& listBox;
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
};
|
||||
|
|
Ładowanie…
Reference in New Issue