16namespace tracktion {
inline namespace graph
78 bool connectMidi =
false;
82 static int getMaxDestChannel (
const NodeConnection& connection)
86 for (
const auto& channelConnection : connection.connectedChannels)
87 maxChannel =
std::max (maxChannel, channelConnection.destChannel);
95 bool createLatencyNodes();
102 : nodeID (nodeIDToUse)
111 bool cycleDetected =
false;
112 visitNodes (*input, [
this, &cycleDetected] (
auto& n) { cycleDetected = cycleDetected || &n ==
this; },
false);
118 for (
auto& connection : connections)
120 if (connection.node.get() == input.
get())
122 for (
const auto& channelConnection : connection.connectedChannels)
123 if (newConnection == channelConnection)
126 connection.connectedChannels.push_back (newConnection);
132 connections.
push_back ({ std::move (input),
false, { newConnection } });
139 bool cycleDetected =
false;
140 visitNodes (*input, [
this, &cycleDetected] (
auto& n) { cycleDetected = cycleDetected || &n ==
this; },
false);
146 for (
auto& connection : connections)
148 if (connection.node.get() == input.
get())
150 if (connection.connectMidi)
153 connection.connectMidi =
true;
159 connections.
push_back ({ std::move (input),
true, {} });
167 props.hasAudio =
false;
168 props.hasMidi =
false;
169 props.numberOfChannels = 0;
170 props.nodeID = nodeID;
172 constexpr size_t connectedNodeMagicHash =
size_t (0x636f6e6e656374);
174 if (props.nodeID != 0)
175 hash_combine (props.nodeID, connectedNodeMagicHash);
177 for (
const auto& connection : connections)
179 auto nodeProps = connection.node->getNodeProperties();
180 props.hasAudio = props.hasAudio || ! connection.connectedChannels.empty();
181 props.hasMidi = props.hasMidi || connection.connectMidi;
182 props.numberOfChannels =
std::max (props.numberOfChannels, getMaxDestChannel (connection)) + 1;
183 props.latencyNumSamples =
std::max (props.latencyNumSamples, nodeProps.latencyNumSamples);
186 hash_combine (props.nodeID, nodeProps.nodeID);
187 hash_combine (props.nodeID, connection.connectMidi);
189 for (
const auto& channelConnection : connection.connectedChannels)
191 hash_combine (props.nodeID, channelConnection.sourceChannel);
192 hash_combine (props.nodeID, channelConnection.destChannel);
203 for (
const auto& connection : connections)
204 inputs.
push_back (connection.node.get());
211 return createLatencyNodes() ? TransformResult::connectionsMade
212 : TransformResult::none;
217 for (
const auto& connection : connections)
218 if (! connection.node->hasProcessed())
230 auto destAudio = pc.buffers.audio;
231 auto& destMIDI = pc.buffers.midi;
233 const int numSamples = (
int) pc.referenceSampleRange.
getLength();
235 jassert (destAudio.getNumChannels() == 0 || numSamples == (
int) destAudio.getNumFrames());
237 for (
const auto& connection : connections)
239 auto sourceOutput = connection.node->getProcessedOutput();
240 auto sourceAudio = sourceOutput.audio;
241 auto& sourceMidi = sourceOutput.midi;
242 jassert (destAudio.getNumChannels() == 0 || numSamples == (
int) sourceAudio.getNumFrames());
244 if (connection.connectMidi)
245 destMIDI.mergeFrom (sourceMidi);
247 for (
const auto& channelConnection : connection.connectedChannels)
249 auto sourceChan = channelConnection.sourceChannel;
250 auto destChan = channelConnection.destChannel;
252 if (sourceChan < 0 || destChan < 0)
258 if (sourceChan >= (
int) sourceAudio.getNumChannels())
261 add (destAudio.getChannel ((choc::buffer::ChannelCount) destChan),
262 sourceAudio.getChannel ((choc::buffer::ChannelCount) sourceChan));
267inline bool ConnectedNode::createLatencyNodes()
269 bool topologyChanged =
false;
273 for (
auto& connection : connections)
275 auto& node = connection.node;
276 const int nodeLatency = node->getNodeProperties().latencyNumSamples;
277 const int latencyToAdd = maxLatency - nodeLatency;
279 if (latencyToAdd == 0)
287 topologyChanged =
true;
290 return topologyChanged;
constexpr ValueType getLength() const noexcept
An Node which sums together the multiple inputs adding additional latency to provide a coherent outpu...
void process(ProcessContext &) override
Called when the node is to be processed.
void prepareToPlay(const PlaybackInitialisationInfo &) override
Called once before playback begins for each node.
NodeProperties getNodeProperties() override
Should return the properties of the node.
bool isReadyToProcess() override
Should return true when this node is ready to be processed.
bool addMidiConnection(std::shared_ptr< Node >)
Adds a MIDI connection.
TransformResult transform(Node &, const std::vector< Node * > &, TransformCache &) override
Called after construction to give the node a chance to modify its topology.
bool addAudioConnection(std::shared_ptr< Node >, ChannelConnection)
Adds an audio connection.
ConnectedNode()=default
Creates a ConnectedNode with no connections.
std::vector< Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this node.
Main graph Node processor class.
Struct to describe a single iteration of a process call.
void ignoreUnused(Types &&...) noexcept
void visitNodes(Node &, Visitor &&, bool preordering)
Should call the visitor for any direct inputs to the node exactly once.
TransformResult
Enum to signify the result of the transform function.
int destChannel
The destination channel.
int sourceChannel
The source channel.
Holds some really basic properties of a node.
Passed into Nodes when they are being initialised, to give them useful contextual information that th...