kopia lustrzana https://github.com/jameshball/osci-render
Save ADSR and voice info to state and add Create New Project option
rodzic
fd8935a589
commit
185737dea8
|
@ -46,6 +46,8 @@ MidiComponent::MidiComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
|
|||
audioProcessor.sustainLevel->addListener(this);
|
||||
audioProcessor.releaseTime->addListener(this);
|
||||
audioProcessor.releaseShape->addListener(this);
|
||||
|
||||
handleAsyncUpdate();
|
||||
}
|
||||
|
||||
MidiComponent::~MidiComponent() {
|
||||
|
|
|
@ -240,6 +240,8 @@ void OscirenderAudioProcessorEditor::changeListenerCallback(juce::ChangeBroadcas
|
|||
if (source == &audioProcessor.broadcaster) {
|
||||
initialiseCodeEditors();
|
||||
settings.update();
|
||||
resized();
|
||||
repaint();
|
||||
} else if (source == &audioProcessor.fileChangeBroadcaster) {
|
||||
// triggered when the audioProcessor changes the current file (e.g. to Blender)
|
||||
settings.fileUpdated(audioProcessor.getCurrentFileName());
|
||||
|
@ -401,3 +403,10 @@ void OscirenderAudioProcessorEditor::openAudioSettings() {
|
|||
juce::StandalonePluginHolder* standalone = juce::StandalonePluginHolder::getInstance();
|
||||
standalone->showAudioSettingsDialog();
|
||||
}
|
||||
|
||||
void OscirenderAudioProcessorEditor::resetToDefault() {
|
||||
juce::StandaloneFilterWindow* window = findParentComponentOfClass<juce::StandaloneFilterWindow>();
|
||||
if (window != nullptr) {
|
||||
window->resetToDefaultState();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
void saveProjectAs();
|
||||
void updateTitle();
|
||||
void openAudioSettings();
|
||||
void resetToDefault();
|
||||
|
||||
std::atomic<bool> editingPerspective = false;
|
||||
|
||||
|
|
|
@ -148,20 +148,29 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
addParameter(parameter);
|
||||
}
|
||||
|
||||
addParameter(attackTime);
|
||||
addParameter(attackLevel);
|
||||
addParameter(attackShape);
|
||||
addParameter(decayTime);
|
||||
addParameter(decayShape);
|
||||
addParameter(sustainLevel);
|
||||
addParameter(releaseTime);
|
||||
addParameter(releaseShape);
|
||||
floatParameters.push_back(attackTime);
|
||||
floatParameters.push_back(attackLevel);
|
||||
floatParameters.push_back(attackShape);
|
||||
floatParameters.push_back(decayTime);
|
||||
floatParameters.push_back(decayShape);
|
||||
floatParameters.push_back(sustainLevel);
|
||||
floatParameters.push_back(releaseTime);
|
||||
floatParameters.push_back(releaseShape);
|
||||
|
||||
for (auto parameter : floatParameters) {
|
||||
addParameter(parameter);
|
||||
}
|
||||
|
||||
for (int i = 0; i < voices->getValueUnnormalised(); i++) {
|
||||
synth.addVoice(new ShapeVoice(*this));
|
||||
}
|
||||
|
||||
addParameter(voices);
|
||||
intParameters.push_back(voices);
|
||||
|
||||
for (auto parameter : intParameters) {
|
||||
addParameter(parameter);
|
||||
}
|
||||
|
||||
voices->addListener(this);
|
||||
|
||||
synth.addSound(defaultSound);
|
||||
|
@ -332,6 +341,26 @@ BooleanParameter* OscirenderAudioProcessor::getBooleanParameter(juce::String id)
|
|||
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
|
||||
void OscirenderAudioProcessor::updateEffectPrecedence() {
|
||||
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);
|
||||
}
|
||||
|
||||
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");
|
||||
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");
|
||||
if (perspectiveFunction != nullptr) {
|
||||
auto stream = juce::MemoryOutputStream();
|
||||
|
|
|
@ -317,6 +317,8 @@ private:
|
|||
bool prevMidiEnabled = !midiEnabled->getBoolValue();
|
||||
|
||||
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>> permanentEffects;
|
||||
|
||||
|
@ -332,6 +334,8 @@ private:
|
|||
void updateObjValues();
|
||||
std::shared_ptr<Effect> getEffect(juce::String id);
|
||||
BooleanParameter* getBooleanParameter(juce::String id);
|
||||
FloatParameter* getFloatParameter(juce::String id);
|
||||
IntParameter* getIntParameter(juce::String id);
|
||||
void openLegacyProject(const juce::XmlElement* xml);
|
||||
std::pair<std::shared_ptr<Effect>, EffectParameter*> effectFromLegacyId(const juce::String& id, bool updatePrecedence = false);
|
||||
LfoType lfoTypeFromLegacyAnimationType(const juce::String& type);
|
||||
|
|
|
@ -858,6 +858,12 @@ void EnvelopeComponent::mouseEnter(const juce::MouseEvent& e)
|
|||
EnvelopeHandleComponent* handle = findHandle(convertPixelsToDomain(e.x));
|
||||
EnvelopeHandleComponent* prevHandle = handle->getPreviousHandle();
|
||||
|
||||
if (handle == nullptr || prevHandle == nullptr) {
|
||||
adjustable = false;
|
||||
setMouseCursor(juce::MouseCursor::NormalCursor);
|
||||
return;
|
||||
}
|
||||
|
||||
auto handleBounds = handle->getBoundsInParent();
|
||||
auto prevHandleBounds = prevHandle->getBoundsInParent();
|
||||
|
||||
|
|
|
@ -227,6 +227,26 @@ public:
|
|||
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:
|
||||
// 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;
|
||||
|
|
|
@ -16,6 +16,9 @@ juce::PopupMenu MainMenuBarModel::getMenuForIndex(int topLevelMenuIndex, const j
|
|||
menu.addItem(1, "Open");
|
||||
menu.addItem(2, "Save");
|
||||
menu.addItem(3, "Save As");
|
||||
if (editor.processor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone) {
|
||||
menu.addItem(4, "Create New Project");
|
||||
}
|
||||
} else if (topLevelMenuIndex == 1) {
|
||||
menu.addItem(1, "Audio Settings");
|
||||
}
|
||||
|
@ -36,6 +39,9 @@ void MainMenuBarModel::menuItemSelected(int menuItemID, int topLevelMenuIndex) {
|
|||
case 3:
|
||||
editor.saveProjectAs();
|
||||
break;
|
||||
case 4:
|
||||
editor.resetToDefault();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue