AudioOutConnector* ObjController::addAudioConnection(ObjectsHolder* holder, BaseObjectComponent* objComp, ObjectComponent* audioOutComp, ValueTree source, int index, bool undoable) { if(undoable) { AddAudioConnectionAction* action = new AddAudioConnectionAction( this, objComp, source, audioOutComp, holder); owner.getUndoManager().perform(action, "Add new audio connection"); return audioConnections[action->indexAdded]; } else { AudioOutConnector* aoc = new AudioOutConnector(*this, objComp, audioOutComp); ValueTree sources = aoc->getAudioObject()->getData().getChildWithName(Ids::sources); if(! sources.getChildWithProperty(Ids::value, source[Ids::value]).isValid()) sources.addChild(source, -1, nullptr); audioConnections.insert(index, aoc); holder->addAndMakeVisible(aoc); aoc->update(); aoc->toBack(); return aoc; } return nullptr; }
ValueTree AudioProcessorValueTreeState::getOrCreateChildValueTree (const String& paramID) { ValueTree v (state.getChildWithProperty (idPropertyID, paramID)); if (! v.isValid()) { v = ValueTree (valueType); v.setProperty (idPropertyID, paramID, undoManager); state.addChild (v, -1, undoManager); } return v; }
Value ProjectExporter::getPathForModuleValue (const String& moduleID) { UndoManager* um = project.getUndoManagerFor (settings); ValueTree paths (settings.getOrCreateChildWithName (Ids::MODULEPATHS, um)); ValueTree m (paths.getChildWithProperty (Ids::ID, moduleID)); if (! m.isValid()) { m = ValueTree (Ids::MODULEPATH); m.setProperty (Ids::ID, moduleID, um); paths.addChild (m, -1, um); } return m.getPropertyAsValue (Ids::path, um); }
void ProjectExporter::removePathForModule (const String& moduleID) { ValueTree paths (settings.getChildWithName (Ids::MODULEPATHS)); ValueTree m (paths.getChildWithProperty (Ids::ID, moduleID)); paths.removeChild (m, project.getUndoManagerFor (settings)); }
const String SAMCompiler::compile(ValueTree mdlRoot_) { String dspContent; //========================================================================== // DSP file header //========================================================================== dspContent << "// This DSP file has been generated by the Synth-A-Modeler compiler.\n"; dspContent << "import(\"physicalmodeling.lib\");\n\n"; //========================================================================== ValueTree faustTree = mdlRoot_.getChildWithName(Objects::variables); ValueTree massTree = mdlRoot_.getChildWithName(Objects::masses); ValueTree linkTree = mdlRoot_.getChildWithName(Objects::links); ValueTree wgTree = mdlRoot_.getChildWithName(Objects::waveguides); ValueTree jTree = mdlRoot_.getChildWithName(Objects::junctions); ValueTree tTree = mdlRoot_.getChildWithName(Objects::terminations); ValueTree aoTree = mdlRoot_.getChildWithName(Objects::audioobjects); int numMasslike = 0; int numPorts = 0; int numWaveguides = 0; int numJunctions = 0; String wgTermString; String junctString; StringArray wgOutputs; StringArray wgInputs; StringArray massWithJunct; StringArray linkWithJunct; StringArray massWithJunctLine; StringArray portWithJunctLine; StringArray massWithJunctOutputs; StringArray junctInputs; StringArray junctOutputs; //========================================================================== //========================================================================== // Write all waveguides and terminations //========================================================================== OwnedArray<WgWithSuffixes> wgWithSuffixes; for (int i = 0; i < wgTree.getNumChildren(); ++i) { ++numWaveguides; ValueTree wg = wgTree.getChild(i); WgWithSuffixes* wws = new WgWithSuffixes(); wws->wgId = wg[Ids::identifier].toString(); ValueTree left = jTree.getChildWithProperty(Ids::identifier, wg[Ids::startVertex]); ValueTree right; if (left.isValid()) { right = tTree.getChildWithProperty(Ids::identifier, wg[Ids::endVertex]); } else { left = tTree.getChildWithProperty(Ids::identifier, wg[Ids::startVertex]); right = jTree.getChildWithProperty(Ids::identifier, wg[Ids::endVertex]); } ValueTree term; ValueTree junct; StringArray wgSuffixes; if (left.getType() == Ids::termination) { wgSuffixes.add(wgR); wgSuffixes.add(wgL); wgSuffixes.add(wgRp); wgSuffixes.add(wgLp); term = left; junct = right; wws->termRight = false; } else if (left.getType() == Ids::junction) { wgSuffixes.add(wgL); wgSuffixes.add(wgR); wgSuffixes.add(wgLp); wgSuffixes.add(wgRp); term = right; junct = left; wws->termRight = true; } wws->wgSuffixes = wgSuffixes; wgInputs.add(wg[Ids::identifier].toString() + wgLp); wgInputs.add(wg[Ids::identifier].toString() + wgRp); wgOutputs.add(wg[Ids::identifier].toString() + wgL); wgOutputs.add(wg[Ids::identifier].toString() + wgR); ValueTree paWg = wg.getChildWithName(Ids::parameters); StringArray paWgStrings; for (int j = 0; j < paWg.getNumChildren(); ++j) { paWgStrings.add(paWg.getChild(j)[Ids::value].toString()); } wws->wgParams = paWgStrings; wgWithSuffixes.add(wws); ValueTree paTerm = term.getChildWithName(Ids::parameters); StringArray paTermStrings; for (int j = 0; j < paTerm.getNumChildren(); ++j) { paTermStrings.add(paTerm.getChild(j)[Ids::value].toString()); } //====================================================================== wgTermString << "\t"; wgTermString << wg[Ids::identifier].toString(); wgTermString << wgSuffixes[0] << " = " << term[Ids::identifier].toString(); wgTermString << " : "; wgTermString << paWgStrings[1]; wgTermString << ";\n\t"; wgTermString << term[Ids::identifier].toString(); wgTermString << " = "; wgTermString << wg[Ids::identifier].toString() << wgSuffixes[3]; wgTermString << " : "; wgTermString << paTermStrings[0] << ";\n\n"; //====================================================================== } //========================================================================== // Write all junctions //========================================================================== for (int i = 0; i < jTree.getNumChildren(); ++i) { ++numJunctions; ValueTree junct = jTree.getChild(i); junctOutputs.add(junct[Ids::identifier].toString()); junctInputs.add(junct[Ids::identifier].toString()+"p"); ValueTree wgs = getWgForJunct(wgTree, junct); StringArray junctWgOuts; StringArray junctWgParams; junctString << "\t"; for (int k = 0; k < wgs.getNumChildren(); ++k) { ValueTree wg = wgs.getChild(k); int wgSuffixesIdx = containsWgRef(wgWithSuffixes, wg[Ids::identifier].toString()); if (wgSuffixesIdx == -1) continue; const StringArray& wgSuffixes = wgWithSuffixes[wgSuffixesIdx]->wgSuffixes; junctString << wg[Ids::identifier].toString() << wgSuffixes[1]; junctString << " = "; junctString << junct[Ids::identifier].toString() << jTO; junctString << wg[Ids::identifier].toString(); junctString << " : "; junctString << wgWithSuffixes[wgSuffixesIdx]->wgParams[1]; junctString << ";\n\t"; junctString << junct[Ids::identifier].toString() << jTO; junctString << wg[Ids::identifier].toString() << " = "; junctString << junct[Ids::identifier].toString() << jOutputs; junctString << ":(_,!)-"; junctString << wg[Ids::identifier].toString() << wgSuffixes[2]; junctString << ";\n\t"; String jwo; jwo << wg[Ids::identifier].toString() << wgSuffixes[2]; jwo << "*" << wgWithSuffixes[wgSuffixesIdx]->wgParams[0]; junctWgOuts.add(jwo); junctWgParams.add(wgWithSuffixes[wgSuffixesIdx]->wgParams[0]); } String junctLinkString; String junctMassString; // Check if junction has one link and mass connected ValueTree junctLink = getJunctionLink(linkTree, junct); if (junctLink.isValid()) { String jm; if (junctLink[Ids::startVertex] == junct[Ids::identifier]) jm << junctLink[Ids::endVertex].toString(); else jm << junctLink[Ids::startVertex].toString(); junctMassString << jm << "p"; massWithJunct.add(jm); massWithJunctOutputs.add(jm + "p"); linkWithJunct.add(junctLink[Ids::identifier].toString()); ValueTree junctLinkParams = junctLink.getChildWithName(Ids::parameters); StringArray junctLinkParamsStrings; for (int k = 0; k < junctLinkParams.getNumChildren(); ++k) { ValueTree param = junctLinkParams.getChild(k); junctLinkParamsStrings.add(param[Ids::value].toString()); } junctLinkString << "junction" << junctLink.getType().toString(); junctLinkString << "Underneath(0.0,"; junctLinkString << junctLinkParamsStrings.joinIntoString(","); junctLinkString << ")"; // Get mass-like object connected with junction > link ValueTree mwj = massTree.getChildWithProperty(Ids::identifier, jm); String mwjl = "\t"; mwjl << jm; mwjl << " = (0.0"; StringArray otherLinks; for (int k = 0; k < linkTree.getNumChildren(); ++k) { ValueTree li = linkTree.getChild(k); if(li[Ids::identifier].toString() == junctLink[Ids::identifier].toString()) continue; if(li[Ids::startVertex].toString() == jm) { otherLinks.add("-"+li[Ids::identifier].toString()); } else if (li[Ids::endVertex].toString() == jm) { otherLinks.add("+"+li[Ids::identifier].toString()); } } mwjl << otherLinks.joinIntoString(String::empty); mwjl << "+("; mwjl << junct[Ids::identifier].toString() << jOutputs << ":(!,_)))"; // mwjl << " : "; // ValueTree mwjp = mwj.getChildWithName(Ids::parameters); // StringArray mwjpStrings; // for (int p = 0; p < mwjp.getNumChildren(); ++p) // { // ValueTree param = mwjp.getChild(p); // mwjpStrings.add(param[Ids::value].toString()); // } // mwjl << mwj.getType().toString(); // mwjl << "(" << mwjpStrings.joinIntoString(",") << ")"; mwjl << ";"; massWithJunctLine.add(mwjl); } else { junctMassString << "0.0"; junctLinkString << "junctionlink(0.0, 0.0, 0.0, 0.0)"; } junctString << junct[Ids::identifier].toString() << jOutputs; junctString << " = ("; junctString << junctMassString << ", 0.0+"; junctString << junctWgOuts.joinIntoString("+"); junctString << ", 0.0+"; junctString << junctWgParams.joinIntoString("+"); junctString << ") : "; junctString << junctLinkString << ";\n\t"; junctString << junct[Ids::identifier].toString(); junctString << " = "; junctString << junct[Ids::identifier].toString() << jOutputs; junctString << ":(_,!);\n\n"; } //========================================================================== // Write all faustcode //========================================================================== for (int i = 0; i < faustTree.getNumChildren(); ++i) { ValueTree fa = faustTree.getChild(i); dspContent << fa[Ids::identifier].toString(); dspContent << "="; dspContent << fa[Ids::faustCode].toString(); dspContent << ";\n"; } dspContent << "\n"; //========================================================================== // Get all mass names //========================================================================== OwnedArray<MassLinkRef> massLinkRefs; for (int i = 0; i < massTree.getNumChildren(); ++i) { ValueTree ma = massTree.getChild(i); if (massWithJunct.contains(ma[Ids::identifier].toString())) continue; MassLinkRef* mlf = new MassLinkRef(); mlf->massId = ma[Ids::identifier].toString(); StringArray mlfa; mlf->linkRefs = mlfa; if (ma.getType() == Ids::port) mlf->isPort = true; else mlf->isPort = false; massLinkRefs.add(mlf); } //========================================================================== // Write all link-like objects //========================================================================== StringArray linkobjects; for (int i = 0; i < linkTree.getNumChildren(); ++i) { ValueTree li = linkTree.getChild(i); String linkId = li[Ids::identifier].toString(); if (linkWithJunct.contains(linkId)) continue; String startVertex = li[Ids::startVertex].toString(); String endVertex = li[Ids::endVertex].toString(); int sIdx = containsMassLinkRef(massLinkRefs, startVertex); if (sIdx >= 0) massLinkRefs[sIdx]->linkRefs.add("-" + linkId); int eIdx = containsMassLinkRef(massLinkRefs, endVertex); if (eIdx >= 0) massLinkRefs[eIdx]->linkRefs.add("+" + linkId); String tagName = li.getType().toString(); ValueTree params = li.getChildWithName(Ids::parameters); StringArray paramsStr; for (int k = 0; k < params.getNumChildren(); ++k) { ValueTree param = params.getChild(k); paramsStr.add(param[Ids::value].toString()); } //====================================================================== String linkLine; linkLine << "\t"; linkLine << linkId; linkLine << " = ("; linkLine << startVertex << "p - "; linkLine << endVertex << "p) : "; linkLine << tagName << "("; linkLine << paramsStr.joinIntoString(",") << ");"; linkobjects.add(linkLine); //====================================================================== } StringArray massobjects; //========================================================================== // write all mass-like object except those connected to junctions //========================================================================== for (int i = 0; i < massTree.getNumChildren(); ++i) { ValueTree ma = massTree.getChild(i); if (massWithJunct.contains(ma[Ids::identifier].toString())) { if(ma.getType().toString().compare("port") == 0) ++numPorts; continue; } ++numMasslike; String tagName = ma.getType().toString(); String massName = ma[Ids::identifier].toString(); String massLine; massLine << "\t"; massLine << massName << " = (0.0"; if (tagName.compare("port") == 0) ++numPorts; int mIdx = containsMassLinkRef(massLinkRefs, massName); if (mIdx >= 0) { if (massLinkRefs[mIdx]->linkRefs.size() > 0) { massLine << massLinkRefs[mIdx]->linkRefs.joinIntoString(String::empty); } } massLine << ")"; if (tagName.compare("port") != 0) { massLine << " : "; massLine << tagName << "("; ValueTree params = ma.getChildWithName(Ids::parameters); StringArray paramsStr; for (int k = 0; k < params.getNumChildren(); ++k) { ValueTree param = params.getChild(k); paramsStr.add(param[Ids::value].toString()); } massLine << paramsStr.joinIntoString(",") << ")"; } massLine << ";"; massobjects.add(massLine); } //========================================================================== // add remaining mass-like object which are connected to junctions //========================================================================== massobjects.addArray(massWithJunctLine); //========================================================================== // Write all audio objects //========================================================================== StringArray audioobjects; StringArray audioNames; for (int i = 0; i < aoTree.getNumChildren(); ++i) { ValueTree ao = aoTree.getChild(i); String audioLine; String audioName = ao[Ids::identifier].toString(); audioNames.add(audioName); audioLine << "\t"; audioLine << audioName << " = "; ValueTree sources = ao.getChildWithName(Ids::sources); String paramLine; StringArray paramsStr; if (sources.getNumChildren() > 0) { for (int k = 0; k < sources.getNumChildren(); ++k) { ValueTree src = sources.getChild(k); paramsStr.add(src[Ids::value].toString()); } paramLine << paramsStr.joinIntoString("+"); } String optional = ao[Ids::optional].toString(); if (optional != String::empty) { if(! paramLine.startsWith("(")) paramLine = "(" + paramLine; if(! paramLine.endsWith(")")) paramLine << ")"; paramLine << optional; } audioLine << paramLine; audioLine << ";"; audioobjects.add(audioLine); } //========================================================================== // Generate all inputs and outputs //========================================================================== StringArray inputs; StringArray inputsPorts; for (int i = 0; i < massLinkRefs.size(); ++i) { if (massLinkRefs[i]->isPort) inputsPorts.add(massLinkRefs[i]->massId); else inputs.add(massLinkRefs[i]->massId); } StringArray outputs = inputs; outputs.addArray(massWithJunct); StringArray outputsPorts = inputsPorts; StringArray inputsP; StringArray inputsPPorts; for (int i = 0; i < inputs.size(); ++i) { String inputP = inputs[i]; inputP << "p"; inputsP.add(inputP); } for (int i = 0; i < massWithJunctOutputs.size(); ++i) { ++numMasslike; String inputP = massWithJunctOutputs[i]; inputsP.add(inputP); } for (int i = 0; i < inputsPorts.size(); ++i) { String inputPPort = inputsPorts[i]; inputPPort << "p"; inputsPPorts.add(inputPPort); } //========================================================================== // bibBlock with all imputs and outputs //========================================================================== dspContent << "bigBlock(" << inputsP.joinIntoString(","); if (wgInputs.size() > 0) dspContent << "," << wgInputs.joinIntoString(","); if (junctInputs.size() > 0) dspContent << "," << junctInputs.joinIntoString(","); if (inputsPPorts.size() > 0) dspContent << "," << inputsPPorts.joinIntoString(","); dspContent << ") = ("; dspContent << outputs.joinIntoString(","); if (wgOutputs.size() > 0) dspContent << "," << wgOutputs.joinIntoString(","); if (junctOutputs.size() > 0) dspContent << "," << junctOutputs.joinIntoString(","); if (outputsPorts.size() > 0) dspContent << "," << outputsPorts.joinIntoString(","); if (audioNames.size() > 0) dspContent << "," << audioNames.joinIntoString(","); dspContent << ") with {\n"; //========================================================================== // code for model objects //========================================================================== dspContent << "\n\t//waveguide termination objects\n"; dspContent << wgTermString; dspContent << "\t//junctions\n"; dspContent << junctString; dspContent << "\t//mass-like objects\n"; dspContent << massobjects.joinIntoString("\n") << "\n"; dspContent << "\n\t//link-like objects\n"; dspContent << linkobjects.joinIntoString("\n") << "\n"; dspContent << "\n\t//audio objects\n"; dspContent << audioobjects.joinIntoString("\n") << "\n};\n\n"; //========================================================================== // Calculate and write feedback line //========================================================================== StringArray feedbackArray; StringArray outputArray; //TODO: needs to be fixed for latest Synth-A-Modeler changes/fiyes int numFeedback = numMasslike - numPorts + (2 * numWaveguides) + numJunctions; for (int i = 0; i < numFeedback; ++i) { feedbackArray.add("_"); outputArray.add("!"); } for (int i = 0; i < numPorts + audioNames.size(); ++i) { feedbackArray.add("!"); outputArray.add("_"); } dspContent << "process = (bigBlock)~("; dspContent << feedbackArray.joinIntoString(","); dspContent << "):("; dspContent << outputArray.joinIntoString(",") << ");"; //========================================================================== massLinkRefs.clear(); wgWithSuffixes.clear(); return dspContent; }