tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_TestNodes.h
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11#pragma once
12
13namespace tracktion { inline namespace graph
14{
15
16//==============================================================================
17//==============================================================================
22class MidiNode final : public Node
23{
24public:
25 MidiNode (juce::MidiMessageSequence sequenceToPlay)
26 : sequence (std::move (sequenceToPlay))
27 {
28 }
29
31 {
32 return { false, true, 0 };
33 }
34
35 bool isReadyToProcess() override
36 {
37 return true;
38 }
39
40 void prepareToPlay (const PlaybackInitialisationInfo& info) override
41 {
42 sampleRate = info.sampleRate;
43 }
44
45 void process (ProcessContext& pc) override
46 {
47 const int numSamples = (int) pc.referenceSampleRange.getLength();
48 const double blockDuration = numSamples / sampleRate;
49 const auto timeRange = juce::Range<double>::withStartAndLength (lastTime, blockDuration);
50
51 for (int index = sequence.getNextIndexAtTime (timeRange.getStart()); index >= 0; ++index)
52 {
53 if (auto eventHolder = sequence.getEventPointer (index))
54 {
55 auto time = sequence.getEventTime (index);
56
57 if (! timeRange.contains (time))
58 break;
59
60 pc.buffers.midi.addMidiMessage (eventHolder->message, time - timeRange.getStart(),
61 tracktion_engine::MidiMessageArray::notMPE);
62 }
63 else
64 {
65 break;
66 }
67 }
68
69 lastTime = timeRange.getEnd();
70 }
71
72private:
74 double sampleRate = 0.0, lastTime = 0.0;
75};
76
77
78//==============================================================================
79//==============================================================================
80class SinNode final : public Node
81{
82public:
83 SinNode (float frequencyToUse, int numChannelsToUse = 1, size_t nodeIDToUse = 0)
84 : numChannels (numChannelsToUse), nodeID (nodeIDToUse), frequency (frequencyToUse)
85 {
86 }
87
89 {
90 NodeProperties props;
91 props.hasAudio = true;
92 props.hasMidi = false;
93 props.numberOfChannels = numChannels;
94 props.nodeID = nodeID;
95
96 return props;
97 }
98
99 bool isReadyToProcess() override
100 {
101 return true;
102 }
103
104 void prepareToPlay (const PlaybackInitialisationInfo& info) override
105 {
106 oscillator.reset (frequency, info.sampleRate);
107 }
108
109 void process (ProcessContext& pc) override
110 {
111 setAllFrames (pc.buffers.audio, [&] { return oscillator.getNext(); });
112 }
113
114private:
115 const int numChannels;
116 size_t nodeID = 0;
118 float frequency = 0;
119};
120
121
122//==============================================================================
123//==============================================================================
127class SilentNode final : public Node
128{
129public:
130 SilentNode (int numChannelsToUse = 1)
131 : numChannels (numChannelsToUse)
132 {
133 setOptimisations ({ ClearBuffers::no,
134 AllocateAudioBuffer::no });
135 }
136
138 {
139 NodeProperties props;
140 props.hasAudio = true;
141 props.hasMidi = false;
142 props.numberOfChannels = numChannels;
143
144 return props;
145 }
146
147 bool isReadyToProcess() override
148 {
149 return true;
150 }
151
152 void prepareToPlay (const PlaybackInitialisationInfo& info) override
153 {
154 audioBuffer.resize (choc::buffer::Size::create ((choc::buffer::ChannelCount) numChannels,
155 (choc::buffer::FrameCount) info.blockSize));
156 audioBuffer.clear();
157 }
158
159 void process (ProcessContext& pc) override
160 {
161 pc.buffers.midi.clear();
162 setAudioOutput (nullptr, audioBuffer.getView().getStart (pc.buffers.audio.getNumFrames()));
163 }
164
165private:
166 const int numChannels;
167 choc::buffer::ChannelArrayBuffer<float> audioBuffer;
168};
169
170
171//==============================================================================
172//==============================================================================
173class BasicSummingNode final : public Node
174{
175public:
177 : nodes (std::move (inputs))
178 {
179 }
180
182 {
183 NodeProperties props;
184 props.hasAudio = false;
185 props.hasMidi = false;
186 props.numberOfChannels = 0;
187
188 for (auto& node : nodes)
189 {
190 auto nodeProps = node->getNodeProperties();
191 props.hasAudio = props.hasAudio || nodeProps.hasAudio;
192 props.hasMidi = props.hasMidi || nodeProps.hasMidi;
193 props.numberOfChannels = std::max (props.numberOfChannels, nodeProps.numberOfChannels);
194 }
195
196 return props;
197 }
198
200 {
201 std::vector<Node*> inputNodes;
202
203 for (auto& node : nodes)
204 inputNodes.push_back (node.get());
205
206 return inputNodes;
207 }
208
209 bool isReadyToProcess() override
210 {
211 for (auto& node : nodes)
212 if (! node->hasProcessed())
213 return false;
214
215 return true;
216 }
217
218 void process (ProcessContext& pc) override
219 {
220 const auto numChannels = pc.buffers.audio.getNumChannels();
221
222 // Get each of the inputs and add them to dest
223 for (auto& node : nodes)
224 {
225 auto inputFromNode = node->getProcessedOutput();
226
227 if (auto numChannelsToAdd = std::min (inputFromNode.audio.getNumChannels(), numChannels))
228 add (pc.buffers.audio.getFirstChannels (numChannelsToAdd),
229 inputFromNode.audio.getFirstChannels (numChannelsToAdd));
230
231 pc.buffers.midi.mergeFrom (inputFromNode.midi);
232 }
233 }
234
235private:
237};
238
239
241static inline std::unique_ptr<BasicSummingNode> makeBaicSummingNode (std::initializer_list<Node*> nodes)
242{
244
245 for (auto node : nodes)
246 nodeVector.push_back (std::unique_ptr<Node> (node));
247
248 return std::make_unique<BasicSummingNode> (std::move (nodeVector));
249}
250
251
252//==============================================================================
253//==============================================================================
254class FunctionNode final : public Node
255{
256public:
258 std::function<float (float)> fn)
259 : node (std::move (input)),
260 function (std::move (fn))
261 {
262 jassert (function);
263 }
264
266 {
267 return node->getNodeProperties();
268 }
269
271 {
272 return { node.get() };
273 }
274
275 bool isReadyToProcess() override
276 {
277 return node->hasProcessed();
278 }
279
280 void process (ProcessContext& pc) override
281 {
282 auto inputBuffer = node->getProcessedOutput().audio;
283
284 auto numFrames = pc.referenceSampleRange.getLength();
285 const auto numChannels = std::min (inputBuffer.getNumChannels(), pc.buffers.audio.getNumChannels());
286 jassert (inputBuffer.getNumFrames() == numFrames);
287
288 for (choc::buffer::ChannelCount c = 0; c < numChannels; ++c)
289 {
290 auto destIter = pc.buffers.audio.getIterator (c);
291 auto sourceIter = inputBuffer.getIterator (c);
292
293 for (choc::buffer::FrameCount i = 0; i < numFrames; ++i)
294 *destIter++ = function (*sourceIter++);
295 }
296 }
297
298private:
300 std::function<float (float)> function;
301};
302
303//==============================================================================
305static inline std::unique_ptr<Node> makeGainNode (std::unique_ptr<Node> input, float gain)
306{
307 return makeNode<FunctionNode> (std::move (input), [gain] (float s) { return s * gain; });
308}
309
310//==============================================================================
311//==============================================================================
312class GainNode final : public Node
313{
314public:
316 GainNode (Node* inputNode, std::function<float()> gainFunc)
317 : input (inputNode), gainFunction (std::move (gainFunc))
318 {
319 assert (input != nullptr);
320 assert (gainFunction);
321 lastGain = gainFunction();
322 }
323
325 GainNode (std::unique_ptr<Node> inputNode, std::function<float()> gainFunc)
326 : ownedInput (std::move (inputNode)), input (ownedInput.get()),
327 gainFunction (std::move (gainFunc))
328 {
329 assert (ownedInput != nullptr);
330 assert (input != nullptr);
331 assert (gainFunction);
332 lastGain = gainFunction();
333 }
334
336 {
337 auto props = input->getNodeProperties();
338 constexpr size_t gainNodeMagicHash = size_t (0x6761696e4e6f6465);
339
340 if (props.nodeID != 0)
341 hash_combine (props.nodeID, gainNodeMagicHash);
342
343 return props;
344 }
345
347 {
348 return { input };
349 }
350
351 bool isReadyToProcess() override
352 {
353 return input->hasProcessed();
354 }
355
356 void process (ProcessContext& pc) override
357 {
358 jassert (pc.buffers.audio.getNumChannels() == input->getProcessedOutput().audio.getNumChannels());
359
360 // Just pass out input on to our output
361 copy (pc.buffers.audio, input->getProcessedOutput().audio);
362 pc.buffers.midi.mergeFrom (input->getProcessedOutput().midi);
363
364 float gain = gainFunction();
365
366 if (gain == lastGain)
367 {
368 if (gain == 0.0f)
369 pc.buffers.audio.clear();
370 else if (gain != 1.0f)
371 applyGain (pc.buffers.audio, gain);
372 }
373 else
374 {
375 juce::SmoothedValue<float> smoother (lastGain);
376 smoother.setTargetValue (gain);
377 smoother.reset ((int) pc.buffers.audio.getNumFrames());
378 applyGainPerFrame (pc.buffers.audio, [&] { return smoother.getNextValue(); });
379 }
380
381 lastGain = gain;
382 }
383
384private:
385 std::unique_ptr<Node> ownedInput;
386 Node* input = nullptr;
387 std::function<float()> gainFunction;
388 float lastGain = 0.0f;
389};
390
391//==============================================================================
392//==============================================================================
393class SendNode : public Node
394{
395public:
396 SendNode (std::unique_ptr<Node> inputNode, int busIDToUse,
397 std::function<float()> getGainFunc = nullptr)
398 : input (std::move (inputNode)), busID (busIDToUse),
399 gainFunction (std::move (getGainFunc))
400 {
401 setOptimisations ({ ClearBuffers::no,
402 AllocateAudioBuffer::no });
403 }
404
405 int getBusID() const
406 {
407 return busID;
408 }
409
410 std::function<float()> getGainFunction()
411 {
412 return gainFunction;
413 }
414
416 {
417 auto props = input->getNodeProperties();
418 constexpr size_t sendNodeMagicHash = size_t (0x73656e644e6f6465);
419
420 if (props.nodeID != 0)
421 hash_combine (props.nodeID, sendNodeMagicHash);
422
423 return props;
424 }
425
427 {
428 return { input.get() };
429 }
430
431 bool isReadyToProcess() override
432 {
433 return input->hasProcessed();
434 }
435
436 void process (ProcessContext& pc) override
437 {
438 auto source = input->getProcessedOutput();
439 jassert (pc.buffers.audio.getSize() == source.audio.getSize());
440
441 // Just pass out input on to our output
442 // N.B We need to clear manually here due to optimisations
443 setAudioOutput (input.get(), source.audio);
444
445 // If the source only outputs to this node, we can steal its data
446 if (input->numOutputNodes == 1)
447 pc.buffers.midi.swapWith (source.midi);
448 else
449 pc.buffers.midi.copyFrom (source.midi);
450 }
451
452private:
454 const int busID;
455 std::function<float()> gainFunction;
456};
457
458
459//==============================================================================
460//==============================================================================
461class ReturnNode final : public Node
462{
463public:
464 ReturnNode (int busIDToUse)
465 : busID (busIDToUse)
466 {
467 setOptimisations ({ ClearBuffers::no,
468 AllocateAudioBuffer::yes });
469 }
470
471 ReturnNode (std::unique_ptr<Node> inputNode, int busIDToUse)
472 : input (std::move (inputNode)), busID (busIDToUse)
473 {
474 setOptimisations ({ ClearBuffers::no,
475 AllocateAudioBuffer::yes });
476 }
477
479 {
480 NodeProperties props;
481 props.hasAudio = false;
482 props.hasMidi = false;
483 props.numberOfChannels = 0;
484
485 for (auto& node : getDirectInputNodes())
486 {
487 auto nodeProps = node->getNodeProperties();
488 props.hasAudio = props.hasAudio || nodeProps.hasAudio;
489 props.hasMidi = props.hasMidi || nodeProps.hasMidi;
490 props.numberOfChannels = std::max (props.numberOfChannels, nodeProps.numberOfChannels);
491 props.latencyNumSamples = std::max (props.latencyNumSamples, nodeProps.latencyNumSamples);
492 hash_combine (props.nodeID, nodeProps.nodeID);
493 }
494
495 constexpr size_t returnNodeMagicHash = size_t (0x72657475726e);
496
497 if (props.nodeID != 0)
498 hash_combine (props.nodeID, returnNodeMagicHash);
499
500 return props;
501 }
502
504 {
505 if (! input)
506 return {};
507
508 return { input.get() };
509 }
510
511 TransformResult transform (Node& rootNode, const std::vector<Node*>& postOrderedNodes, TransformCache& cache) override
512 {
513 if (! hasInitialised)
514 {
515 findSendNodes (rootNode, postOrderedNodes, cache);
516 return TransformResult::connectionsMade;
517 }
518
519 return TransformResult::none;
520 }
521
523 {
524 if (! input)
525 return;
526
527 if (! info.enableNodeMemorySharing)
528 return;
529
530 if (input->numOutputNodes > 1)
531 return;
532
533 const auto inputNumChannels = input->getNodeProperties().numberOfChannels;
534 const auto desiredNumChannels = getNodeProperties().numberOfChannels;
535
536 if (inputNumChannels >= desiredNumChannels)
537 {
538 canUseSourceBuffers = true;
539 setOptimisations ({ tracktion::graph::ClearBuffers::no,
540 tracktion::graph::AllocateAudioBuffer::no });
541 }
542 }
543
544 bool isReadyToProcess() override
545 {
546 return ! input || input->hasProcessed();
547 }
548
549 void preProcess (choc::buffer::FrameCount, juce::Range<int64_t>) override
550 {
551 if (canUseSourceBuffers)
552 setBufferViewToUse (input.get(), input->getProcessedOutput().audio);
553 }
554
555 void process (ProcessContext& pc) override
556 {
557 if (! input)
558 {
559 // N.B We need to clear manually here due to optimisations
560 pc.buffers.midi.clear();
561 pc.buffers.audio.clear();
562
563 return;
564 }
565
566 auto source = input->getProcessedOutput();
567 jassert (pc.buffers.audio.getSize() == source.audio.getSize());
568
569 // Copy the input on to our output, the SummingNode will copy all the sends and get all the input
570 setAudioOutput (input.get(), source.audio);
571 pc.buffers.midi.copyFrom (source.midi);
572 }
573
574private:
576 const int busID;
577 bool hasInitialised = false, canUseSourceBuffers = false;
578
579 void findSendNodes (Node&, const std::vector<Node*>& postOrderedNodes, TransformCache& cache)
580 {
581 // This can only be initialised once as otherwise the latency nodes will get created again
582 jassert (! hasInitialised);
583
584 if (hasInitialised)
585 return;
586
587 std::vector<SendNode*> allSends;
588
589 constexpr size_t cacheKey = 3399892065; // Random number
590
591 if (auto cachedVec = cache.getCachedProperty<std::vector<SendNode*>> (cacheKey))
592 {
593 allSends = *cachedVec;
594 }
595 else
596 {
597 for (auto n : postOrderedNodes)
598 if (auto send = dynamic_cast<SendNode*> (n))
599 allSends.push_back (send);
600
601 cache.cacheProperty (cacheKey, allSends);
602 }
603
605
606 for (auto send : allSends)
607 if (send->getBusID() == busID)
608 sends.push_back (send);
609
610 // Remove any send nodes that feed back in to this
611 std::vector<Node*> sendsToRemove;
612
613 for (auto send : sends)
614 {
615 visitNodes (*send,
616 [&] (Node& n)
617 {
618 if (&n == this)
619 sendsToRemove.push_back (send);
620 }, true);
621 }
622
623 sends.erase (std::remove_if (sends.begin(), sends.end(),
624 [&] (auto n) { return std::find (sendsToRemove.begin(), sendsToRemove.end(), n) != sendsToRemove.end(); }),
625 sends.end());
626
627 // Create a summing node if required
628 if (sends.size() > 0)
629 {
631
632 if (input)
633 ownedNodes.push_back (std::move (input));
634
635 // For each of the sends create a live gain node
636 for (int i = (int) sends.size(); --i >= 0;)
637 {
638 auto gainFunction = sends[(size_t) i]->getGainFunction();
639
640 if (! gainFunction)
641 continue;
642
643 ownedNodes.push_back (makeNode<GainNode> (std::move (sends[(size_t) i]), std::move (gainFunction)));
644 sends.erase (std::find (sends.begin(), sends.end(), sends[(size_t) i]));
645 }
646
647 auto node = makeNode<SummingNode> (std::move (ownedNodes), std::vector<Node*> (sends.begin(), sends.end()));
648 input.swap (node);
649 }
650
651 hasInitialised = true;
652 }
653};
654
655
656//==============================================================================
657//==============================================================================
659class ChannelRemappingNode final : public Node
660{
661public:
664 bool passMidiThrough)
665 : input (std::move (inputNode)),
666 channelMap (std::move (channelMapToUse)),
667 passMIDI (passMidiThrough)
668 {
669 jassert (input);
670 }
671
673 {
674 NodeProperties props;
675 props.hasAudio = ! channelMap.empty();
676 props.hasMidi = passMIDI;
677 props.numberOfChannels = 0;
678
679 const auto inputProps = input->getNodeProperties();
680 props.latencyNumSamples = inputProps.latencyNumSamples;
681
682 props.nodeID = inputProps.nodeID;
683 hash_combine (props.nodeID, passMIDI);
684
685 // Num channels is the max of destinations
686 for (auto channel : channelMap)
687 {
688 hash_combine (props.nodeID, channel.first);
689 hash_combine (props.nodeID, channel.second);
690
691 props.numberOfChannels = std::max (props.numberOfChannels, channel.second + 1);
692 }
693
694 constexpr size_t channelNodeMagicHash = size_t (0x6368616e6e656c);
695
696 if (props.nodeID != 0)
697 hash_combine (props.nodeID, channelNodeMagicHash);
698
699 return props;
700 }
701
703 {
704 return { input.get() };
705 }
706
707 bool isReadyToProcess() override
708 {
709 return input->hasProcessed();
710 }
711
712 void process (ProcessContext& pc) override
713 {
714 auto inputBuffers = input->getProcessedOutput();
715
716 // Pass on MIDI
717 if (passMIDI)
718 pc.buffers.midi.mergeFrom (inputBuffers.midi);
719
720 // Remap audio
721 for (auto channel : channelMap)
722 if (channel.first < (int) inputBuffers.audio.getNumChannels())
723 add (pc.buffers.audio.getChannel ((choc::buffer::ChannelCount) channel.second),
724 inputBuffers.audio.getChannel ((choc::buffer::ChannelCount) channel.first));
725 }
726
727private:
729 const std::vector<std::pair<int, int>> channelMap;
730 const bool passMIDI;
731};
732
733
735static inline std::vector<std::pair<int, int>> makeChannelMap (std::initializer_list<std::pair<int, int>> sourceDestChannelIndicies)
736{
738
739 for (auto channelPair : sourceDestChannelIndicies)
740 map.push_back (channelPair);
741
742 return map;
743}
744
745//==============================================================================
746//==============================================================================
748class SinkNode final : public Node
749{
750public:
752 : input (std::move (inputNode))
753 {
754 jassert (input);
755 }
756
758 {
759 constexpr size_t sinkNodeMagicHash = size_t (0x95ab5e9dcd);
760 auto props = input->getNodeProperties();
761 hash_combine (props.nodeID, sinkNodeMagicHash);
762
763 return props;
764 }
765
767 {
768 return { input.get() };
769 }
770
771 bool isReadyToProcess() override
772 {
773 return input->hasProcessed();
774 }
775
776 void process (ProcessContext&) override
777 {
778 }
779
780private:
782};
783
784
785//==============================================================================
786//==============================================================================
789{
790public:
792 : input (inputNode)
793 {
794 jassert (input);
795 }
796
798 : ForwardingNode (inputNode.get())
799 {
800 nodePtr = std::move (inputNode);
801 }
802
804 {
805 auto props = input->getNodeProperties();
806 hash_combine (props.nodeID, nodeID);
807
808 return props;
809 }
810
812 {
813 return { input };
814 }
815
816 bool isReadyToProcess() override
817 {
818 return input->hasProcessed();
819 }
820
821 void process (ProcessContext& pc) override
822 {
823 auto inputBuffers = input->getProcessedOutput();
824 copy (pc.buffers.audio, inputBuffers.audio);
825 pc.buffers.midi.copyFrom (inputBuffers.midi);
826 }
827
828private:
831 const size_t nodeID { (size_t) juce::Random::getSystemRandom().nextInt() };
832};
833
834}}
assert
T begin(T... args)
double getEventTime(int index) const noexcept
int getNextIndexAtTime(double timeStamp) const noexcept
MidiEventHolder * getEventPointer(int index) const noexcept
int nextInt() noexcept
static Random & getSystemRandom() noexcept
static Range withStartAndLength(const ValueType startValue, const ValueType length) noexcept
constexpr ValueType getLength() const noexcept
void reset(double sampleRate, double rampLengthInSeconds) noexcept
void setTargetValue(FloatType newValue) noexcept
std::vector< Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this node.
bool isReadyToProcess() override
Should return true when this node is ready to be processed.
NodeProperties getNodeProperties() override
Should return the properties of the node.
void process(ProcessContext &pc) override
Called when the node is to be processed.
Maps channels from one to another.
void process(ProcessContext &pc) override
Called when the node is to be processed.
std::vector< Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this 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.
Takes a non-owning input node and simply forwards its outputs on.
void process(ProcessContext &pc) override
Called when the node is to be processed.
tracktion::graph::NodeProperties getNodeProperties() override
Should return the properties of the node.
std::vector< tracktion::graph::Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this node.
bool isReadyToProcess() override
Should return true when this node is ready to be processed.
void process(ProcessContext &pc) override
Called when the node is to be processed.
std::vector< Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this 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.
GainNode(std::unique_ptr< Node > inputNode, std::function< float()> gainFunc)
Creates a GainNode that owns its input.
GainNode(Node *inputNode, std::function< float()> gainFunc)
Creates a GainNode that doesn't own its input.
std::vector< Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this 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.
void process(ProcessContext &pc) override
Called when the node is to be processed.
Plays back a MIDI sequence.
void prepareToPlay(const PlaybackInitialisationInfo &info) override
Called once before playback begins for each node.
bool isReadyToProcess() override
Should return true when this node is ready to be processed.
NodeProperties getNodeProperties() override
Should return the properties of the node.
void process(ProcessContext &pc) override
Called when the node is to be processed.
Main graph Node processor class.
void setAudioOutput(Node *sourceNode, const choc::buffer::ChannelArrayView< float > &)
This can be called during your process function to set a view to the output.
void setOptimisations(NodeOptimisations)
This can be called to provide some hints about allocating or playing back a Node to improve efficienc...
void setBufferViewToUse(Node *sourceNode, const choc::buffer::ChannelArrayView< float > &)
This can be called during prepareToPlay to set a BufferView to use which can improve efficiency.
Struct to describe a single iteration of a process call.
TransformResult transform(Node &rootNode, const std::vector< Node * > &postOrderedNodes, TransformCache &cache) override
Called after construction to give the node a chance to modify its topology.
std::vector< Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this 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.
void preProcess(choc::buffer::FrameCount, juce::Range< int64_t >) override
Called when the node is to be processed, just before process.
void process(ProcessContext &pc) override
Called when the node is to be processed.
void prepareToPlay(const tracktion::graph::PlaybackInitialisationInfo &info) override
Called once before playback begins for each node.
void process(ProcessContext &pc) override
Called when the node is to be processed.
std::vector< Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this node.
bool isReadyToProcess() override
Should return true when this node is ready to be processed.
NodeProperties getNodeProperties() override
Should return the properties of the node.
Just a simple audio node that doesn't take any input so can be used as a stub.
void process(ProcessContext &pc) override
Called when the node is to be processed.
bool isReadyToProcess() override
Should return true when this node is ready to be processed.
void prepareToPlay(const PlaybackInitialisationInfo &info) override
Called once before playback begins for each node.
NodeProperties getNodeProperties() override
Should return the properties of the 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.
void prepareToPlay(const PlaybackInitialisationInfo &info) override
Called once before playback begins for each node.
void process(ProcessContext &pc) override
Called when the node is to be processed.
Blocks audio and MIDI input from reaching the outputs.
NodeProperties getNodeProperties() override
Should return the properties of the node.
bool isReadyToProcess() override
Should return true when this node is ready to be processed.
void process(ProcessContext &) override
Called when the node is to be processed.
std::vector< Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this node.
T empty(T... args)
T end(T... args)
T erase(T... args)
T find(T... args)
T get(T... args)
T is_pointer_v
#define jassert(expression)
typedef int
typedef float
T max(T... args)
T min(T... args)
TransformResult
Enum to signify the result of the transform function.
T push_back(T... args)
T remove_if(T... args)
send
T size(T... args)
Holds some really basic properties of a node.
Passed into Nodes when they are being initialised, to give them useful contextual information that th...
T swap(T... args)
typedef size_t
time