26 size_t channelsPerStereoBus,
size_t numRecorders,
27 size_t numInputChannels,
size_t numOutputChannels)
28 : AudioProcessor(ioLayouts),
29 m_autoplay{{
"CoreEngine0",
false}, {
"CoreEngine1",
false}, {
"CoreEngine2",
false}, {
"CoreEngine3",
false}},
30 m_audioOuts(numBusses), m_channelsPerStereoBus(channelsPerStereoBus), m_numRecorders(numRecorders),
31 m_numVoices(NUM_VOICES_TOTAL),
32 m_mainGraph(m_numVoices, numInputChannels,
35 m_modulatorGraph(m_numVoices, numInputChannels, numOutputChannels),
36 m_synthPoly(m_mainGraph, m_modulatorGraph, 0, NUM_VOICES_POLY,
38 m_synthDrone(m_mainGraph, m_modulatorGraph, NUM_VOICES_POLY, NUM_VOICES_DRONE,
40 parameterManager(*
this)
42 initialiseStateListeners();
44 m_presetEventMiddleware.addHook(std::make_unique<RelativeSamplePathRewriteHook>());
46 presetManager.presetChanged = [
this](
const ValueTree& newState) {
48 auto setNewStateSuccess = setState(newState);
50 if (!setNewStateSuccess)
53 PresetManagerUI::alertStateValidation();
55 if (m_globalAutoplayOn)
57 triggerRecordingStart();
58 m_synthDrone.noteOn(1, MIDI_NOTE_FLAG_DRONE + MIDI_NOTE_NUMBER_C3, 1.0f);
62 initialiseSettingsFileValues();
63 initialiseAudioOutConfiguration();
65 initialiseRecorders();
68 if (!host.isPluginval())
73 KwidgetAudioProcessor::~KwidgetAudioProcessor()
86 masterReference.clear();
89 void KwidgetAudioProcessor::setInitialState()
94 presetManager.getInitPresetFile()
96 m_lastLoadedPresetPath = m_initPresetPath;
111 auto setNewStateSuccess =
112 setState(PresetManager::getValueTreeFromFile(File(m_lastLoadedPresetPath)));
114 if (setNewStateSuccess)
116 m_shouldInit =
false;
121 PresetManagerUI::alertStateValidation();
127 MessageManager::callAsync([
this, target = WeakReference<KwidgetAudioProcessor>{
this}] {
128 if (target && m_shouldInit)
130 presetManager.setCurrentPreset(m_lastLoadedPresetPath);
131 m_shouldInit =
false;
139 std::cout << ex.
what() << std::endl;
143 void KwidgetAudioProcessor::removeEngines()
145 suspendProcessing(
true);
146 removeKwidgetsOfType({KType::CoreEngine, KType::Reformer});
147 suspendProcessing(
false);
150 void KwidgetAudioProcessor::initialiseSettingsFileValues()
153 settingsFile.setDefaultIfVoid(autoPlayMaxDuration, 180);
156 settingsFile.setDefaultIfVoid(recorderReleaseTime, 1.5);
159 settingsFile.setDefaultIfVoid(DroppedFileNameFormat, DefaultDroppedFileNameFormat);
162 settingsFile.setDefaultIfVoid(T2PStrictMode,
false);
165 void KwidgetAudioProcessor::initialiseAudioOutConfiguration()
168 const int channelIncrement = m_channelsPerStereoBus;
169 for (
int i = 0; i < m_audioOuts.size(); ++i)
172 String audioOutID = i == 0 ? m_masterAudioOutID : KType::AudioOut + String(i);
174 m_audioOuts[i] = addKwidgetWithID(KType::AudioOut, audioOutID,
true);
175 m_mainGraph.connectToOutputNode(m_audioOuts[i], i * channelIncrement, m_channelsPerStereoBus);
183 jassert(m_audioOuts[i]->getParameters().size() == 2);
189 jassert(m_audioOuts[0] !=
nullptr);
190 m_masterAudioOut = m_audioOuts[0];
193 m_masterAudioOut->addParameterCallback(Kwidget_AudioOut::Parameters::Autoplay, [
this](
float newValue) {
194 autoPlayGlobalChanged(newValue > ParameterManager::OnOffThreshold);
200 addKwidgetWithID(KType::AudioOut, KwidgetFactory::KwidgetModifiers::SandBox + KType::AudioOut,
true);
207 jassert(m_masterAudioOut->getParameters().size() == 4);
210 void KwidgetAudioProcessor::initialiseRecorders()
212 for (
int i = 0; i < m_numRecorders; i++)
215 String recorderID = KType::Recorder + (i > 0 ? String(i) :
"");
216 std::unique_ptr<Kwidget> m_recorder_tmp = std::make_unique<Kwidget_Recorder>(recorderID);
217 m_recorders[i] = std::move(m_recorder_tmp);
218 parameterManager.addKwidget(m_recorders[i].get());
219 m_kwidgets.add(m_recorders[i].get());
221 m_kwidgetLookup[m_recorders[i]->getKwidgetID()] = m_recorders[i].get();
225 void KwidgetAudioProcessor::initialiseMasterFX()
227 String masterFilterID = KMod::MasterFX + KType::Filter;
228 m_masterFilter = std::make_unique<Kwidget_Filter>(masterFilterID);
229 parameterManager.addKwidget(m_masterFilter.get(),
true,
false);
230 m_kwidgets.add(m_masterFilter.get());
231 m_kwidgetLookup[m_masterFilter->getKwidgetID()] = m_masterFilter.get();
233 String masterReverbID = KMod::MasterFX + KType::ConvolutionReverb;
234 m_masterReverb = std::make_unique<Kwidget_ConvolutionReverb>(masterReverbID);
235 parameterManager.addKwidget(m_masterReverb.get(),
true,
false);
236 m_kwidgets.add(m_masterReverb.get());
237 m_kwidgetLookup[m_masterReverb->getKwidgetID()] = m_masterReverb.get();
238 m_masterReverb->getCustomParameter(Kwidget_ConvolutionReverb::Parameters::ImpulsePath)
239 ->setValue(utils::StringsIntoPath(Kwidget_ConvolutionReverb::getDefaultImpulsePath(),
"D_Equipment",
240 "Classic Hall.wav"));
242 String macroSliderID = KMod::MasterFX + KType::MacroSlider;
243 m_intensityMacro = std::make_unique<Kwidget_MacroSlider>(macroSliderID);
244 parameterManager.addKwidget(m_intensityMacro.get(),
true,
false);
245 m_kwidgets.add(m_intensityMacro.get());
246 m_kwidgetLookup[m_intensityMacro->getKwidgetID()] = m_intensityMacro.get();
253 jassert(m_masterReverb->getParameters().size() == 4);
254 jassert(m_masterFilter->getParameters().size() == 6);
255 jassert(m_intensityMacro->getParameters().size() == 1);
258 m_masterAudioOut->getParameter(Kwidget_AudioOut::Parameters::FXActivation)->set(0.0f);
261 m_audioOutFxEnabledParameter = m_masterAudioOut->getParameter(Kwidget_AudioOut::Parameters::FXActivation);
264 parameterManager.addModulation(macroSliderID, 0, masterFilterID, Kwidget_Filter::Parameters::Cutoff, -0.8f,
265 KAttachment::Polarity::Unipolar);
266 parameterManager.addModulation(macroSliderID, 0, masterReverbID, Kwidget_ConvolutionReverb::Parameters::Mix,
267 1.0f, KAttachment::Polarity::Unipolar);
290 void KwidgetAudioProcessor::soloActivatedAllEngines(
const String& callingID)
296 for (
auto& k : m_kwidgets)
298 if (k->isAChildKwidget())
302 else if (k->getKwidgetType() == KType::Reformer)
305 if (k->getKwidgetID() == callingID)
307 k->getParameter(Kwidget_Reformer::Parameters::Mute)->set(0.0f);
311 k->getParameter(Kwidget_Reformer::Parameters::Mute)->set(1.0f);
312 k->getParameter(Kwidget_Reformer::Parameters::Solo)->set(0.0f);
315 else if (k->getKwidgetType() == KType::CoreEngine)
318 if (k->getKwidgetID() == callingID)
320 k->getParameter(Kwidget_CoreEngine::Parameters::Mute)->set(0.0f);
324 k->getParameter(Kwidget_CoreEngine::Parameters::Mute)->set(1.0f);
325 k->getParameter(Kwidget_CoreEngine::Parameters::Solo)->set(0.0f);
331 void KwidgetAudioProcessor::soloDeActivatedAllEngines(
const String& callingID)
336 for (
auto& k : m_kwidgets)
338 if (k->isAChildKwidget() || k->getKwidgetID() == callingID)
342 else if (k->getKwidgetType() == KType::Reformer)
344 k->getParameter(Kwidget_Reformer::Parameters::Mute)->set(0.0f);
346 else if (k->getKwidgetType() == KType::CoreEngine)
348 k->getParameter(Kwidget_CoreEngine::Parameters::Mute)->set(0.0f);
353 void KwidgetAudioProcessor::triggerRecordingStart()
355 if (isTimerRunning() ==
false)
358 auto autoplayMaxDurationValue = settingsFile.getSetting(autoPlayMaxDuration);
361 int maxDuration = autoplayMaxDurationValue.isVoid() ? 180 :
static_cast<int>(autoplayMaxDurationValue);
363 startTimer(maxDuration * 1000);
366 m_recordingTriggerStarted =
true;
368 for (
auto& m_recorderTmp : m_recorders)
370 m_recorderTmp->getActiveVoice()->noteOn(MIDI_NOTE_NUMBER_C3, 1.0f);
374 void KwidgetAudioProcessor::triggerRecordingStop()
376 m_recordingTriggerStarted =
false;
378 for (
auto& m_recorderTmp : m_recorders)
380 m_recorderTmp->getActiveVoice()->noteOff(1.0f);
384 void KwidgetAudioProcessor::parameterValueChanged(
int ,
float )
390 for (
auto* kw : m_kwidgets)
392 if (kw->getKwidgetType().contains(KType::XyPad))
394 for (
auto kwParam : kw->getParameters())
396 if (kwParam->paramID == Kwidget_XyPad::Parameters::toggleOn)
398 m_xypadTriggerOn = kw->getParameter(Kwidget_XyPad::Parameters::toggleOn)->getValue() >
399 ParameterManager::OnOffThreshold;
402 if (kwParam->paramID == Kwidget_XyPad::Parameters::onClick)
404 m_xypadTriggerOn = kw->getParameter(Kwidget_XyPad::Parameters::toggleOn)->getValue() >
405 ParameterManager::OnOffThreshold;
407 if (m_xypadTriggerOn ==
true && m_globalAutoplayOn ==
false)
409 if (kwParam->getValue() > ParameterManager::OnOffThreshold &&
410 m_previousTriggerValue <= ParameterManager::OnOffThreshold)
412 m_synthPoly.noteOn(1, MIDI_NOTE_NUMBER_C3, 1.0f);
413 triggerRecordingStart();
415 else if (kwParam->getValue() <= ParameterManager::OnOffThreshold &&
416 m_previousTriggerValue > ParameterManager::OnOffThreshold)
418 m_synthPoly.noteOff(1, MIDI_NOTE_NUMBER_C3, 1.0f,
true);
419 triggerRecordingStop();
421 m_previousTriggerValue = kwParam->getValue();
430 AudioBuffer<float> KwidgetAudioProcessor::extractStereoBuffer(
int numChannel1,
int numChannel2,
431 AudioBuffer<float>& multiChannelBuffer)
433 float* channels[2] = {multiChannelBuffer.getWritePointer(numChannel1),
434 multiChannelBuffer.getWritePointer(numChannel2)};
435 AudioBuffer<float> buffer(channels, 2, 0, multiChannelBuffer.getNumSamples());
439 void KwidgetAudioProcessor::autoPlayGlobalChanged(
bool enableAutoplay)
441 if (m_globalAutoplayOn == enableAutoplay)
444 if (enableAutoplay && !m_globalAutoplayOn)
447 auto autoplayMaxDurationValue = settingsFile.getSetting(autoPlayMaxDuration);
450 int maxDuration = autoplayMaxDurationValue.isVoid() ? 180 :
static_cast<int>(autoplayMaxDurationValue);
452 startTimer(maxDuration * 1000);
454 triggerRecordingStart();
457 m_synthDrone.noteOn(1, MIDI_NOTE_FLAG_DRONE + MIDI_NOTE_NUMBER_C3, 1.0f);
459 else if (!enableAutoplay)
466 1, MIDI_NOTE_FLAG_DRONE_NOTEUP + MIDI_NOTE_FLAG_FLUSH + MIDI_NOTE_FLAG_DRONE + MIDI_NOTE_NUMBER_C3,
469 triggerRecordingStop();
472 m_globalAutoplayOn = enableAutoplay;
475 void KwidgetAudioProcessor::timerCallback()
477 autoPlayGlobalChanged(
false);
479 if (onAutoplayTimerStop !=
nullptr)
481 onAutoplayTimerStop();
488 m_autoplay[thisID.toRawUTF8()] = (bool)(newValue > ParameterManager::OnOffThreshold);
493 void KwidgetAudioProcessor::addKListener(
KListener* l) { m_listeners.add(l); }
495 void KwidgetAudioProcessor::removeKListener(
KListener* l) { m_listeners.remove(l); }
497 void KwidgetAudioProcessor::prepareToPlay(
double sampleRate,
int samplesPerBlock)
499 m_synthPoly.setCurrentPlaybackSampleRate(sampleRate);
500 m_synthPoly.setSamePitchNoteStealingEnable(
false);
501 m_synthDrone.setCurrentPlaybackSampleRate(sampleRate);
502 m_synthDrone.setNoteStealingEnabled(
true);
503 m_mainGraph.prepareToPlay(sampleRate, samplesPerBlock);
504 m_modulatorGraph.prepareToPlay(sampleRate, samplesPerBlock);
505 notifyAllKwidgetsParametersListeners();
507 for (
auto& m_recorderTmp : m_recorders)
509 m_recorderTmp->getActiveVoice()->prepareToPlay(sampleRate, samplesPerBlock);
513 m_masterFilter.get()->getActiveVoice()->prepareToPlay(sampleRate, samplesPerBlock);
516 m_masterReverb.get()->getActiveVoice()->prepareToPlay(sampleRate, samplesPerBlock);
518 if (m_globalAutoplayOn)
520 m_synthDrone.noteOn(1, MIDI_NOTE_FLAG_DRONE + MIDI_NOTE_NUMBER_C3, 1.0f);
524 void KwidgetAudioProcessor::processBlock(AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
533 m_synthPoly.processBlock(buffer, midiMessages);
535 if (m_globalAutoplayOn ==
true)
538 midiMessages.clear();
541 m_synthDrone.processBlock(buffer, midiMessages);
544 buffer.applyGain(Decibels::decibelsToGain<float>(
547 if (!bypassPostFx && m_audioOutFxEnabledParameter->get() > ParameterManager::OnOffThreshold)
551 auto stereoBufferTmp = extractStereoBuffer(0, 1, buffer);
552 m_masterFilter.get()->getActiveVoice()->processBlock(stereoBufferTmp, midiMessages);
553 m_masterReverb.get()->getActiveVoice()->processBlock(stereoBufferTmp, midiMessages);
557 recordOutput(buffer, midiMessages);
560 void KwidgetAudioProcessor::recordOutput(AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
563 int m_activeRecorders = 1;
564 for (
int i = 0; i < m_activeRecorders; i++)
567 auto bufferTmp = extractStereoBuffer(chan, chan + 1, buffer);
570 String s = String(KType::CoreEngine) + String(i - 1);
572 if (m_autoplay[s.toRawUTF8()] ==
false)
579 m_recorders[i]->getActiveVoice()->processBlock(bufferTmp, midiMessages);
583 Kwidget* KwidgetAudioProcessor::addKwidgetWithID(
const String& kwidgetType,
const String& kwidgetID,
584 bool useEndParams,
bool isChildKwidget)
587 m_addedFromState =
false;
589 auto newKwidget = KwidgetFactory::createKwidget(kwidgetType, kwidgetID);
591 auto newKwidgetPtr = newKwidget.get();
593 if (!parameterManager.addKwidget(newKwidgetPtr, useEndParams, isChildKwidget))
596 addKwidgetInternal(std::move(newKwidget));
597 return newKwidgetPtr;
600 Kwidget* KwidgetAudioProcessor::addChildKwidget(
const String& kwidgetType,
const String& parentID,
601 const String& childID,
int typeLimit)
604 m_addedFromState =
false;
606 String baseKwidgetID = parentID + Kwidget::Constants::ChildDelimiter +
609 auto autoGeneratedkwidgetID = parameterManager.generateKwidgetID(
610 baseKwidgetID,
"", typeLimit);
612 auto newKwidget = KwidgetFactory::createKwidget(kwidgetType, autoGeneratedkwidgetID);
613 auto newKwidgetPtr = newKwidget.get();
615 if (!parameterManager.addKwidget(newKwidgetPtr,
false,
true))
618 addKwidgetInternal(std::move(newKwidget));
619 newKwidgetPtr = m_kwidgets.getLast();
621 return newKwidgetPtr;
624 Kwidget* KwidgetAudioProcessor::addUserKwidget(
const String& kwidgetType,
const String& idModifier,
625 int typeInstanceLimit)
628 m_addedFromState =
false;
632 String kwidgetID = parameterManager.generateKwidgetID(kwidgetType, idModifier, typeInstanceLimit);
639 auto newKwidget = KwidgetFactory::createKwidget(kwidgetType, kwidgetID);
641 if (newKwidget ==
nullptr)
647 auto newKwidgetPtr = newKwidget.get();
649 if (!parameterManager.addKwidget(newKwidgetPtr))
657 coreEngineKwidget->canReadSpecificFiles(m_readSpecificFiles);
659 else if (
auto reformerKwidget =
dynamic_cast<Kwidget_Reformer*
>(newKwidgetPtr))
661 reformerKwidget->canReadSpecificFiles(m_readSpecificFiles);
664 addKwidgetInternal(std::move(newKwidget));
667 newKwidgetPtr = m_kwidgets.getLast();
669 makeStaticConnectionsForKwidget(newKwidgetPtr);
671 newKwidgetPtr->createNestedKwidgets(*
this);
677 coreEngineKwidget->addListener(
this);
679 else if (
auto reformerKwidget =
dynamic_cast<Kwidget_Reformer*
>(newKwidgetPtr))
682 reformerKwidget->addListener(
this);
685 return newKwidgetPtr;
688 void KwidgetAudioProcessor::removeKwidget(
const String& kwidgetID)
690 if (m_kwidgetLookup.count(kwidgetID) == 1)
692 auto kwidget = m_kwidgetLookup.at(kwidgetID);
695 if (
auto xyPadKwidget =
dynamic_cast<Kwidget_XyPad*
>(kwidget))
697 xyPadKwidget->getParameter(Kwidget_XyPad::Parameters::onClick)->removeListener(
this);
698 xyPadKwidget->getParameter(Kwidget_XyPad::Parameters::toggleOn)->removeListener(
this);
699 xyPadKwidget->setKwidgetAudioProcessorReference(
nullptr);
703 triggerButtonKwidget->removeListener(
this);
708 coreEngineKwidget->removeListener(
this);
711 std::vector<Kwidget*>& children = kwidget->getChildKwidgets();
714 for (
int i =
static_cast<int>(children.size()) - 1; i >= 0; i--)
716 removeKwidget(children.at(i)->getKwidgetID());
721 parameterManager.removeKwidget(kwidgetID);
725 m_kwidgets.removeFirstMatchingValue(kwidget);
727 m_kwidgetLookup.erase(kwidgetID);
729 if (kwidget->isModulator())
730 m_modulatorGraph.removeKwidget(kwidget);
732 m_mainGraph.removeKwidget(kwidget);
744 void KwidgetAudioProcessor::removeDynamicKwidgets() { removeKwidgetsExcluding({}); }
746 void KwidgetAudioProcessor::removeKwidgetsExcluding(
const StringArray& kwidgetsToExclude)
748 std::vector<Kwidget*> kwidgetsToRemove;
750 for (
auto& k : m_kwidgets)
752 auto id = k->getKwidgetID();
753 auto type = k->getKwidgetType();
755 if (!kwidgetsToExclude.contains(
id) && !k->isAChildKwidget() && !isAStaticKwidget(*k))
758 kwidgetsToRemove.push_back(k);
762 for (
auto& k : kwidgetsToRemove)
764 removeKwidget(k->getKwidgetID());
768 void KwidgetAudioProcessor::removeKwidgetsOfType(
const StringArray& kwidgetTypesToRemove)
770 std::vector<Kwidget*> kwidgetsToRemove;
772 for (
auto& k : m_kwidgets)
774 auto kType = k->getKwidgetType();
775 if ((kwidgetTypesToRemove.contains(kType)) && !isAStaticKwidget(*k) &&
776 (!k->isAChildKwidget()))
777 kwidgetsToRemove.push_back(k);
780 for (
auto& k : kwidgetsToRemove)
782 removeKwidget(k->getKwidgetID());
786 const bool KwidgetAudioProcessor::isAStaticKwidget(
const Kwidget& kwidget)
789 isStatic |= StaticKwidgetIDs.contains(kwidget.
getKwidgetID());
793 bool KwidgetAudioProcessor::addConnection(
const String& sourceID,
const String& destID)
795 if (!m_kwidgetLookup.count(sourceID))
802 if (!m_kwidgetLookup.count(destID))
809 auto src = m_kwidgetLookup.at(sourceID);
810 auto dest = m_kwidgetLookup.at(destID);
813 jassert(!src->isModulator() && !dest->isModulator());
815 if (!m_mainGraph.canConnect(src, dest))
821 parameterManager.addConnection(sourceID, destID);
826 bool KwidgetAudioProcessor::makeStaticConnectionsForKwidget(
Kwidget* kwidget)
832 if (kwidget !=
nullptr)
839 if (kwidgetID.contains(KwidgetFactory::KwidgetModifiers::SandBox))
848 auto masterOutID = m_masterAudioOut->getKwidgetID();
852 if (kwidgetID.startsWith(
"Tab"))
854 int tabIndex = kwidgetID.substring(3, 4).getIntValue();
856 retVal &= addConnection(kwidgetID, masterOutID);
857 retVal &= addConnection(kwidgetID,
858 m_audioOuts[tabIndex]->getKwidgetID());
864 retVal &= addConnection(kwidgetID, masterOutID);
865 retVal &= addConnection(kwidgetID, m_audioOuts[1]->getKwidgetID());
875 void KwidgetAudioProcessor::clearModulation()
877 if (m_intensityMacro !=
nullptr)
879 parameterManager.clearModulationExcept(m_intensityMacro.get()->getKwidgetID());
883 parameterManager.clearModulation();
887 void KwidgetAudioProcessor::loadBundle(
const File& bundleDir)
889 auto presetFile = PresetBundler::getPresetFromBundleDirectory(bundleDir);
890 presetManager.setCurrentPreset(presetFile);
893 bool KwidgetAudioProcessor::setState(
const ValueTree& newState)
896 loadRequest.
newState =
const_cast<ValueTree&
>(newState);
897 loadRequest.
presetFile = presetManager.getCurrentPreset().path;
898 auto loadResponse = m_presetEventMiddleware.processPresetLoad(loadRequest);
899 if (!loadResponse.success)
901 DBG(loadResponse.message);
906 auto validationSuccess = validateState(newState,
true);
908 if (!validationSuccess)
912 for (
int i = 0; i < m_numRecorders; i++)
918 suspendProcessing(
true);
920 parameterManager.clearConnections();
922 removeDynamicKwidgets();
924 auto kwidgetTree = newState.getChildWithName(XmlType::Tag::kwidgets);
928 auto masterAudioOutTree =
929 kwidgetTree.getChildWithProperty(XmlType::Property::id, m_masterAudioOut->getKwidgetID());
931 auto masterFilterTree =
932 kwidgetTree.getChildWithProperty(XmlType::Property::id, m_masterFilter.get()->getKwidgetID());
934 auto masterReverbTree =
935 kwidgetTree.getChildWithProperty(XmlType::Property::id, m_masterReverb.get()->getKwidgetID());
938 for (
int i = 0; i < StaticKwidgetTypes.size(); ++i)
940 auto staticKwidgetTree = kwidgetTree.getChildWithProperty(XmlType::Property::type, StaticKwidgetTypes[i]);
941 kwidgetTree.removeChild(staticKwidgetTree,
nullptr);
944 auto intensityMacroTree =
945 kwidgetTree.getChildWithProperty(XmlType::Property::id, m_intensityMacro.get()->getKwidgetID());
946 kwidgetTree.removeChild(intensityMacroTree,
nullptr);
950 ValueTree customDataTree = newState.getChildWithName(XmlType::Tag::customData);
951 if (customDataTree.isValid())
953 auto lastLoadedPreset = customDataTree.getChildWithName(XmlType::Tag::LastLoadedPreset);
954 if (lastLoadedPreset.isValid())
956 m_lastLoadedPresetPath =
957 lastLoadedPreset.getProperty(XmlType::Property::LastLoadedPresetName).toString();
958 if (m_lastLoadedPresetPath.isEmpty())
960 m_lastLoadedPresetPath = m_initPresetPath;
967 parameterManager.getCustomDataTree().copyPropertiesAndChildrenFrom(
968 newState.getChildWithName(XmlType::Tag::customData),
nullptr);
971 for (
const auto& kwidget : kwidgetTree)
976 String kwidgetType = kwidget.getProperty(XmlType::Property::type);
978 if (!isAStaticKwidgetType(kwidgetType))
980 addKwidgetFromState(kwidget);
984 parameterManager.setCurrentState(newState);
987 m_masterAudioOut->setState(masterAudioOutTree, *
this);
988 m_masterFilter->setState(masterFilterTree, *
this);
989 m_masterReverb->setState(masterReverbTree, *
this);
990 m_intensityMacro->setState(intensityMacroTree, *
this);
993 addConnection(m_audioOutSandBox->getKwidgetID(), m_masterAudioOut->getKwidgetID());
996 const String presetName =
997 File::createFileWithoutCheckingPath(m_lastLoadedPresetPath).getFileNameWithoutExtension();
998 setRecordersNameData(presetName);
1001 suspendProcessing(
false);
1012 notifyAllKwidgetsParametersListeners();
1017 bool KwidgetAudioProcessor::validateState(
const ValueTree& newState,
bool repairEnabled)
1019 auto paramTreeGeneric = newState.getChildWithName(XmlType::Tag::params);
1021 bool noFailures = parameterManager.initialiseLinkIndexUsageTable(newState, repairEnabled);
1023 noFailures &= parameterManager.initialiseKwidgetIDUsageTable(newState, repairEnabled);
1025 auto kwidgetTree = newState.getChildWithName(XmlType::Tag::kwidgets);
1028 for (
auto kwidget : kwidgetTree)
1030 noFailures &= parameterManager.validateKwidgetState(kwidget, paramTreeGeneric, repairEnabled);
1031 auto childKwidgetTree = kwidget.getChildWithName(XmlType::Tag::kwidgets);
1032 for (
auto ckwidget : childKwidgetTree)
1034 noFailures &= parameterManager.validateKwidgetState(ckwidget, paramTreeGeneric, repairEnabled);
1041 void KwidgetAudioProcessor::notifyAllKwidgetsParametersListeners()
1043 for (
auto& kwidget : m_kwidgets)
1045 kwidget->notifyAllParametersListeners();
1049 ValueTree KwidgetAudioProcessor::getState()
1051 for (
const auto& k : m_kwidgetLookup)
1052 k.second->flushState();
1054 m_masterAudioOut->flushState();
1056 return parameterManager.getState().createCopy();
1059 const Array<Kwidget*>& KwidgetAudioProcessor::getKwidgets() {
return m_kwidgets; }
1061 Kwidget* KwidgetAudioProcessor::getKwidget(
const String& kwidgetID)
1063 if (kwidgetID.contains(
":") ==
true)
1066 int parentIDIndex = kwidgetID.indexOf(Kwidget::Constants::ChildDelimiter);
1067 if (parentIDIndex > 0)
1069 String parentID = kwidgetID.substring(0, parentIDIndex);
1071 if (m_kwidgetLookup.count(parentID) > 0)
1073 return m_kwidgetLookup.at(parentID)->findChildKwidget(kwidgetID);
1078 if (m_kwidgetLookup.count(kwidgetID) > 0)
1080 return m_kwidgetLookup.at(kwidgetID);
1089 const Array<Kwidget*> KwidgetAudioProcessor::getKwidgetsOfType(
const String kwidgetType)
1091 Array<Kwidget*> typedKwidgets;
1094 for (
auto& kwidget : m_kwidgets)
1096 if (kwidget->getKwidgetType() == kwidgetType)
1098 typedKwidgets.add(kwidget);
1102 return typedKwidgets;
1105 const Array<Kwidget*> KwidgetAudioProcessor::getKwidgetsOfTypeWithAccessPermission(
const StringRef kwidgetType,
1106 const StringRef reqId)
1108 Array<Kwidget*> typedKwidgets;
1111 for (
auto& kwidget : m_kwidgets)
1113 if (kwidget->getKwidgetType() == kwidgetType)
1116 if (kwidget->requestAccess(reqId))
1118 typedKwidgets.add(kwidget);
1123 return typedKwidgets;
1126 Kwidget* KwidgetAudioProcessor::getKwidgetWithAccessPermission(
const String& kwidgetID,
const StringRef reqId)
1130 const juce::ScopedLock scopedLock(m_lock);
1132 auto kwidget = getKwidget(kwidgetID);
1135 if (kwidget !=
nullptr)
1138 if (kwidget->requestAccess(reqId))
1148 void KwidgetAudioProcessor::getStateInformation(MemoryBlock& destData)
1150 auto currentState = getState();
1153 auto customData = currentState.getChildWithName(XmlType::Tag::customData);
1154 if (customData.isValid())
1157 auto lastPresetField = customData.getChildWithName(XmlType::Tag::LastLoadedPreset);
1158 if (lastPresetField.isValid())
1167 if (presetInfoTree !=
nullptr)
1169 auto m_vtCopy = presetInfoTree->createCopy();
1170 m_vtCopy.setProperty(XmlType::Property::LastLoadedPresetName, m_lastLoadedPresetPath,
nullptr);
1171 customData.appendChild(m_vtCopy,
nullptr);
1175 std::unique_ptr<XmlElement> xml(currentState.createXml());
1176 copyXmlToBinary(*xml, destData);
1179 void KwidgetAudioProcessor::setStateInformation(
const void* incomingData,
int sizeInBytes)
1181 std::unique_ptr<XmlElement> xmlState(getXmlFromBinary(incomingData, sizeInBytes));
1182 if (xmlState.get() !=
nullptr)
1184 auto stateFromXML = ValueTree::fromXml(*xmlState);
1186 auto setNewStateSuccess = setState(stateFromXML);
1189 if (!setNewStateSuccess)
1192 PresetManagerUI::alertStateValidation();
1197 m_shouldInit =
false;
1202 void KwidgetAudioProcessor::setLastPresetPath(String lastLoadedPresetPath)
1204 m_lastLoadedPresetPath = lastLoadedPresetPath;
1207 String& KwidgetAudioProcessor::getLastPresetPath() {
return m_lastLoadedPresetPath; }
1209 const String KwidgetAudioProcessor::getName()
const {
return JucePlugin_Name; }
1210 bool KwidgetAudioProcessor::acceptsMidi()
const {
return true; }
1211 bool KwidgetAudioProcessor::producesMidi()
const {
return true; }
1212 bool KwidgetAudioProcessor::isMidiEffect()
const {
return false; }
1213 double KwidgetAudioProcessor::getTailLengthSeconds()
const {
return 0.0; }
1214 int KwidgetAudioProcessor::getNumPrograms() {
return 1; }
1215 int KwidgetAudioProcessor::getCurrentProgram() {
return 0; }
1216 void KwidgetAudioProcessor::setCurrentProgram(
int) {}
1217 const String KwidgetAudioProcessor::getProgramName(
int) {
return {}; }
1218 void KwidgetAudioProcessor::changeProgramName(
int,
const String&) {}
1219 bool KwidgetAudioProcessor::isBusesLayoutSupported(
const BusesLayout&)
const {
return true; }
1221 Kwidget* KwidgetAudioProcessor::addKwidgetFromState(
const ValueTree& kwidgetToAdd)
1224 m_addedFromState =
true;
1232 auto kwidgetTree = kwidgetToAdd.createCopy();
1236 auto loadResponse = m_presetEventMiddleware.processKwidgetLoad(loadRequest);
1237 if (loadResponse.success)
1243 DBG(
"Event middleware failed to execute: \n\t" << loadResponse.message);
1247 String kwidgetType = kwidgetTree[XmlType::Property::type].toString();
1250 auto kwidgetID = kwidgetTree[XmlType::Property::id].toString();
1251 auto newKwidget = KwidgetFactory::createKwidget(kwidgetType, kwidgetID);
1254 auto newKwidgetPtr = newKwidget.get();
1258 coreEngineKwidget->canReadSpecificFiles(m_readSpecificFiles);
1260 else if (
auto reformerKwidget =
dynamic_cast<Kwidget_Reformer*
>(newKwidgetPtr))
1262 reformerKwidget->canReadSpecificFiles(m_readSpecificFiles);
1266 newKwidget->setState(kwidgetTree, *
this);
1272 coreEngineKwidget->addListener(
this);
1279 reformerKwidget->addListener(
this);
1282 parameterManager.addKwidget(newKwidgetPtr,
false, newKwidget->isAChildKwidget());
1285 addKwidgetInternal(std::move(newKwidget));
1287 newKwidgetPtr = m_kwidgets.getLast();
1289 makeStaticConnectionsForKwidget(newKwidgetPtr);
1291 newKwidgetPtr->createNestedKwidgets(*
this);
1293 return newKwidgetPtr;
1296 void KwidgetAudioProcessor::addKwidgetInternal(std::unique_ptr<Kwidget> kwidget)
1298 auto kwidgetPtr = kwidget.get();
1301 if (kwidget->getKwidgetType().contains(KType::XyPad))
1304 xyPadKwidget->
getParameter(Kwidget_XyPad::Parameters::onClick)->addListener(
this);
1305 xyPadKwidget->
getParameter(Kwidget_XyPad::Parameters::toggleOn)->addListener(
this);
1308 else if (kwidget->getKwidgetType().contains(KType::TriggerButton))
1314 if (kwidget->isModulator())
1315 m_modulatorGraph.addKwidget(std::move(kwidget));
1317 m_mainGraph.addKwidget(std::move(kwidget));
1319 m_kwidgets.add(kwidgetPtr);
1320 m_kwidgetLookup[kwidgetPtr->getKwidgetID()] = kwidgetPtr;
1326 updateHostDisplay();
1329 void KwidgetAudioProcessor::initialiseStateListeners()
1332 const auto& connectionTree = parameterManager.getState().getChildWithName(XmlType::Tag::connections);
1336 m_connectionAttachment->onChildAdded = [
this](ValueTree& , ValueTree& child) {
1339 auto src = getKwidget(child[XmlType::Property::source].toString());
1340 auto dest = getKwidget(child[XmlType::Property::destination].toString());
1342 jassert(src != NULL);
1343 jassert(dest != NULL);
1345 if (MessageManager::getInstance()->isThisTheMessageThread())
1354 m_mainGraph.addConnection(src, dest, 0, m_channelsPerStereoBus);
1358 MessageManager::callAsync(
1359 [
this, src, dest]() { m_mainGraph.addConnection(src, dest, 0, m_channelsPerStereoBus); });
1363 m_connectionAttachment->onChildRemoved = [
this](ValueTree& , ValueTree& child) {
1364 auto src = getKwidget(child[XmlType::Property::source].toString());
1365 auto dest = getKwidget(child[XmlType::Property::destination].toString());
1366 m_mainGraph.removeConnection(src, dest);
1370 const auto& modulationTree = parameterManager.getState().getChildWithName(XmlType::Tag::modulations);
1373 m_modulationAttachment->onChildAdded = [
this](ValueTree& , ValueTree& child) {
1374 auto src = getKwidget(child[XmlType::Property::source].toString());
1375 auto dest = getKwidget(child[XmlType::Property::destination].toString());
1376 auto paramID = child[XmlType::Property::param].toString();
1377 auto idx = int(child[XmlType::Property::modulatorIndex]);
1378 auto depth = child[XmlType::Property::depth];
1379 auto polarity = int(child[XmlType::Property::polarity]);
1383 auto depthParam =
new CustomParameter(child, XmlType::Property::depth, parameterManager.getUndoManager());
1384 auto polarityParam =
1385 new CustomParameter(child, XmlType::Property::polarity, parameterManager.getUndoManager());
1387 depthParam->valueChanged = [=](
const var& newDepth) {
1388 dest->setModulatorDepth(paramID, src, idx, newDepth);
1391 polarityParam->valueChanged = [=](
const var& newPolarity) {
1392 dest->setModulatorPolarity(paramID, src, idx,
static_cast<KAttachment::Polarity>((
int)newPolarity));
1395 m_modulationInstances.add(depthParam);
1396 m_modulationInstances.add(polarityParam);
1399 m_modulationAttachment->onChildRemoved = [
this](ValueTree& , ValueTree& child) {
1400 auto src = getKwidget(child[XmlType::Property::source].toString());
1401 auto dest = getKwidget(child[XmlType::Property::destination].toString());
1402 auto paramID = child[XmlType::Property::param].toString();
1403 auto idx = int(child[XmlType::Property::modulatorIndex]);
1405 for (
auto inst : m_modulationInstances)
1407 if (inst->getParameterTree() == child)
1409 m_modulationInstances.removeObject(inst);
1414 dest->removeModulator(paramID, src, idx);
1418 bool KwidgetAudioProcessor::isRecording()
1420 m_isRecording =
false;
1422 for (
int i = 0; i < m_numRecorders; i++)
1424 if (m_recorderPtrs[i]->getActive() ==
true)
1426 m_isRecording =
true;
1430 return m_isRecording;
1436 if (newValue > ParameterManager::OnOffThreshold)
1439 m_synthPoly.noteOn(1, MIDI_NOTE_NUMBER_C3 +
static_cast<int>(midiModeValue) - 1, 1.0f);
1440 triggerRecordingStart();
1445 m_synthPoly.noteOff(1, MIDI_NOTE_NUMBER_C3 +
static_cast<int>(midiModeValue) - 1, 1.0f,
true);
1448 if (m_masterAudioOut->getParameter(Kwidget_AudioOut::Parameters::Autoplay)->get() <=
1449 ParameterManager::OnOffThreshold)
1451 triggerRecordingStop();
1456 void KwidgetAudioProcessor::setReadSpecificFiles(
bool canRead)
1458 for (
auto* kwidget : getKwidgets())
1460 if (kwidget->getKwidgetType() == KType::CoreEngine)
1465 else if (kwidget->getKwidgetType() == KType::Reformer)
1472 m_readSpecificFiles = canRead;
1475 void KwidgetAudioProcessor::setRecordersNameData(String newPresetName)
1477 for (
auto& recorder : m_recorderPtrs)
1481 recorder->setPresetName(newPresetName);
static File getPluginDirectory()
Definition AssetManager.cpp:392
A wrapper around juce::ValueTree designed to store custom plugin state (strings, arrays,...
Definition CustomParameter.h:9
Polarity
Definition KAttachment.h:120
An exception for preset manager.
Definition PresetManager.h:148
char const * what() const noexcept override
Definition PresetManager.cpp:339
Definition ValueTreeAttachment.h:4
Definition AirAbsorptionFilter.cpp:2
MIDIMode
Definition SampleEngine.h:54
A middleware request object for a preset load event.
Definition PresetEventMiddleware.h:7
File presetFile
Definition PresetEventMiddleware.h:12
ValueTree newState
The new preset state value tree.
Definition PresetEventMiddleware.h:11
static const Identifier LastLoadedPresetName
Definition XmlType.h:51
static const Identifier LastLoadedPreset
Definition XmlType.h:29