Save ADSR and voice info to state and add Create New Project option

pull/170/head
James Ball 2023-12-21 14:43:15 +00:00
rodzic fd8935a589
commit 185737dea8
8 zmienionych plików z 118 dodań i 9 usunięć

Wyświetl plik

@ -46,6 +46,8 @@ MidiComponent::MidiComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
audioProcessor.sustainLevel->addListener(this); audioProcessor.sustainLevel->addListener(this);
audioProcessor.releaseTime->addListener(this); audioProcessor.releaseTime->addListener(this);
audioProcessor.releaseShape->addListener(this); audioProcessor.releaseShape->addListener(this);
handleAsyncUpdate();
} }
MidiComponent::~MidiComponent() { MidiComponent::~MidiComponent() {

Wyświetl plik

@ -240,6 +240,8 @@ void OscirenderAudioProcessorEditor::changeListenerCallback(juce::ChangeBroadcas
if (source == &audioProcessor.broadcaster) { if (source == &audioProcessor.broadcaster) {
initialiseCodeEditors(); initialiseCodeEditors();
settings.update(); settings.update();
resized();
repaint();
} else if (source == &audioProcessor.fileChangeBroadcaster) { } else if (source == &audioProcessor.fileChangeBroadcaster) {
// triggered when the audioProcessor changes the current file (e.g. to Blender) // triggered when the audioProcessor changes the current file (e.g. to Blender)
settings.fileUpdated(audioProcessor.getCurrentFileName()); settings.fileUpdated(audioProcessor.getCurrentFileName());
@ -401,3 +403,10 @@ void OscirenderAudioProcessorEditor::openAudioSettings() {
juce::StandalonePluginHolder* standalone = juce::StandalonePluginHolder::getInstance(); juce::StandalonePluginHolder* standalone = juce::StandalonePluginHolder::getInstance();
standalone->showAudioSettingsDialog(); standalone->showAudioSettingsDialog();
} }
void OscirenderAudioProcessorEditor::resetToDefault() {
juce::StandaloneFilterWindow* window = findParentComponentOfClass<juce::StandaloneFilterWindow>();
if (window != nullptr) {
window->resetToDefaultState();
}
}

Wyświetl plik

@ -33,6 +33,7 @@ public:
void saveProjectAs(); void saveProjectAs();
void updateTitle(); void updateTitle();
void openAudioSettings(); void openAudioSettings();
void resetToDefault();
std::atomic<bool> editingPerspective = false; std::atomic<bool> editingPerspective = false;

Wyświetl plik

@ -148,20 +148,29 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
addParameter(parameter); addParameter(parameter);
} }
addParameter(attackTime); floatParameters.push_back(attackTime);
addParameter(attackLevel); floatParameters.push_back(attackLevel);
addParameter(attackShape); floatParameters.push_back(attackShape);
addParameter(decayTime); floatParameters.push_back(decayTime);
addParameter(decayShape); floatParameters.push_back(decayShape);
addParameter(sustainLevel); floatParameters.push_back(sustainLevel);
addParameter(releaseTime); floatParameters.push_back(releaseTime);
addParameter(releaseShape); floatParameters.push_back(releaseShape);
for (auto parameter : floatParameters) {
addParameter(parameter);
}
for (int i = 0; i < voices->getValueUnnormalised(); i++) { for (int i = 0; i < voices->getValueUnnormalised(); i++) {
synth.addVoice(new ShapeVoice(*this)); synth.addVoice(new ShapeVoice(*this));
} }
addParameter(voices); intParameters.push_back(voices);
for (auto parameter : intParameters) {
addParameter(parameter);
}
voices->addListener(this); voices->addListener(this);
synth.addSound(defaultSound); synth.addSound(defaultSound);
@ -332,6 +341,26 @@ BooleanParameter* OscirenderAudioProcessor::getBooleanParameter(juce::String id)
return nullptr; return nullptr;
} }
// effectsLock should be held when calling this
FloatParameter* OscirenderAudioProcessor::getFloatParameter(juce::String id) {
for (auto& parameter : floatParameters) {
if (parameter->paramID == id) {
return parameter;
}
}
return nullptr;
}
// effectsLock should be held when calling this
IntParameter* OscirenderAudioProcessor::getIntParameter(juce::String id) {
for (auto& parameter : intParameters) {
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) {
@ -639,6 +668,18 @@ void OscirenderAudioProcessor::getStateInformation(juce::MemoryBlock& destData)
parameter->save(parameterXml); parameter->save(parameterXml);
} }
auto floatParametersXml = xml->createNewChildElement("floatParameters");
for (auto parameter : floatParameters) {
auto parameterXml = floatParametersXml->createNewChildElement("parameter");
parameter->save(parameterXml);
}
auto intParametersXml = xml->createNewChildElement("intParameters");
for (auto parameter : intParameters) {
auto parameterXml = intParametersXml->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()));
@ -703,6 +744,26 @@ void OscirenderAudioProcessor::setStateInformation(const void* data, int sizeInB
} }
} }
auto floatParametersXml = xml->getChildByName("floatParameters");
if (floatParametersXml != nullptr) {
for (auto parameterXml : floatParametersXml->getChildIterator()) {
auto parameter = getFloatParameter(parameterXml->getStringAttribute("id"));
if (parameter != nullptr) {
parameter->load(parameterXml);
}
}
}
auto intParametersXml = xml->getChildByName("intParameters");
if (intParametersXml != nullptr) {
for (auto parameterXml : intParametersXml->getChildIterator()) {
auto parameter = getIntParameter(parameterXml->getStringAttribute("id"));
if (parameter != nullptr) {
parameter->load(parameterXml);
}
}
}
auto perspectiveFunction = xml->getChildByName("perspectiveFunction"); auto perspectiveFunction = xml->getChildByName("perspectiveFunction");
if (perspectiveFunction != nullptr) { if (perspectiveFunction != nullptr) {
auto stream = juce::MemoryOutputStream(); auto stream = juce::MemoryOutputStream();

Wyświetl plik

@ -317,6 +317,8 @@ private:
bool prevMidiEnabled = !midiEnabled->getBoolValue(); bool prevMidiEnabled = !midiEnabled->getBoolValue();
std::vector<BooleanParameter*> booleanParameters; std::vector<BooleanParameter*> booleanParameters;
std::vector<FloatParameter*> floatParameters;
std::vector<IntParameter*> intParameters;
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;
@ -332,6 +334,8 @@ private:
void updateObjValues(); void updateObjValues();
std::shared_ptr<Effect> getEffect(juce::String id); std::shared_ptr<Effect> getEffect(juce::String id);
BooleanParameter* getBooleanParameter(juce::String id); BooleanParameter* getBooleanParameter(juce::String id);
FloatParameter* getFloatParameter(juce::String id);
IntParameter* getIntParameter(juce::String id);
void openLegacyProject(const juce::XmlElement* xml); void openLegacyProject(const juce::XmlElement* xml);
std::pair<std::shared_ptr<Effect>, EffectParameter*> effectFromLegacyId(const juce::String& id, bool updatePrecedence = false); std::pair<std::shared_ptr<Effect>, EffectParameter*> effectFromLegacyId(const juce::String& id, bool updatePrecedence = false);
LfoType lfoTypeFromLegacyAnimationType(const juce::String& type); LfoType lfoTypeFromLegacyAnimationType(const juce::String& type);

Wyświetl plik

@ -858,6 +858,12 @@ void EnvelopeComponent::mouseEnter(const juce::MouseEvent& e)
EnvelopeHandleComponent* handle = findHandle(convertPixelsToDomain(e.x)); EnvelopeHandleComponent* handle = findHandle(convertPixelsToDomain(e.x));
EnvelopeHandleComponent* prevHandle = handle->getPreviousHandle(); EnvelopeHandleComponent* prevHandle = handle->getPreviousHandle();
if (handle == nullptr || prevHandle == nullptr) {
adjustable = false;
setMouseCursor(juce::MouseCursor::NormalCursor);
return;
}
auto handleBounds = handle->getBoundsInParent(); auto handleBounds = handle->getBoundsInParent();
auto prevHandleBounds = prevHandle->getBoundsInParent(); auto prevHandleBounds = prevHandle->getBoundsInParent();

Wyświetl plik

@ -227,6 +227,26 @@ public:
return juce::AudioProcessorParameter::genericParameter; return juce::AudioProcessorParameter::genericParameter;
} }
void save(juce::XmlElement* xml) {
xml->setAttribute("id", paramID);
xml->setAttribute("value", value.load());
xml->setAttribute("min", min.load());
xml->setAttribute("max", max.load());
}
// opt to not change any values if not found
void load(juce::XmlElement* xml) {
if (xml->hasAttribute("value")) {
value = xml->getIntAttribute("value");
}
if (xml->hasAttribute("min")) {
min = xml->getIntAttribute("min");
}
if (xml->hasAttribute("max")) {
max = xml->getIntAttribute("max");
}
}
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<int> value = 0; std::atomic<int> value = 0;

Wyświetl plik

@ -16,6 +16,9 @@ juce::PopupMenu MainMenuBarModel::getMenuForIndex(int topLevelMenuIndex, const j
menu.addItem(1, "Open"); menu.addItem(1, "Open");
menu.addItem(2, "Save"); menu.addItem(2, "Save");
menu.addItem(3, "Save As"); menu.addItem(3, "Save As");
if (editor.processor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone) {
menu.addItem(4, "Create New Project");
}
} else if (topLevelMenuIndex == 1) { } else if (topLevelMenuIndex == 1) {
menu.addItem(1, "Audio Settings"); menu.addItem(1, "Audio Settings");
} }
@ -36,6 +39,9 @@ void MainMenuBarModel::menuItemSelected(int menuItemID, int topLevelMenuIndex) {
case 3: case 3:
editor.saveProjectAs(); editor.saveProjectAs();
break; break;
case 4:
editor.resetToDefault();
break;
default: default:
break; break;
} }