kopia lustrzana https://github.com/jameshball/osci-render
Projects are now fully saveable and loadable from a DAW
rodzic
c75a036048
commit
8bdbe2aac4
|
@ -16,15 +16,6 @@ EffectsComponent::EffectsComponent(OscirenderAudioProcessor& p, OscirenderAudioP
|
||||||
audioProcessor.frequencyEffect->setValue(frequency.slider.getValue());
|
audioProcessor.frequencyEffect->setValue(frequency.slider.getValue());
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
|
||||||
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
|
|
||||||
for (int i = 0; i < audioProcessor.toggleableEffects.size(); i++) {
|
|
||||||
auto effect = audioProcessor.toggleableEffects[i];
|
|
||||||
effect->setValue(effect->getValue());
|
|
||||||
itemData.data.push_back(effect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*addBtn.setButtonText("Add Item...");
|
/*addBtn.setButtonText("Add Item...");
|
||||||
addBtn.onClick = [this]()
|
addBtn.onClick = [this]()
|
||||||
{
|
{
|
||||||
|
@ -33,12 +24,18 @@ EffectsComponent::EffectsComponent(OscirenderAudioProcessor& p, OscirenderAudioP
|
||||||
};
|
};
|
||||||
addAndMakeVisible(addBtn);*/
|
addAndMakeVisible(addBtn);*/
|
||||||
|
|
||||||
|
{
|
||||||
|
juce::MessageManagerLock lock;
|
||||||
|
audioProcessor.broadcaster.addChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
listBox.setModel(&listBoxModel);
|
listBox.setModel(&listBoxModel);
|
||||||
addAndMakeVisible(listBox);
|
addAndMakeVisible(listBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
EffectsComponent::~EffectsComponent() {
|
EffectsComponent::~EffectsComponent() {
|
||||||
|
juce::MessageManagerLock lock;
|
||||||
|
audioProcessor.broadcaster.removeChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectsComponent::resized() {
|
void EffectsComponent::resized() {
|
||||||
|
@ -48,3 +45,8 @@ void EffectsComponent::resized() {
|
||||||
area.removeFromTop(6);
|
area.removeFromTop(6);
|
||||||
listBox.setBounds(area);
|
listBox.setBounds(area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EffectsComponent::changeListenerCallback(juce::ChangeBroadcaster* source) {
|
||||||
|
itemData.resetData();
|
||||||
|
listBox.updateContent();
|
||||||
|
}
|
||||||
|
|
|
@ -7,12 +7,13 @@
|
||||||
#include "components/EffectsListComponent.h"
|
#include "components/EffectsListComponent.h"
|
||||||
|
|
||||||
class OscirenderAudioProcessorEditor;
|
class OscirenderAudioProcessorEditor;
|
||||||
class EffectsComponent : public juce::GroupComponent {
|
class EffectsComponent : public juce::GroupComponent, public juce::ChangeListener {
|
||||||
public:
|
public:
|
||||||
EffectsComponent(OscirenderAudioProcessor&, OscirenderAudioProcessorEditor&);
|
EffectsComponent(OscirenderAudioProcessor&, OscirenderAudioProcessorEditor&);
|
||||||
~EffectsComponent() override;
|
~EffectsComponent() override;
|
||||||
|
|
||||||
void resized() override;
|
void resized() override;
|
||||||
|
void changeListenerCallback(juce::ChangeBroadcaster* source) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OscirenderAudioProcessor& audioProcessor;
|
OscirenderAudioProcessor& audioProcessor;
|
||||||
|
|
|
@ -125,12 +125,16 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addParameter(fixedRotateX);
|
booleanParameters.push_back(fixedRotateX);
|
||||||
addParameter(fixedRotateY);
|
booleanParameters.push_back(fixedRotateY);
|
||||||
addParameter(fixedRotateZ);
|
booleanParameters.push_back(fixedRotateZ);
|
||||||
addParameter(perspectiveEffect->fixedRotateX);
|
booleanParameters.push_back(perspectiveEffect->fixedRotateX);
|
||||||
addParameter(perspectiveEffect->fixedRotateY);
|
booleanParameters.push_back(perspectiveEffect->fixedRotateY);
|
||||||
addParameter(perspectiveEffect->fixedRotateZ);
|
booleanParameters.push_back(perspectiveEffect->fixedRotateZ);
|
||||||
|
|
||||||
|
for (auto parameter : booleanParameters) {
|
||||||
|
addParameter(parameter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OscirenderAudioProcessor::~OscirenderAudioProcessor() {}
|
OscirenderAudioProcessor::~OscirenderAudioProcessor() {}
|
||||||
|
@ -257,6 +261,26 @@ void OscirenderAudioProcessor::updateObjValues() {
|
||||||
rotateSpeed->apply();
|
rotateSpeed->apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// effectsLock should be held when calling this
|
||||||
|
std::shared_ptr<Effect> OscirenderAudioProcessor::getEffect(juce::String id) {
|
||||||
|
for (auto& effect : allEffects) {
|
||||||
|
if (effect->getId() == id) {
|
||||||
|
return effect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// effectsLock should be held when calling this
|
||||||
|
BooleanParameter* OscirenderAudioProcessor::getBooleanParameter(juce::String id) {
|
||||||
|
for (auto& parameter : booleanParameters) {
|
||||||
|
if (parameter->paramID == id) {
|
||||||
|
return parameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// effectsLock MUST be held when calling this
|
// effectsLock MUST be held when calling this
|
||||||
void OscirenderAudioProcessor::updateEffectPrecedence() {
|
void OscirenderAudioProcessor::updateEffectPrecedence() {
|
||||||
auto sortFunc = [](std::shared_ptr<Effect> a, std::shared_ptr<Effect> b) {
|
auto sortFunc = [](std::shared_ptr<Effect> a, std::shared_ptr<Effect> b) {
|
||||||
|
@ -294,15 +318,28 @@ void OscirenderAudioProcessor::addFile(juce::String fileName, const char* data,
|
||||||
openFile(fileBlocks.size() - 1);
|
openFile(fileBlocks.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parsersLock AND effectsLock must be locked before calling this function
|
||||||
|
void OscirenderAudioProcessor::addFile(juce::String fileName, std::shared_ptr<juce::MemoryBlock> data) {
|
||||||
|
fileBlocks.push_back(data);
|
||||||
|
fileNames.push_back(fileName);
|
||||||
|
parsers.push_back(std::make_unique<FileParser>());
|
||||||
|
|
||||||
|
openFile(fileBlocks.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// parsersLock AND effectsLock must be locked before calling this function
|
// parsersLock AND effectsLock must be locked before calling this function
|
||||||
void OscirenderAudioProcessor::removeFile(int index) {
|
void OscirenderAudioProcessor::removeFile(int index) {
|
||||||
if (index < 0 || index >= fileBlocks.size()) {
|
if (index < 0 || index >= fileBlocks.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
changeCurrentFile(index - 1);
|
|
||||||
fileBlocks.erase(fileBlocks.begin() + index);
|
fileBlocks.erase(fileBlocks.begin() + index);
|
||||||
fileNames.erase(fileNames.begin() + index);
|
fileNames.erase(fileNames.begin() + index);
|
||||||
parsers.erase(parsers.begin() + index);
|
parsers.erase(parsers.begin() + index);
|
||||||
|
auto newFileIndex = index;
|
||||||
|
if (newFileIndex >= fileBlocks.size()) {
|
||||||
|
newFileIndex = fileBlocks.size() - 1;
|
||||||
|
}
|
||||||
|
changeCurrentFile(newFileIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int OscirenderAudioProcessor::numFiles() {
|
int OscirenderAudioProcessor::numFiles() {
|
||||||
|
@ -572,6 +609,13 @@ void OscirenderAudioProcessor::getStateInformation(juce::MemoryBlock& destData)
|
||||||
for (auto effect : allEffects) {
|
for (auto effect : allEffects) {
|
||||||
effect->save(effectsXml->createNewChildElement("effect"));
|
effect->save(effectsXml->createNewChildElement("effect"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto booleanParametersXml = xml->createNewChildElement("booleanParameters");
|
||||||
|
for (auto parameter : booleanParameters) {
|
||||||
|
auto parameterXml = booleanParametersXml->createNewChildElement("parameter");
|
||||||
|
parameter->save(parameterXml);
|
||||||
|
}
|
||||||
|
|
||||||
auto perspectiveFunction = xml->createNewChildElement("perspectiveFunction");
|
auto perspectiveFunction = xml->createNewChildElement("perspectiveFunction");
|
||||||
perspectiveFunction->addTextElement(juce::Base64::toBase64(perspectiveEffect->getCode()));
|
perspectiveFunction->addTextElement(juce::Base64::toBase64(perspectiveEffect->getCode()));
|
||||||
auto filesXml = xml->createNewChildElement("files");
|
auto filesXml = xml->createNewChildElement("files");
|
||||||
|
@ -588,8 +632,58 @@ void OscirenderAudioProcessor::getStateInformation(juce::MemoryBlock& destData)
|
||||||
}
|
}
|
||||||
|
|
||||||
void OscirenderAudioProcessor::setStateInformation(const void* data, int sizeInBytes) {
|
void OscirenderAudioProcessor::setStateInformation(const void* data, int sizeInBytes) {
|
||||||
// You should use this method to restore your parameters from this memory block,
|
juce::SpinLock::ScopedLockType lock1(parsersLock);
|
||||||
// whose contents will have been created by the getStateInformation() call.
|
juce::SpinLock::ScopedLockType lock2(effectsLock);
|
||||||
|
|
||||||
|
std::unique_ptr<juce::XmlElement> xml(getXmlFromBinary(data, sizeInBytes));
|
||||||
|
|
||||||
|
if (xml.get() != nullptr && xml->hasTagName("project")) {
|
||||||
|
auto effectsXml = xml->getChildByName("effects");
|
||||||
|
if (effectsXml != nullptr) {
|
||||||
|
for (auto effectXml : effectsXml->getChildIterator()) {
|
||||||
|
auto effect = getEffect(effectXml->getStringAttribute("id"));
|
||||||
|
if (effect != nullptr) {
|
||||||
|
effect->load(effectXml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateEffectPrecedence();
|
||||||
|
|
||||||
|
auto booleanParametersXml = xml->getChildByName("booleanParameters");
|
||||||
|
if (booleanParametersXml != nullptr) {
|
||||||
|
for (auto parameterXml : booleanParametersXml->getChildIterator()) {
|
||||||
|
auto parameter = getBooleanParameter(parameterXml->getStringAttribute("id"));
|
||||||
|
if (parameter != nullptr) {
|
||||||
|
parameter->load(parameterXml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto perspectiveFunction = xml->getChildByName("perspectiveFunction");
|
||||||
|
if (perspectiveFunction != nullptr) {
|
||||||
|
auto stream = juce::MemoryOutputStream();
|
||||||
|
juce::Base64::convertFromBase64(stream, perspectiveFunction->getAllSubText());
|
||||||
|
perspectiveEffect->updateCode(stream.toString());
|
||||||
|
}
|
||||||
|
// close all files
|
||||||
|
auto numFiles = fileBlocks.size();
|
||||||
|
for (int i = 0; i < numFiles; i++) {
|
||||||
|
removeFile(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto filesXml = xml->getChildByName("files");
|
||||||
|
if (filesXml != nullptr) {
|
||||||
|
for (auto fileXml : filesXml->getChildIterator()) {
|
||||||
|
auto fileName = fileXml->getStringAttribute("name");
|
||||||
|
auto stream = juce::MemoryOutputStream();
|
||||||
|
juce::Base64::convertFromBase64(stream, fileXml->getAllSubText());
|
||||||
|
auto fileBlock = std::make_shared<juce::MemoryBlock>(stream.getData(), stream.getDataSize());
|
||||||
|
addFile(fileName, fileBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changeCurrentFile(xml->getIntAttribute("currentFile", -1));
|
||||||
|
broadcaster.sendChangeMessage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
|
@ -175,6 +175,8 @@ public:
|
||||||
std::vector<juce::String> fileNames;
|
std::vector<juce::String> fileNames;
|
||||||
std::atomic<int> currentFile = -1;
|
std::atomic<int> currentFile = -1;
|
||||||
|
|
||||||
|
juce::ChangeBroadcaster broadcaster;
|
||||||
|
|
||||||
FrameProducer producer = FrameProducer(*this, std::make_shared<FileParser>());
|
FrameProducer producer = FrameProducer(*this, std::make_shared<FileParser>());
|
||||||
|
|
||||||
BufferProducer audioProducer;
|
BufferProducer audioProducer;
|
||||||
|
@ -188,6 +190,7 @@ public:
|
||||||
void updateFileBlock(int index, std::shared_ptr<juce::MemoryBlock> block);
|
void updateFileBlock(int index, std::shared_ptr<juce::MemoryBlock> block);
|
||||||
void addFile(juce::File file);
|
void addFile(juce::File file);
|
||||||
void addFile(juce::String fileName, const char* data, const int size);
|
void addFile(juce::String fileName, const char* data, const int size);
|
||||||
|
void addFile(juce::String fileName, std::shared_ptr<juce::MemoryBlock> data);
|
||||||
void removeFile(int index);
|
void removeFile(int index);
|
||||||
int numFiles();
|
int numFiles();
|
||||||
void changeCurrentFile(int index);
|
void changeCurrentFile(int index);
|
||||||
|
@ -214,6 +217,7 @@ private:
|
||||||
double lengthIncrement = 0.0;
|
double lengthIncrement = 0.0;
|
||||||
bool invalidateFrameBuffer = false;
|
bool invalidateFrameBuffer = false;
|
||||||
|
|
||||||
|
std::vector<BooleanParameter*> booleanParameters;
|
||||||
std::vector<std::shared_ptr<Effect>> allEffects;
|
std::vector<std::shared_ptr<Effect>> allEffects;
|
||||||
std::vector<std::shared_ptr<Effect>> permanentEffects;
|
std::vector<std::shared_ptr<Effect>> permanentEffects;
|
||||||
|
|
||||||
|
@ -247,6 +251,8 @@ private:
|
||||||
void openFile(int index);
|
void openFile(int index);
|
||||||
void updateLuaValues();
|
void updateLuaValues();
|
||||||
void updateObjValues();
|
void updateObjValues();
|
||||||
|
std::shared_ptr<Effect> getEffect(juce::String id);
|
||||||
|
BooleanParameter* getBooleanParameter(juce::String id);
|
||||||
|
|
||||||
const double MIN_LENGTH_INCREMENT = 0.000001;
|
const double MIN_LENGTH_INCREMENT = 0.000001;
|
||||||
|
|
||||||
|
|
|
@ -2,20 +2,9 @@
|
||||||
#include "../shape/Vector2.h"
|
#include "../shape/Vector2.h"
|
||||||
#include <JuceHeader.h>
|
#include <JuceHeader.h>
|
||||||
|
|
||||||
class BooleanParameter : public juce::AudioProcessorParameter {
|
class BooleanParameter : public juce::AudioProcessorParameterWithID {
|
||||||
public:
|
public:
|
||||||
juce::String name;
|
BooleanParameter(juce::String name, juce::String id, bool value) : AudioProcessorParameterWithID(id, name), value(value) {}
|
||||||
juce::String id;
|
|
||||||
|
|
||||||
BooleanParameter(juce::String name, juce::String id, bool value) : name(name), id(id), value(value) {}
|
|
||||||
|
|
||||||
// COPY CONSTRUCTOR SHOULD ONLY BE USED BEFORE
|
|
||||||
// THE OBJECT IS USED IN MULTIPLE THREADS
|
|
||||||
BooleanParameter(const BooleanParameter& other) {
|
|
||||||
name = other.name;
|
|
||||||
id = other.id;
|
|
||||||
value.store(other.value.load());
|
|
||||||
}
|
|
||||||
|
|
||||||
juce::String getName(int maximumStringLength) const override {
|
juce::String getName(int maximumStringLength) const override {
|
||||||
return name.substring(0, maximumStringLength);
|
return name.substring(0, maximumStringLength);
|
||||||
|
@ -86,6 +75,15 @@ public:
|
||||||
return juce::AudioProcessorParameter::genericParameter;
|
return juce::AudioProcessorParameter::genericParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void save(juce::XmlElement* xml) {
|
||||||
|
xml->setAttribute("id", paramID);
|
||||||
|
xml->setAttribute("value", value.load());
|
||||||
|
}
|
||||||
|
|
||||||
|
void load(juce::XmlElement* xml) {
|
||||||
|
setBoolValueNotifyingHost(xml->getBoolAttribute("value", getDefaultValue()));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic<bool> value = false;
|
std::atomic<bool> value = false;
|
||||||
};
|
};
|
|
@ -151,9 +151,39 @@ juce::String Effect::getName() {
|
||||||
|
|
||||||
void Effect::save(juce::XmlElement* xml) {
|
void Effect::save(juce::XmlElement* xml) {
|
||||||
if (enabled != nullptr) {
|
if (enabled != nullptr) {
|
||||||
xml->setAttribute("enabled", enabled->getBoolValue());
|
auto enabledXml = xml->createNewChildElement("enabled");
|
||||||
|
enabled->save(enabledXml);
|
||||||
}
|
}
|
||||||
|
xml->setAttribute("id", getId());
|
||||||
|
xml->setAttribute("precedence", precedence);
|
||||||
for (auto parameter : parameters) {
|
for (auto parameter : parameters) {
|
||||||
parameter->save(xml->createNewChildElement("parameter"));
|
parameter->save(xml->createNewChildElement("parameter"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Effect::load(juce::XmlElement* xml) {
|
||||||
|
if (enabled != nullptr) {
|
||||||
|
auto enabledXml = xml->getChildByName("enabled");
|
||||||
|
if (enabledXml != nullptr) {
|
||||||
|
enabled->load(enabledXml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xml->hasAttribute("precedence")) {
|
||||||
|
setPrecedence(xml->getIntAttribute("precedence"));
|
||||||
|
}
|
||||||
|
for (auto parameterXml : xml->getChildIterator()) {
|
||||||
|
auto parameter = getParameter(parameterXml->getStringAttribute("id"));
|
||||||
|
if (parameter != nullptr) {
|
||||||
|
parameter->load(parameterXml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EffectParameter* Effect::getParameter(juce::String id) {
|
||||||
|
for (auto parameter : parameters) {
|
||||||
|
if (parameter->paramID == id) {
|
||||||
|
return parameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ public:
|
||||||
juce::String getId();
|
juce::String getId();
|
||||||
juce::String getName();
|
juce::String getName();
|
||||||
void save(juce::XmlElement* xml);
|
void save(juce::XmlElement* xml);
|
||||||
|
void load(juce::XmlElement* xml);
|
||||||
|
EffectParameter* getParameter(juce::String id);
|
||||||
|
|
||||||
std::vector<EffectParameter*> parameters;
|
std::vector<EffectParameter*> parameters;
|
||||||
BooleanParameter* enabled;
|
BooleanParameter* enabled;
|
||||||
|
|
|
@ -104,6 +104,22 @@ public:
|
||||||
xml->setAttribute("step", step.load());
|
xml->setAttribute("step", step.load());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// opt to not change any values if not found
|
||||||
|
void load(juce::XmlElement* xml) {
|
||||||
|
if (xml->hasAttribute("value")) {
|
||||||
|
value = xml->getDoubleAttribute("value");
|
||||||
|
}
|
||||||
|
if (xml->hasAttribute("min")) {
|
||||||
|
min = xml->getDoubleAttribute("min");
|
||||||
|
}
|
||||||
|
if (xml->hasAttribute("max")) {
|
||||||
|
max = xml->getDoubleAttribute("max");
|
||||||
|
}
|
||||||
|
if (xml->hasAttribute("step")) {
|
||||||
|
step = xml->getDoubleAttribute("step");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// value is not necessarily in the range [min, max] so effect applications may need to clip to a valid range
|
// 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;
|
std::atomic<float> value = 0.0;
|
||||||
|
@ -247,30 +263,36 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
float getValueForText(const juce::String& text) const override {
|
float getValueForText(const juce::String& text) const override {
|
||||||
|
int unnormalisedValue;
|
||||||
if (text == "Static") {
|
if (text == "Static") {
|
||||||
return (int)LfoType::Static;
|
unnormalisedValue = (int)LfoType::Static;
|
||||||
} else if (text == "Sine") {
|
} else if (text == "Sine") {
|
||||||
return (int)LfoType::Sine;
|
unnormalisedValue = (int)LfoType::Sine;
|
||||||
} else if (text == "Square") {
|
} else if (text == "Square") {
|
||||||
return (int)LfoType::Square;
|
unnormalisedValue = (int)LfoType::Square;
|
||||||
} else if (text == "Seesaw") {
|
} else if (text == "Seesaw") {
|
||||||
return (int)LfoType::Seesaw;
|
unnormalisedValue = (int)LfoType::Seesaw;
|
||||||
} else if (text == "Triangle") {
|
} else if (text == "Triangle") {
|
||||||
return (int)LfoType::Triangle;
|
unnormalisedValue = (int)LfoType::Triangle;
|
||||||
} else if (text == "Sawtooth") {
|
} else if (text == "Sawtooth") {
|
||||||
return (int)LfoType::Sawtooth;
|
unnormalisedValue = (int)LfoType::Sawtooth;
|
||||||
} else if (text == "Reverse Sawtooth") {
|
} else if (text == "Reverse Sawtooth") {
|
||||||
return (int)LfoType::ReverseSawtooth;
|
unnormalisedValue = (int)LfoType::ReverseSawtooth;
|
||||||
} else if (text == "Noise") {
|
} else if (text == "Noise") {
|
||||||
return (int)LfoType::Noise;
|
unnormalisedValue = (int)LfoType::Noise;
|
||||||
} else {
|
} else {
|
||||||
return (int)LfoType::Static;
|
unnormalisedValue = (int)LfoType::Static;
|
||||||
}
|
}
|
||||||
|
return getNormalisedValue(unnormalisedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void save(juce::XmlElement* xml) {
|
void save(juce::XmlElement* xml) {
|
||||||
xml->setAttribute("lfo", getText(getValue(), 100));
|
xml->setAttribute("lfo", getText(getValue(), 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void load(juce::XmlElement* xml) {
|
||||||
|
setValueNotifyingHost(getValueForText(xml->getStringAttribute("lfo")));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class EffectParameter : public FloatParameter {
|
class EffectParameter : public FloatParameter {
|
||||||
|
@ -309,5 +331,15 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void load(juce::XmlElement* xml) {
|
||||||
|
FloatParameter::load(xml);
|
||||||
|
|
||||||
|
auto lfoXml = xml->getChildByName("lfo");
|
||||||
|
if (lfoXml != nullptr) {
|
||||||
|
lfo->load(lfoXml);
|
||||||
|
lfoRate->load(lfoXml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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) {}
|
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) {}
|
||||||
};
|
};
|
|
@ -74,13 +74,13 @@ void EffectsListComponent::resized() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<juce::Component> EffectsListComponent::createComponent(EffectParameter* parameter) {
|
std::shared_ptr<juce::Component> EffectsListComponent::createComponent(EffectParameter* parameter) {
|
||||||
if (parameter->paramID == "rotateX" || parameter->paramID == "rotateY" || parameter->paramID == "rotateZ") {
|
if (parameter->paramID == "perspectiveRotateX" || parameter->paramID == "perspectiveRotateY" || parameter->paramID == "perspectiveRotateZ") {
|
||||||
BooleanParameter* toggle;
|
BooleanParameter* toggle;
|
||||||
if (parameter->paramID == "rotateX") {
|
if (parameter->paramID == "perspectiveRotateX") {
|
||||||
toggle = audioProcessor.perspectiveEffect->fixedRotateX;
|
toggle = audioProcessor.perspectiveEffect->fixedRotateX;
|
||||||
} else if (parameter->paramID == "rotateY") {
|
} else if (parameter->paramID == "perspectiveRotateY") {
|
||||||
toggle = audioProcessor.perspectiveEffect->fixedRotateY;
|
toggle = audioProcessor.perspectiveEffect->fixedRotateY;
|
||||||
} else if (parameter->paramID == "rotateZ") {
|
} else if (parameter->paramID == "perspectiveRotateZ") {
|
||||||
toggle = audioProcessor.perspectiveEffect->fixedRotateZ;
|
toggle = audioProcessor.perspectiveEffect->fixedRotateZ;
|
||||||
}
|
}
|
||||||
std::shared_ptr<SvgButton> button = std::make_shared<SvgButton>(parameter->name, BinaryData::fixed_rotate_svg, "white", "red", toggle);
|
std::shared_ptr<SvgButton> button = std::make_shared<SvgButton>(parameter->name, BinaryData::fixed_rotate_svg, "white", "red", toggle);
|
||||||
|
@ -88,7 +88,7 @@ std::shared_ptr<juce::Component> EffectsListComponent::createComponent(EffectPar
|
||||||
toggle->setBoolValueNotifyingHost(!toggle->getBoolValue());
|
toggle->setBoolValueNotifyingHost(!toggle->getBoolValue());
|
||||||
};
|
};
|
||||||
return button;
|
return button;
|
||||||
} else if (parameter->paramID == "depthScale") {
|
} else if (parameter->paramID == "perspectiveStrength") {
|
||||||
std::shared_ptr<SvgButton> button = std::make_shared<SvgButton>(parameter->name, BinaryData::pencil_svg, "white", "red");
|
std::shared_ptr<SvgButton> button = std::make_shared<SvgButton>(parameter->name, BinaryData::pencil_svg, "white", "red");
|
||||||
std::weak_ptr<SvgButton> weakButton = button;
|
std::weak_ptr<SvgButton> weakButton = button;
|
||||||
button->setEdgeIndent(5);
|
button->setEdgeIndent(5);
|
||||||
|
|
|
@ -14,7 +14,19 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
||||||
OscirenderAudioProcessor& audioProcessor;
|
OscirenderAudioProcessor& audioProcessor;
|
||||||
OscirenderAudioProcessorEditor& editor;
|
OscirenderAudioProcessorEditor& editor;
|
||||||
|
|
||||||
AudioEffectListBoxItemData(OscirenderAudioProcessor& p, OscirenderAudioProcessorEditor& editor) : audioProcessor(p), editor(editor) {}
|
AudioEffectListBoxItemData(OscirenderAudioProcessor& p, OscirenderAudioProcessorEditor& editor) : audioProcessor(p), editor(editor) {
|
||||||
|
resetData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetData() {
|
||||||
|
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
|
||||||
|
data.clear();
|
||||||
|
for (int i = 0; i < audioProcessor.toggleableEffects.size(); i++) {
|
||||||
|
auto effect = audioProcessor.toggleableEffects[i];
|
||||||
|
effect->setValue(effect->getValue());
|
||||||
|
data.push_back(effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int getNumItems() override {
|
int getNumItems() override {
|
||||||
return data.size();
|
return data.size();
|
||||||
|
|
Ładowanie…
Reference in New Issue