13namespace tracktion {
inline namespace engine
26 : input (std::move (inputNode)),
27 inputProvider (std::move (inputProviderToUse))
35 return { input.get() };
40 return input->getNodeProperties();
45 return input->hasProcessed();
54 auto inputs = input->getProcessedOutput();
55 tracktion::graph::sanityCheckView (inputs.audio);
56 inputProvider->setInputs (inputs);
71 int numAudioChannels,
bool hasMidiInput)
72 : inputProvider (std::move (inputProviderToUse)),
73 numChannels (numAudioChannels),
74 hasMidi (hasMidiInput)
79 : inputProvider (std::move (inputProviderToUse)),
80 numChannels ((
int) (inputProvider->numChannels > 0 ? inputProvider->numChannels
81 : inputProvider->audio.getNumChannels())),
86 void setInputDependancy (
Node* dependancy)
88 nodeDependancy = dependancy;
94 props.hasAudio = numChannels > 0;
95 props.hasMidi = hasMidi;
96 props.numberOfChannels = numChannels;
97 props.nodeID = nodeID;
108 return { nodeDependancy };
125 auto inputBuffers = inputProvider->getInputs();
126 tracktion::graph::sanityCheckView (inputBuffers.audio);
130 auto& outputBuffers = pc.buffers;
133 auto numInputChannelsToCopy =
std::min (inputBuffers.audio.getNumChannels(),
134 outputBuffers.audio.getNumChannels());
136 if (numInputChannelsToCopy > 0)
140 jassert (inputBuffers.audio.getNumFrames() >= outputBuffers.audio.getNumFrames());
142 add (outputBuffers.audio.getFirstChannels (numInputChannelsToCopy),
143 inputBuffers.audio.getFirstChannels (numInputChannelsToCopy).getStart (outputBuffers.audio.getNumFrames()));
148 pc.buffers.midi.copyFrom (inputBuffers.midi);
153 const int numChannels;
155 Node* nodeDependancy =
nullptr;
168 : nodes (std::move (nodesToStore)),
169 nodeID ((
size_t) rackID.getRawID())
175 return {
true,
true, 0, 0, nodeID };
200namespace RackNodeBuilder
207 node =
dynamic_cast<ModifierNode*
> (&pluginOrModifierNode);
224 if (
dynamic_cast<PluginNode*
> (&destPluginOrModifierNode) !=
nullptr)
225 return destPinIndex - 1;
227 if (
auto node =
dynamic_cast<ModifierNode*
> (&destPluginOrModifierNode))
228 return destPinIndex - node->getModifier().getMidiInputNames().size();
239 node =
dynamic_cast<ModifierNode*
> (&pluginOrModifierNode);
247 struct RackConnectionData
249 EditItemID sourceID, destID;
250 int sourcePin = -1, destPin = -1;
254 struct RackPinConnections
256 EditItemID sourceID, destID;
263 bool passMidi =
false;
270 for (
auto c : channels)
271 numChannels =
std::
max (numChannels,
272 std::
max (c.first, c.second) + 1);
284 for (
auto& node : itemNodes)
285 if (auto modifierNode = dynamic_cast<ModifierNode*> (node.get()))
286 if (modifierNode->getModifier().itemID == itemID)
287 return modifierNode->getModifier().getMidiInputNames().
size();
296 for (
auto c : connections)
305 for (
auto c : connections)
306 pinConnections.push_back ({ c.sourcePin, c.destPin });
308 return pinConnections;
314 ChannelMap channelMap;
316 for (
auto c : pinConnections)
318 if (c.first == 0 && c.second < numDestMidiPins)
319 channelMap.passMidi =
true;
321 channelMap.channels.push_back ({ c.first - 1, c.second - numDestMidiPins });
328 EditItemID sourceID, EditItemID destID)
332 for (
auto c : allConnections)
333 if (c->sourceID == sourceID && c->destID == destID)
334 connections.push_back ({ c->sourceID.get(), c->destID.get(), c->sourcePin.get(), c->destPin.get() });
342 auto allConnections = rack.getConnections();
345 for (
auto c : allConnections)
347 if (itemIsSource && c->sourceID != itemID)
350 if (c->destID != itemID)
353 auto sourceDest =
std::make_pair (c->sourceID.get(), c->destID.get());
356 if (
std::find (sourcesDestsDone.
begin(), sourcesDestsDone.
end(), sourceDest) != sourcesDestsDone.
end())
359 connections.
push_back (getConnectionsBetween (allConnections, c->sourceID, c->destID));
364 [] (
auto c) { return c.empty(); }),
372 return getConnectionsToOrFrom (rack, destID,
false);
377 return getConnectionsToOrFrom (rack, sourceID,
true);
382 double sampleRate,
int blockSize,
384 ProcessState& processState,
387 using namespace tracktion::graph;
396 for (
auto plugin : rack.getPlugins())
398 plugin, sampleRate, blockSize, nullptr,
399 processState, isRendering, true, -1);
401 for (
auto m : rack.getModifierList().getModifiers())
403 m, sampleRate, blockSize, nullptr,
404 processState.playHeadState, isRendering);
410 for (
const auto& connection : rack.getConnections())
412 const EditItemID sourceID = connection->sourceID;
414 const int sourcePin = connection->sourcePin;
415 const int destPin = connection->destPin;
417 if (sourceID.isInvalid() && destID.isInvalid())
420 if (sourcePin == 0 && destPin == 0)
421 outputNode->addMidiConnection (inputNode);
422 else if (sourcePin > 0 && destPin > 0)
423 outputNode->addAudioConnection (inputNode,
ChannelConnection { sourcePin - 1, destPin - 1 });
427 else if (sourceID.isInvalid() && destID.isValid())
430 if (
auto destNode = itemNodes[destID])
432 auto& destConnectedNode = getConnectedNode (*destNode);
434 if (sourcePin == 0 && destPin == 0)
435 destConnectedNode.addMidiConnection (inputNode);
436 else if (sourcePin > 0 && destPin >= 0)
437 destConnectedNode.addAudioConnection (inputNode,
ChannelConnection { sourcePin - 1, getDestChannelIndex (*destNode, destPin) });
446 else if (sourceID.isValid() && destID.isInvalid())
449 if (
auto sourceNode = itemNodes[sourceID])
451 if (sourcePin == 0 && destPin == 0)
452 outputNode->addMidiConnection (sourceNode);
453 else if (sourcePin > 0 && destPin > 0)
454 outputNode->addAudioConnection (sourceNode,
ChannelConnection { sourcePin - 1, destPin - 1 });
463 else if (sourceID.isValid() && destID.isValid())
466 auto sourceNode = itemNodes[sourceID];
467 auto destNode = itemNodes[destID];
469 if (sourceNode ==
nullptr || destNode ==
nullptr)
475 auto& destConnectedNode = getConnectedNode (*destNode);
477 if (sourcePin == 0 && destPin == 0)
478 destConnectedNode.addMidiConnection (sourceNode);
479 else if (sourcePin > 0 && destPin >= 0)
480 destConnectedNode.addAudioConnection (sourceNode,
ChannelConnection { sourcePin - 1, getDestChannelIndex (*destNode, destPin) });
491 for (
auto& node : itemNodes)
492 if (auto modifierNode = dynamic_cast<
ModifierNode*> (node.second.get()))
493 if (getConnectionsFrom (rack, modifierNode->getModifier().itemID).
empty())
496 if (finalOutput->getDirectInputNodes().size() > 0)
498 finalOutput->addInput (std::move (outputNode));
507 double sampleRate,
int blockSize,
511 return createRackNodeConnectedNode (rackType,
512 sampleRate, blockSize,
514 processState, isRendering);
static Random & getSystemRandom() noexcept
Takes ownership of a number of nodes but doesn't do any processing.
void process(ProcessContext &) override
Called when the node is to be processed.
bool isReadyToProcess() override
Should return true when this node is ready to be processed.
std::vector< tracktion::graph::Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this node.
tracktion::graph::NodeProperties getNodeProperties() override
Should return the properties of the node.
Node for processing a Modifier.
Node for processing a plugin.
An Node which sums together the multiple inputs adding additional latency to provide a coherent outpu...
Takes a non-owning input node and simply forwards its outputs on.
Main graph Node processor class.
virtual std::vector< Node * > getDirectInputNodes()
Should return all the inputs directly feeding in to this node.
virtual NodeProperties getNodeProperties()=0
Should return the properties of the node.
bool hasProcessed() const
Returns true if this node has processed and its outputs can be retrieved.
Struct to describe a single iteration of a process call.
An Node which sums together the multiple inputs adding additional latency to provide a coherent outpu...
std::unique_ptr< Node > makeNode(Args &&... args)
Creates a node of the given type and returns it as the base Node class.
ID for objects of type EditElement - e.g.
Holds the state of a process call.
Holds some really basic properties of a node.
Passed into Nodes when they are being initialised, to give them useful contextual information that th...