29 : input (
std::move (nodeToProcess)), playHeadState (playHeadStateToUse)
36 return input ? input.get()
37 : nodeGraph ? nodeGraph->rootNode.get()
44 setNode (std::move (newNode), sampleRate, blockSize);
50 auto newGraph =
prepareToPlay (std::move (newNode), nodeGraph.get(), sampleRateToUse, blockSizeToUse);
55 oldGraph = std::move (nodeGraph);
56 nodeGraph = std::move (newGraph);
63 if (sampleRate == sampleRateToUse && blockSize == blockSizeToUse)
66 auto oldGraph = std::move (nodeGraph);
67 auto rootNodeToPrepare = input ? std::move (input)
68 : oldGraph ? std::move (oldGraph->rootNode)
70 nodeGraph =
prepareToPlay (std::move (rootNodeToPrepare),
nullptr, sampleRateToUse, blockSizeToUse);
76 sampleRate = sampleRateToUse;
77 blockSize = blockSizeToUse;
79 if (playHeadState !=
nullptr)
82 return node_player_utils::prepareToPlay (std::move (node), oldGraph, sampleRateToUse, blockSizeToUse);
94 inputAndNodesLock.
exit();
100 if (playHeadState !=
nullptr)
101 numMisses = processWithPlayHeadState (*playHeadState, *nodeGraph, pc);
103 numMisses = processPostorderedNodes (*nodeGraph, pc);
105 inputAndNodesLock.
exit();
113 double getSampleRate()
const
118 int processPostorderedNodes (
NodeGraph& graphToProcess,
const Node::ProcessContext& pc)
126 PlayHeadState* playHeadState =
nullptr;
128 double sampleRate = 0.0;
133 int processWithPlayHeadState (PlayHeadState& phs, NodeGraph& graphToProcess,
134 const Node::ProcessContext& pc)
139 const auto splitTimelineRange = referenceSampleRangeToSplitTimelineRange (phs.playHead, pc.referenceSampleRange);
141 if (splitTimelineRange.isSplit)
143 const auto firstProportion = splitTimelineRange.timelineRange1.getLength() / (
double) pc.referenceSampleRange.getLength();
145 const auto firstReferenceRange = pc.referenceSampleRange.withEnd (pc.referenceSampleRange.getStart() + (
int64_t)
std::llround (pc.referenceSampleRange.getLength() * firstProportion));
146 const auto secondReferenceRange =
juce::Range<int64_t> (firstReferenceRange.getEnd(), pc.referenceSampleRange.getEnd());
147 jassert (firstReferenceRange.getLength() + secondReferenceRange.getLength() == pc.referenceSampleRange.getLength());
149 const auto firstNumSamples = (choc::buffer::FrameCount)
std::llround (pc.numSamples * firstProportion);
150 const auto secondNumSamples = pc.numSamples - firstNumSamples;
151 jassert (firstNumSamples + secondNumSamples == pc.numSamples);
154 auto destAudio = pc.buffers.audio.getStart (firstNumSamples);
155 auto& destMidi = pc.buffers.midi;
157 phs.update (firstReferenceRange);
159 numMisses += processPostorderedNodes (graphToProcess, pc1);
163 auto destAudio = pc.buffers.audio.getFrameRange ({ firstNumSamples, firstNumSamples + secondNumSamples });
164 auto& destMidi = pc.buffers.midi;
168 phs.update (secondReferenceRange);
169 numMisses += processPostorderedNodes (graphToProcess, pc2);
174 phs.update (pc.referenceSampleRange);
175 numMisses += processPostorderedNodes (graphToProcess, pc);
186 for (
auto node : nodeGraph.orderedNodes)
187 node->prepareForNextBlock (pc.referenceSampleRange);
190 size_t numNodesProcessed = 0;
194 for (
auto node : nodeGraph.orderedNodes)
196 if (! node->hasProcessed() && node->isReadyToProcess())
198 node->process (pc.numSamples, pc.referenceSampleRange);
207 if (numNodesProcessed == nodeGraph.orderedNodes.size())
209 auto output = nodeGraph.rootNode->getProcessedOutput();
210 auto numAudioChannels =
std::min (output.audio.getNumChannels(),
211 pc.buffers.audio.getNumChannels());
213 if (numAudioChannels > 0)
214 add (pc.buffers.audio.getFirstChannels (numAudioChannels),
215 output.audio.getFirstChannels (numAudioChannels));
217 pc.buffers.midi.mergeFrom (output.midi);
std::unique_ptr< NodeGraph > prepareToPlay(std::unique_ptr< Node > node, NodeGraph *oldGraph, double sampleRateToUse, int blockSizeToUse)
Prepares a specific Node to be played and returns all the Nodes.
Struct to describe a single iteration of a process call.