// make the multiple procs. Must set template beforehand. // new copies are intially not enabled. void MLMultProxy::setCopies(const int newSize) { if (newSize < 1) return; if (mTemplate) { int oldSize = (int)mCopies.size(); if (newSize != oldSize) { mCopies.resize(newSize); // initialize new copies MLSymbol className = mTemplate->getClassName(); MLSymbol procName = mTemplate->getName(); for(int i = 0; i < newSize; ++i) { // make new proc. we use the template object's container for the call to // newProc(), but the new proc is not added to the container. // instead we keep a ProcPtr in mCopies. MLProcContainer* c = static_cast<MLProcContainer*>(mTemplate->getContext()); mCopies[i] = c->newProc(className, procName); mCopies[i]->setCopyIndex(i + 1); mCopies[i]->clearProc(); } } } else { debug() << "MLMultProxy: no template for setCopies()!\n"; } }
void MLMultiContainer::process(const int n) { const int outs = getNumOutputs(); // for each copy, process. // TODO this can be dispatched to multiple threads. for (int i=0; i < mEnabledCopies; ++i) { getCopyAsContainer(i)->process(n); } // for each of our outputs, for (int i=1; i <= outs; ++i) { // sum outputs of copies to our output. MLSignal& y = getOutput(i); y.clear(); for(int j=0; j < mEnabledCopies; ++j) { // TODO rewrite to handle multiple outputs better. // right now if the last copy is enabled, it shares a buffer with the // parent and this add doubles the last value. the hack in place adds one more copy to prevent this. MLProcContainer* pCopy = getCopyAsContainer(j); if(pCopy) { y.add(pCopy->getOutput(i)); } else { debug() << "MLMultiContainer: null copy in process()!\n"; } } } }
void MLMultProxy::setEnabledCopies(const int c) { int copies = (int)mCopies.size(); mEnabledCopies = min(c, copies); for (int i=0; i < copies; ++i) { MLProcContainer* pCopy = getCopyAsContainer(i); if (i < mEnabledCopies) { if(!pCopy->isEnabled()) { pCopy->clearProc(); pCopy->setEnabled(true); } } else { if(pCopy->isEnabled()) { pCopy->setEnabled(false); pCopy->clearProc(); } } } }
void MLProcDelayOutput::doParams() { // first get delay input. That's the MLProcDelayInput object with // the same name as us before the underscore. This is fairly brittle and // hackish. We don't have something like string parameters, so this // is the best I could come up with. MLProcContainer* myContainer = static_cast<MLProcContainer*>(getContext()); const std::string myName = getName().getString(); int dPos = myName.find('_'); MLPath delayName (myName.substr(0, dPos)); MLProcPtr myInputProc = myContainer->getProc(delayName); if (myInputProc) { //debug() << "MLProcDelayOutput " << getName() << " doParams found delay proc " << delayName << "!\n"; mpDelayInputProc = static_cast<MLProcDelayInput*>(&(*myInputProc)); if(mpDelayInputProc) { // must be power of two size MLSignal& buffer = mpDelayInputProc->getBuffer(); mLengthMask = buffer.getWidth() - 1; //debug() << "MLProcDelayOutput::doParams found buffer, length mask " << std::hex << mLengthMask << std::dec << "\n"; } } else { debug() << "MLProcDelayOutput::doParams: couldn't find delay proc " << delayName << "\n"; } if(getParam("backwards")) { mVectorDelay = getContextVectorSize(); } else { mVectorDelay = 0; } //debug() << "MLProcDelayOutput: vector delay " << mVectorDelay << "\n"; mParamsChanged = false; }
MLProc::err MLMultiContainer::buildProc(juce::XmlElement* parent) { err e = OK; const int copies = (int)mCopies.size(); const MLSymbol className(parent->getStringAttribute("class").toUTF8()); const MLSymbol procName(parent->getStringAttribute("name").toUTF8()); // debug() << "MLMultiContainer::buildProc (class=" << className << ", name=" << procName << ")\n"; for(int i=0; i<copies; i++) { // add the specified proc to all subcontainers. MLProcContainer* pCopy = getCopyAsContainer(i); if(pCopy != nullptr) { e = pCopy->addProc(className, procName); if (e == MLProc::OK) { MLPath procPath(procName); pCopy->setProcParams(procPath, parent); pCopy->setCopyIndex(i + 1); MLProcPtr p = pCopy->getProc(procPath); if(p) { p->setup(); if (p->isContainer()) { MLProcContainer* pc = static_cast<MLProcContainer*>(&(*p)); pc->buildGraph(parent); } } else { debug() << "MLMultiContainer::buildProc: getProc failed for new proc!\n"; } } } else { debug() << "MLMultiContainer: null copy in buildProc ()!\n"; } } return e; }