From e9a5784ed16af1e5ed2f400df41329c3c45f484b Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sun, 10 May 2026 16:10:51 +0200 Subject: [PATCH] refactored pacth import/export --- src/plug/JaySynthMidiCC.cpp | 221 ++++++++++++++++++++--------------- src/plug/JaySynthMidiCC.h | 8 +- src/plug/PluginProcessor.cpp | 63 +++++----- 3 files changed, 166 insertions(+), 126 deletions(-) diff --git a/src/plug/JaySynthMidiCC.cpp b/src/plug/JaySynthMidiCC.cpp index bd74f82..15914c9 100644 --- a/src/plug/JaySynthMidiCC.cpp +++ b/src/plug/JaySynthMidiCC.cpp @@ -184,25 +184,13 @@ int JaySynthMidiCC::findParamID_byName(String name) return (int)paramNamedValueSet.getWithDefault (toParameterNameXML(name), var(-1)); } -void JaySynthMidiCC::exportXML(String name) -{ - File file(name); - XmlElement xml ("JSYNTH_MIDICC_TABLE_FILE"); - - exportXML(&xml); - - file.create(); - xml.writeToFile (/*const File &destinationFile*/file, /*const String &dtdToUse*/"JSYNTH_MIDICC_TABLE_FILE" /*, const String &encodingType="UTF-8", int lineWrapLength=60*/); -} - -void JaySynthMidiCC::exportXML(XmlElement *pXML_root) const +void JaySynthMidiCC::export_midi_cc(XmlElement *pXML) const { int paramID; midiCC_container_t const *pMidiContainer; - XmlElement *pXML, *pXML_PARAM, *pXML_PARAM_INFO; + XmlElement *pXML_PARAM, *pXML_PARAM_INFO; // Store controller and slider infos - pXML = pXML_root->createNewChildElement (String("TARGETS")); for (paramID=0; paramID < SYNTH_NUM_PARAMS; paramID++) { pMidiContainer = &midiCC_containers[paramID]; @@ -212,29 +200,34 @@ void JaySynthMidiCC::exportXML(XmlElement *pXML_root) const pXML_PARAM->setAttribute ("IS_ABSOLUTE", pMidiContainer->doChangeParameter); pXML_PARAM->setAttribute ("DO_APPLY_ON_PATCH_INIT", pMidiContainer->doApplyOnPatchInit); pXML_PARAM->setAttribute ("CONTROLLER_ID", pMidiContainer->controllerID); + } +} +void JaySynthMidiCC::export_midi_velkey(XmlElement *pXML) const +{ + int paramID; + midiCC_container_t const *pMidiContainer; + XmlElement *pXML_PARAM, *pXML_PARAM_INFO; + + // Store controller and slider infos + for (paramID=0; paramID < SYNTH_NUM_PARAMS; paramID++) + { + pMidiContainer = &midiCC_containers[paramID]; + pXML_PARAM = pXML->createNewChildElement (String("PARAM_") + String(paramID)); + pXML_PARAM->setAttribute ("NAME", toParameterNameXML(pMidiContainer->constraints.pName)); pXML_PARAM->setAttribute ("IS_VELOCITY_ASSIGNED", pMidiContainer->isVelAssigned); pXML_PARAM->setAttribute ("IS_KEYFOLLOW_ASSIGNED", pMidiContainer->isKeyAssigned); pXML_PARAM->setAttribute ("VELKEY_COMBINE_OP", pMidiContainer->velKeyCombineOP); pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("RELATIVE")); -// pXML_PARAM_INFO->setAttribute ("BASE", String(pMidiContainer->control.base, 10)); -// pXML_PARAM_INFO->setAttribute ("KEXP", String(pMidiContainer->control.kexp, 10)); -// pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->control.scenter, 10)); pXML_PARAM_INFO->setAttribute ("PMIN", String(pMidiContainer->control.pmin, 10)); pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->control.pmax, 10)); -// pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->control.pinterval, 10)); pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("ABSOLUTE")); -// pXML_PARAM_INFO->setAttribute ("BASE", String(pMidiContainer->param.base, 10)); -// pXML_PARAM_INFO->setAttribute ("KEXP", String(pMidiContainer->param.kexp, 10)); -// pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->param.scenter, 10)); pXML_PARAM_INFO->setAttribute ("PMIN", String(pMidiContainer->param.pmin, 10)); pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->param.pmax, 10)); -// pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->param.pinterval, 10)); pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("VELOCITY_CURVE")); -// pXML_PARAM_INFO->setAttribute ("BASE", String(pMidiContainer->curve_vel.base, 10)); pXML_PARAM_INFO->setAttribute ("KEXP", String(pMidiContainer->curve_vel.kexp, 10)); pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->curve_vel.scenter, 10)); pXML_PARAM_INFO->setAttribute ("PMIN", String(pMidiContainer->curve_vel.pmin, 10)); @@ -242,41 +235,124 @@ void JaySynthMidiCC::exportXML(XmlElement *pXML_root) const pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->curve_vel.pinterval, 10)); pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("KEYFOLLOW_CURVE")); -// pXML_PARAM_INFO->setAttribute ("BASE", String(pMidiContainer->curve_key.base, 10)); pXML_PARAM_INFO->setAttribute ("KEXP", String(pMidiContainer->curve_key.kexp, 10)); pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->curve_key.scenter, 10)); pXML_PARAM_INFO->setAttribute ("PMIN", String(pMidiContainer->curve_key.pmin, 10)); pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->curve_key.pmax, 10)); pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->curve_key.pinterval, 10)); } - -/* - { - int i, controllerID, numDst; - XmlElement *pXML_dst, *pXML_MIDICC; - - // todo: romove that in future versions - pXML = pXML_root->createNewChildElement (String("CONTROLLERS")); - // Store MIDI controller assignments - for (controllerID=0; controllerID < NUM_MIDI_CONTROLLERS; controllerID++) - { - pXML_MIDICC = pXML->createNewChildElement (String("MIDICC_") + String(controllerID)); - pXML_MIDICC->setAttribute ("ID", controllerID); - - pXML_dst = pXML_MIDICC->createNewChildElement (String("TARGETS")); - numDst = getNumDestinations(controllerID); - for (i=0; i < numDst; i++) - { - pMidiContainer = getDestination(controllerID, i); - pXML_dst->setAttribute (String("PARAM") + String(pMidiContainer->constraints.id), pMidiContainer->constraints.pName); - } - } - } - // todo: romove that in future versions -*/ } -int JaySynthMidiCC::importXML(XmlElement const *pXML_MidiCc) +int JaySynthMidiCC::import_midi_velkey(XmlElement const *pXML) +{ + int i, paramID; + midiCC_container_t *pMidiContainer; + XmlElement *pXML_PARAM, *pXML_PARAM_INFO; + + for (i=0; i < NUM_MIDI_CONTROLLERS; i++) + removeDestinations(i); + + // make sure that it's actually our type of XML object.. + if (pXML) + { + pXML_PARAM = pXML->getFirstChildElement(); + while(pXML_PARAM) + { + paramID = findParamID_byName(pXML_PARAM->getStringAttribute("NAME")); + if (paramID < 0) + { + pXML_PARAM = pXML_PARAM->getNextElement(); + continue; + } + + pMidiContainer = &midiCC_containers[paramID]; + pMidiContainer->isVelAssigned = pXML_PARAM->getIntAttribute("IS_VELOCITY_ASSIGNED", 0) != 0; + pMidiContainer->isKeyAssigned = pXML_PARAM->getIntAttribute("IS_KEYFOLLOW_ASSIGNED", 0) != 0; + pMidiContainer->velKeyCombineOP = pXML_PARAM->getIntAttribute("VELKEY_COMBINE_OP", VELKEY_OP_ADD); + + pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("RELATIVE")); + if (pXML_PARAM_INFO) + { + pMidiContainer->control.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", pMidiContainer->constraints.pmin); + pMidiContainer->control.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", pMidiContainer->constraints.pmax); + } + + pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("ABSOLUTE")); + if (pXML_PARAM_INFO) + { + pMidiContainer->param.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", pMidiContainer->constraints.pmin); + pMidiContainer->param.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", pMidiContainer->constraints.pmax); + } + + pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("VELOCITY_CURVE")); + if (pXML_PARAM_INFO) + { + pMidiContainer->curve_vel.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", 0); + pMidiContainer->curve_vel.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", 0.5); + pMidiContainer->curve_vel.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", 0); + pMidiContainer->curve_vel.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", 1); + } + + pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("KEYFOLLOW_CURVE")); + if (pXML_PARAM_INFO) + { + pMidiContainer->curve_key.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", 0); + pMidiContainer->curve_key.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", 0.5); + pMidiContainer->curve_key.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", 0); + pMidiContainer->curve_key.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", 1); + } + + if (pXML_PARAM->getIntAttribute("IS_ASSIGNED", 0)) + add(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0)); + else + remove(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0)); + + pXML_PARAM = pXML_PARAM->getNextElement(); + } + } + isModified = false; + return 0; +} + +int JaySynthMidiCC::import_midi_cc(XmlElement const *pXML) +{ + int i, paramID; + midiCC_container_t *pMidiContainer; + XmlElement *pXML_PARAM, *pXML_PARAM_INFO; + + for (i=0; i < NUM_MIDI_CONTROLLERS; i++) + removeDestinations(i); + + // make sure that it's actually our type of XML object.. + if (pXML) + { + pXML_PARAM = pXML->getFirstChildElement(); + while(pXML_PARAM) + { + paramID = findParamID_byName(pXML_PARAM->getStringAttribute("NAME")); + if (paramID < 0) + { + pXML_PARAM = pXML_PARAM->getNextElement(); + continue; + } + + pMidiContainer = &midiCC_containers[paramID]; + pMidiContainer->doChangeParameter = pXML_PARAM->getIntAttribute("IS_ABSOLUTE", pXML_PARAM->getIntAttribute("DO_CHANGE_PARAMETER", 0)) != 0; + pMidiContainer->doApplyOnPatchInit = pXML_PARAM->getIntAttribute("DO_APPLY_ON_PATCH_INIT", 0) != 0; + + if (pXML_PARAM->getIntAttribute("IS_ASSIGNED", 0)) + add(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0)); + else + remove(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0)); + + pXML_PARAM = pXML_PARAM->getNextElement(); + } + } + isModified = false; + return 0; +} + +int JaySynthMidiCC::import_midi_cc_legacy(XmlElement const *pXML_MidiCc) { int i, paramID; midiCC_container_t *pMidiContainer; @@ -289,7 +365,7 @@ int JaySynthMidiCC::importXML(XmlElement const *pXML_MidiCc) if (pXML_MidiCc) { pXML = pXML_MidiCc->getFirstChildElement(); - while(pXML) + if(pXML) { pXML_PARAM = pXML->getFirstChildElement(); while(pXML_PARAM) @@ -312,45 +388,33 @@ int JaySynthMidiCC::importXML(XmlElement const *pXML_MidiCc) pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("RELATIVE")); if (pXML_PARAM_INFO) { -// pMidiContainer->control.base = pXML_PARAM_INFO->getDoubleAttribute("BASE", pMidiContainer->constraints.base); -// pMidiContainer->control.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", pMidiContainer->constraints.kexp); -// pMidiContainer->control.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", pMidiContainer->constraints.scenter); pMidiContainer->control.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", pMidiContainer->constraints.pmin); pMidiContainer->control.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", pMidiContainer->constraints.pmax); -// pMidiContainer->control.pinterval = pXML_PARAM_INFO->getDoubleAttribute("PINTERVAL", pMidiContainer->constraints.pinterval); } pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("ABSOLUTE")); if (pXML_PARAM_INFO) { -// pMidiContainer->param.base = pXML_PARAM_INFO->getDoubleAttribute("BASE", pMidiContainer->constraints.base); -// pMidiContainer->param.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", pMidiContainer->constraints.kexp); -// pMidiContainer->param.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", pMidiContainer->constraints.scenter); pMidiContainer->param.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", pMidiContainer->constraints.pmin); pMidiContainer->param.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", pMidiContainer->constraints.pmax); -// pMidiContainer->param.pinterval = pXML_PARAM_INFO->getDoubleAttribute("PINTERVAL", pMidiContainer->constraints.pinterval); } pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("VELOCITY_CURVE")); if (pXML_PARAM_INFO) { -// pMidiContainer->curve_vel.base = pXML_PARAM_INFO->getDoubleAttribute("BASE", exp(1.0)); pMidiContainer->curve_vel.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", 0); pMidiContainer->curve_vel.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", 0.5); pMidiContainer->curve_vel.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", 0); pMidiContainer->curve_vel.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", 1); -// pMidiContainer->curve_vel.pinterval = pXML_PARAM_INFO->getDoubleAttribute("PINTERVAL", 0); } pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("KEYFOLLOW_CURVE")); if (pXML_PARAM_INFO) { -// pMidiContainer->curve_key.base = pXML_PARAM_INFO->getDoubleAttribute("BASE", exp(1.0)); pMidiContainer->curve_key.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", 0); pMidiContainer->curve_key.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", 0.5); pMidiContainer->curve_key.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", 0); pMidiContainer->curve_key.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", 1); -// pMidiContainer->curve_key.pinterval = pXML_PARAM_INFO->getDoubleAttribute("PINTERVAL", 0); } if (pXML_PARAM->getIntAttribute("IS_ASSIGNED", 0)) @@ -360,37 +424,6 @@ int JaySynthMidiCC::importXML(XmlElement const *pXML_MidiCc) pXML_PARAM = pXML_PARAM->getNextElement(); } - - // todo: romove that in future versions - { - int controllerID; - XmlElement *pXML_MIDICC, *pXML_DST; - - pXML = pXML->getNextElement(); - while(pXML) - { - pXML_MIDICC = pXML->getFirstChildElement(); - while(pXML_MIDICC) - { - controllerID = pXML_MIDICC->getIntAttribute("ID"); - pXML_DST = pXML_MIDICC->getFirstChildElement(); - if (pXML_DST) - { - for (i=0; i < pXML_DST->getNumAttributes(); i++) - { - paramID = findParamID_byName(pXML_DST->getAttributeValue(i)); - if (paramID < 0) - break; - pMidiContainer = &midiCC_containers[paramID]; - add(pMidiContainer, controllerID); - } - } - pXML_MIDICC = pXML_MIDICC->getNextElement(); - } - pXML = pXML->getNextElement(); - } - } - // todo: romove that in future versions } } isModified = false; diff --git a/src/plug/JaySynthMidiCC.h b/src/plug/JaySynthMidiCC.h index 530ea3d..0b54ee1 100644 --- a/src/plug/JaySynthMidiCC.h +++ b/src/plug/JaySynthMidiCC.h @@ -55,9 +55,11 @@ public: bool isMidiCCmodified(void) const; String toParameterNameXML (String const &name) const; int findParamID_byName(String name); - void exportXML(String name); - void exportXML(XmlElement *pXML_doc) const; - int importXML(XmlElement const *pXML_doc); + void export_midi_cc(XmlElement *pXML_doc) const; + int import_midi_cc(XmlElement const *pXML_doc); + void export_midi_velkey(XmlElement *pXML_doc) const; + int import_midi_velkey(XmlElement const *pXML_doc); + int import_midi_cc_legacy(XmlElement const *pXML_doc); void add(midiCC_container_t *pObj, int controllerID); void remove(midiCC_container_t *pObj, int controllerID); struct midiCC_container_t* getAtParamID(int paramID); diff --git a/src/plug/PluginProcessor.cpp b/src/plug/PluginProcessor.cpp index 6470a15..d8b8eb6 100644 --- a/src/plug/PluginProcessor.cpp +++ b/src/plug/PluginProcessor.cpp @@ -741,8 +741,9 @@ void JaySynthAudioProcessor::patchEncodeXml(XmlElement *xml, JaySynthSound const synth_float_t value = patch->getParameter(i); xml_patch->setAttribute (getParameterNameXML(i), String(value, 10)); } - XmlElement *xml_midiCC = xml->createNewChildElement("MidiCC"); - patch->getMidiCC()->exportXML(xml_midiCC); + patch->getMidiCC()->export_midi_velkey(xml->createNewChildElement("VelKey")); + patch->getMidiCC()->export_midi_cc(xml->createNewChildElement("MidiCC")); + } void JaySynthAudioProcessor::patchDecodeXml(const XmlElement *xml, JaySynthSound *patch) @@ -761,12 +762,24 @@ void JaySynthAudioProcessor::patchDecodeXml(const XmlElement *xml, JaySynthSound } patch->setParameter(i, value); } - XmlElement *pXML_MidiCc = xml->getChildByName ("JSYNTH_MIDICONTROLLER_TABLE"); - if (pXML_MidiCc) - { - ((JaySynthMidiCC*)patch->getMidiCC())->importXML(pXML_MidiCc); - } +} +void JaySynthAudioProcessor::patchDecodeXml_legacy(const XmlElement& xml, JaySynthSound *patch) +{ + // ok, now pull out our parameters.. + patch->setName(xml.getStringAttribute("NAME")); + for (int i=0; i < SYNTH_NUM_PARAMS; i++) + { + synth_float_t value = (synth_float_t) xml.getDoubleAttribute (getParameterNameXML(i), patch->getParameter(i)); + if (i==SYNTH_PARAM_TUNE) + { + if (value > 400.0) + { + value = 1200*log(value/440)/log(2.0); + } + } + patch->setParameter(i, value); + } } void JaySynthAudioProcessor::bankEncodeXml(XmlElement *xml) @@ -951,15 +964,26 @@ void JaySynthAudioProcessor::patchImportXml (const XmlElement *xml, JaySynthSoun if (xml2->hasTagName ("Patch")) { patchDecodeXml(xml2, patch); + XmlElement *pXML_MidiCc = xml2->getChildByName ("JSYNTH_MIDICONTROLLER_TABLE"); + if (pXML_MidiCc) + { + ((JaySynthMidiCC*)patch->getMidiCC())->import_midi_cc_legacy(pXML_MidiCc); + } } else if (xml->hasTagName ("JSYNTH_PATCH")) { patchDecodeXml_legacy(*xml, patch); + XmlElement *pXML_MidiCc = xml->getChildByName ("JSYNTH_MIDICONTROLLER_TABLE"); + ((JaySynthMidiCC*)patch->getMidiCC())->import_midi_cc_legacy(pXML_MidiCc); + + } + else if (xml2->hasTagName ("VelKey")) + { + ((JaySynthMidiCC*)patch->getMidiCC())->import_midi_velkey(xml->getChildByName ("VelKey")); } else if (xml2->hasTagName ("MidiCC")) { - XmlElement *pXML_MidiCc = xml->getChildByName ("MidiCC"); - ((JaySynthMidiCC*)patch->getMidiCC())->importXML(pXML_MidiCc); + ((JaySynthMidiCC*)patch->getMidiCC())->import_midi_cc(xml->getChildByName ("MidiCC")); } xml2 = xml2->getNextElement(); }; @@ -1041,25 +1065,6 @@ void JaySynthAudioProcessor::saveBankToFile (const File &file) xml->writeToFile (/*const File &destinationFile*/file, /*dtdToUse*/""); } } -void JaySynthAudioProcessor::patchDecodeXml_legacy(const XmlElement& xml, JaySynthSound *patch) -{ - // ok, now pull out our parameters.. - patch->setName(xml.getStringAttribute("NAME")); - for (int i=0; i < SYNTH_NUM_PARAMS; i++) - { - synth_float_t value = (synth_float_t) xml.getDoubleAttribute (getParameterNameXML(i), patch->getParameter(i)); - if (i==SYNTH_PARAM_TUNE) - { - if (value > 400.0) - { - value = 1200*log(value/440)/log(2.0); - } - } - patch->setParameter(i, value); - } - XmlElement *pXML_MidiCc = xml.getChildByName ("JSYNTH_MIDICONTROLLER_TABLE"); - ((JaySynthMidiCC*)patch->getMidiCC())->importXML(pXML_MidiCc); -} void JaySynthAudioProcessor::bankDecodeXml_legacy(const XmlElement& xml) { @@ -1075,7 +1080,7 @@ void JaySynthAudioProcessor::bankDecodeXml_legacy(const XmlElement& xml) JaySynthSound *pPatch = &patches[progID]; patchDecodeXml_legacy(*pXML, pPatch); XmlElement *pXML_MidiCc = pXML->getChildByName ("JSYNTH_MIDICONTROLLER_TABLE"); - ((JaySynthMidiCC*)pPatch->getMidiCC())->importXML(pXML_MidiCc); + ((JaySynthMidiCC*)pPatch->getMidiCC())->import_midi_cc(pXML_MidiCc); pXML = pXML->getNextElement(); } }