Add LFO start and end parameters and change slider range to slider settings cog

new-features-1
James H Ball 2025-02-15 15:35:38 +00:00
rodzic 274430deb8
commit 90e30ba52a
5 zmienionych plików z 99 dodań i 18 usunięć

Wyświetl plik

@ -396,7 +396,7 @@ void OscirenderLookAndFeel::drawCallOutBoxBackground(juce::CallOutBox& box, juce
g.setColour(juce::Colours::black); g.setColour(juce::Colours::black);
g.drawImageAt(cachedImage, 0, 0); g.drawImageAt(cachedImage, 0, 0);
g.setColour(Colours::dark); g.setColour(Colours::darker);
g.fillPath(path); g.fillPath(path);
g.setColour(juce::Colours::black); g.setColour(juce::Colours::black);

Wyświetl plik

@ -36,10 +36,16 @@ void Effect::animateValues(double volume) {
auto parameter = parameters[i]; auto parameter = parameters[i];
float minValue = parameter->min; float minValue = parameter->min;
float maxValue = parameter->max; float maxValue = parameter->max;
bool lfoEnabled = parameter->lfo != nullptr && parameter->lfo->getValueUnnormalised() != (int)LfoType::Static; bool lfoEnabled = parameter->isLfoEnabled() && parameter->lfo->getValueUnnormalised() != (int)LfoType::Static;
float phase = lfoEnabled ? nextPhase(parameter) : 0.0; float phase = lfoEnabled ? nextPhase(parameter) : 0.0;
float percentage = phase / (2 * std::numbers::pi); float percentage = phase / (2 * std::numbers::pi);
LfoType type = lfoEnabled ? (LfoType)(int)parameter->lfo->getValueUnnormalised() : LfoType::Static; LfoType type = lfoEnabled ? (LfoType)(int)parameter->lfo->getValueUnnormalised() : LfoType::Static;
if (lfoEnabled) {
double originalMin = minValue;
minValue = originalMin + (parameter->lfoStartPercent->getValueUnnormalised() / 100.0) * (maxValue - originalMin);
maxValue = originalMin + (parameter->lfoEndPercent->getValueUnnormalised() / 100.0) * (maxValue - originalMin);
}
switch (type) { switch (type) {
case LfoType::Sine: case LfoType::Sine:

Wyświetl plik

@ -337,6 +337,8 @@ public:
std::atomic<double> smoothValueChange = SMOOTHING_SPEED_CONSTANT; std::atomic<double> smoothValueChange = SMOOTHING_SPEED_CONSTANT;
LfoTypeParameter* lfo = new LfoTypeParameter(name + " LFO", paramID + "Lfo", getVersionHint(), 1); LfoTypeParameter* lfo = new LfoTypeParameter(name + " LFO", paramID + "Lfo", getVersionHint(), 1);
FloatParameter* lfoRate = new FloatParameter(name + " LFO Rate", paramID + "LfoRate", getVersionHint(), 1.0f, 0.0f, 10000.0f, 0.001f, "Hz"); FloatParameter* lfoRate = new FloatParameter(name + " LFO Rate", paramID + "LfoRate", getVersionHint(), 1.0f, 0.0f, 10000.0f, 0.001f, "Hz");
FloatParameter* lfoStartPercent = new FloatParameter(name + " LFO Start", paramID + "LfoStart", getVersionHint(), 0.0f, 0.0f, 100.0f, 0.0001f, "%");
FloatParameter* lfoEndPercent = new FloatParameter(name + " LFO End", paramID + "LfoEnd", getVersionHint(), 100.0f, 0.0f, 100.0f, 0.0001f, "%");
BooleanParameter* sidechain = new BooleanParameter(name + " Sidechain Enabled", paramID + "Sidechain", getVersionHint(), false, "Toggles " + name + " Sidechain."); BooleanParameter* sidechain = new BooleanParameter(name + " Sidechain Enabled", paramID + "Sidechain", getVersionHint(), false, "Toggles " + name + " Sidechain.");
std::atomic<float> phase = 0.0f; std::atomic<float> phase = 0.0f;
juce::String description; juce::String description;
@ -350,6 +352,12 @@ public:
if (lfoRate != nullptr) { if (lfoRate != nullptr) {
parameters.push_back(lfoRate); parameters.push_back(lfoRate);
} }
if (lfoStartPercent != nullptr) {
parameters.push_back(lfoStartPercent);
}
if (lfoEndPercent != nullptr) {
parameters.push_back(lfoEndPercent);
}
if (sidechain != nullptr) { if (sidechain != nullptr) {
parameters.push_back(sidechain); parameters.push_back(sidechain);
} }
@ -357,10 +365,15 @@ public:
} }
void disableLfo() { void disableLfo() {
lfoEnabled = false;
delete lfo; delete lfo;
delete lfoRate; delete lfoRate;
delete lfoStartPercent;
delete lfoEndPercent;
lfo = nullptr; lfo = nullptr;
lfoRate = nullptr; lfoRate = nullptr;
lfoStartPercent = nullptr;
lfoEndPercent = nullptr;
} }
void disableSidechain() { void disableSidechain() {
@ -371,10 +384,14 @@ public:
void save(juce::XmlElement* xml) { void save(juce::XmlElement* xml) {
FloatParameter::save(xml); FloatParameter::save(xml);
if (lfo != nullptr && lfoRate != nullptr) { if (lfoEnabled) {
auto lfoXml = xml->createNewChildElement("lfo"); auto lfoXml = xml->createNewChildElement("lfo");
lfo->save(lfoXml); lfo->save(lfoXml);
lfoRate->save(lfoXml); lfoRate->save(lfoXml);
auto lfoStartXml = xml->createNewChildElement("lfoStart");
lfoStartPercent->save(lfoStartXml);
auto lfoEndXml = xml->createNewChildElement("lfoEnd");
lfoEndPercent->save(lfoEndXml);
} }
if (sidechain != nullptr) { if (sidechain != nullptr) {
@ -386,7 +403,7 @@ public:
void load(juce::XmlElement* xml) { void load(juce::XmlElement* xml) {
FloatParameter::load(xml); FloatParameter::load(xml);
if (lfo != nullptr && lfoRate != nullptr) { if (lfoEnabled) {
auto lfoXml = xml->getChildByName("lfo"); auto lfoXml = xml->getChildByName("lfo");
if (lfoXml != nullptr) { if (lfoXml != nullptr) {
lfo->load(lfoXml); lfo->load(lfoXml);
@ -395,6 +412,20 @@ public:
lfo->setValueNotifyingHost(lfo->getValueForText("Static")); lfo->setValueNotifyingHost(lfo->getValueForText("Static"));
lfoRate->setUnnormalisedValueNotifyingHost(1.0f); lfoRate->setUnnormalisedValueNotifyingHost(1.0f);
} }
auto lfoStartXml = xml->getChildByName("lfoStart");
if (lfoStartXml != nullptr) {
lfoStartPercent->load(lfoStartXml);
} else {
lfoStartPercent->setUnnormalisedValueNotifyingHost(0.0f);
}
auto lfoEndXml = xml->getChildByName("lfoEnd");
if (lfoEndXml != nullptr) {
lfoEndPercent->load(lfoEndXml);
} else {
lfoEndPercent->setUnnormalisedValueNotifyingHost(100.0f);
}
} }
if (sidechain != nullptr) { if (sidechain != nullptr) {
@ -406,6 +437,13 @@ public:
} }
} }
} }
bool isLfoEnabled() {
return lfoEnabled;
}
EffectParameter(juce::String name, juce::String description, juce::String id, int versionHint, float value, float min, float max, float step = 0.0001, double smoothValueChange = SMOOTHING_SPEED_CONSTANT) : FloatParameter(name, id, versionHint, value, min, max, step), smoothValueChange(smoothValueChange), description(description) {} EffectParameter(juce::String name, juce::String description, juce::String id, int versionHint, float value, float min, float max, float step = 0.0001, double smoothValueChange = SMOOTHING_SPEED_CONSTANT) : FloatParameter(name, id, versionHint, value, min, max, step), smoothValueChange(smoothValueChange), description(description) {}
private:
bool lfoEnabled = true;
}; };

Wyświetl plik

@ -6,7 +6,7 @@ EffectComponent::EffectComponent(Effect& effect, int index) : effect(effect), in
addChildComponent(lfoSlider); addChildComponent(lfoSlider);
addAndMakeVisible(lfo); addAndMakeVisible(lfo);
addAndMakeVisible(label); addAndMakeVisible(label);
addAndMakeVisible(rangeButton); addAndMakeVisible(settingsButton);
sidechainEnabled = effect.parameters[index]->sidechain != nullptr; sidechainEnabled = effect.parameters[index]->sidechain != nullptr;
if (sidechainEnabled) { if (sidechainEnabled) {
@ -40,12 +40,13 @@ EffectComponent::EffectComponent(Effect& effect, int index) : effect(effect), in
lfo.addItem("Reverse Sawtooth", static_cast<int>(LfoType::ReverseSawtooth)); lfo.addItem("Reverse Sawtooth", static_cast<int>(LfoType::ReverseSawtooth));
lfo.addItem("Noise", static_cast<int>(LfoType::Noise)); lfo.addItem("Noise", static_cast<int>(LfoType::Noise));
rangeButton.setTooltip("Click to change the range of the slider."); settingsButton.setTooltip("Click to change the slider settings, including range.");
rangeButton.onClick = [this] { settingsButton.onClick = [this] {
auto range = std::make_unique<EffectRangeComponent>(this); auto settings = std::make_unique<EffectSettingsComponent>(this);
range->setSize(200, 110); settings->setLookAndFeel(&getLookAndFeel());
auto& myBox = juce::CallOutBox::launchAsynchronously(std::move(range), rangeButton.getScreenBounds(), nullptr); settings->setSize(200, 220);
auto& myBox = juce::CallOutBox::launchAsynchronously(std::move(settings), settingsButton.getScreenBounds(), nullptr);
}; };
effect.addListener(index, this); effect.addListener(index, this);
@ -152,6 +153,10 @@ void EffectComponent::resized() {
if (sidechainEnabled) { if (sidechainEnabled) {
sidechainButton->setBounds(bounds.removeFromRight(20)); sidechainButton->setBounds(bounds.removeFromRight(20));
} }
if (settingsButton.isVisible()) {
settingsButton.setBounds(bounds.removeFromRight(20));
}
bool drawingSmall = bounds.getWidth() < 3.5 * TEXT_WIDTH; bool drawingSmall = bounds.getWidth() < 3.5 * TEXT_WIDTH;
@ -159,10 +164,8 @@ void EffectComponent::resized() {
lfo.setBounds(bounds.removeFromRight(drawingSmall ? 70 : 100).reduced(0, 5)); lfo.setBounds(bounds.removeFromRight(drawingSmall ? 70 : 100).reduced(0, 5));
} }
if (rangeButton.isVisible()) { bounds.removeFromRight(2);
rangeButton.setBounds(bounds.removeFromRight(20));
}
bounds.removeFromLeft(5); bounds.removeFromLeft(5);
label.setBounds(bounds.removeFromLeft(drawingSmall ? SMALL_TEXT_WIDTH : TEXT_WIDTH)); label.setBounds(bounds.removeFromLeft(drawingSmall ? SMALL_TEXT_WIDTH : TEXT_WIDTH));
@ -198,7 +201,7 @@ void EffectComponent::handleAsyncUpdate() {
} }
void EffectComponent::setRangeEnabled(bool enabled) { void EffectComponent::setRangeEnabled(bool enabled) {
rangeButton.setVisible(enabled); settingsButton.setVisible(enabled);
} }
void EffectComponent::setComponent(std::shared_ptr<juce::Component> component) { void EffectComponent::setComponent(std::shared_ptr<juce::Component> component) {

Wyświetl plik

@ -27,12 +27,16 @@ public:
int index = 0; int index = 0;
juce::ComboBox lfo; juce::ComboBox lfo;
class EffectRangeComponent : public juce::Component { class EffectSettingsComponent : public juce::Component {
public: public:
EffectRangeComponent(EffectComponent* parent) { EffectSettingsComponent(EffectComponent* parent) {
addAndMakeVisible(popupLabel); addAndMakeVisible(popupLabel);
addAndMakeVisible(min); addAndMakeVisible(min);
addAndMakeVisible(max); addAndMakeVisible(max);
addAndMakeVisible(lfoStartLabel);
addAndMakeVisible(lfoEndLabel);
addAndMakeVisible(lfoStartSlider);
addAndMakeVisible(lfoEndSlider);
EffectParameter* parameter = parent->effect.parameters[parent->index]; EffectParameter* parameter = parent->effect.parameters[parent->index];
@ -61,6 +65,28 @@ public:
parent->slider.setRange(parameter->min, parameter->max, parameter->step); parent->slider.setRange(parameter->min, parameter->max, parameter->step);
}; };
lfoStartLabel.setText("LFO Start", juce::dontSendNotification);
lfoStartLabel.setJustificationType(juce::Justification::centred);
lfoStartLabel.setFont(juce::Font(14.0f, juce::Font::bold));
lfoEndLabel.setText("LFO End", juce::dontSendNotification);
lfoEndLabel.setJustificationType(juce::Justification::centred);
lfoEndLabel.setFont(juce::Font(14.0f, juce::Font::bold));
lfoStartSlider.setRange(parameter->lfoStartPercent->min, parameter->lfoStartPercent->max, parameter->lfoStartPercent->step);
lfoStartSlider.setValue(parameter->lfoStartPercent->getValueUnnormalised(), juce::dontSendNotification);
lfoStartSlider.setTextValueSuffix("%");
lfoStartSlider.onValueChange = [this, parameter]() {
parameter->lfoStartPercent->setUnnormalisedValueNotifyingHost(lfoStartSlider.getValue());
};
lfoEndSlider.setRange(parameter->lfoEndPercent->min, parameter->lfoEndPercent->max, parameter->lfoEndPercent->step);
lfoEndSlider.setValue(parameter->lfoEndPercent->getValueUnnormalised(), juce::dontSendNotification);
lfoEndSlider.setTextValueSuffix("%");
lfoEndSlider.onValueChange = [this, parameter]() {
parameter->lfoEndPercent->setUnnormalisedValueNotifyingHost(lfoEndSlider.getValue());
};
popupLabel.setText(parameter->name + " Range", juce::dontSendNotification); popupLabel.setText(parameter->name + " Range", juce::dontSendNotification);
popupLabel.setJustificationType(juce::Justification::centred); popupLabel.setJustificationType(juce::Justification::centred);
popupLabel.setFont(juce::Font(14.0f, juce::Font::bold)); popupLabel.setFont(juce::Font(14.0f, juce::Font::bold));
@ -71,12 +97,20 @@ public:
popupLabel.setBounds(bounds.removeFromTop(30)); popupLabel.setBounds(bounds.removeFromTop(30));
min.setBounds(bounds.removeFromTop(40)); min.setBounds(bounds.removeFromTop(40));
max.setBounds(bounds.removeFromTop(40)); max.setBounds(bounds.removeFromTop(40));
lfoStartLabel.setBounds(bounds.removeFromTop(20));
lfoStartSlider.setBounds(bounds.removeFromTop(40));
lfoEndLabel.setBounds(bounds.removeFromTop(20));
lfoEndSlider.setBounds(bounds.removeFromTop(40));
} }
private: private:
juce::Label popupLabel; juce::Label popupLabel;
LabelledTextBox min{"Min"}; LabelledTextBox min{"Min"};
LabelledTextBox max{"Max"}; LabelledTextBox max{"Max"};
juce::Label lfoStartLabel;
juce::Label lfoEndLabel;
juce::Slider lfoStartSlider;
juce::Slider lfoEndSlider;
}; };
std::function<void()> updateToggleState; std::function<void()> updateToggleState;
@ -98,7 +132,7 @@ private:
juce::Label label; juce::Label label;
SvgButton rangeButton = { "rangeButton", BinaryData::range_svg, juce::Colours::white }; SvgButton settingsButton = { "settingsButton", BinaryData::cog_svg, juce::Colours::white };
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectComponent) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectComponent)
}; };