LMMS
Loading...
Searching...
No Matches
AudioProcessorGraph.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the Water library.
5 Copyright (c) 2015 ROLI Ltd.
6 Copyright (C) 2017-2022 Filipe Coelho <falktx@falktx.com>
7
8 Permission is granted to use this software under the terms of the GNU
9 General Public License as published by the Free Software Foundation;
10 either version 2 of the License, or any later version.
11
12 This program is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15
16 For a full copy of the GNU General Public License see the doc/GPL.txt file.
17
18 ==============================================================================
19*/
20
21#include "AudioProcessorGraph.h"
23
24namespace water {
25
26//==============================================================================
28{
29
31{
34
35 virtual void perform (AudioSampleBuffer& sharedAudioBufferChans,
36 AudioSampleBuffer& sharedCVBufferChans,
37 const OwnedArray<MidiBuffer>& sharedMidiBuffers,
38 const int numSamples) = 0;
39};
40
41// use CRTP
42template <class Child>
44{
45 void perform (AudioSampleBuffer& sharedAudioBufferChans,
46 AudioSampleBuffer& sharedCVBufferChans,
47 const OwnedArray<MidiBuffer>& sharedMidiBuffers,
48 const int numSamples) override
49 {
50 static_cast<Child*> (this)->perform (sharedAudioBufferChans,
51 sharedCVBufferChans,
52 sharedMidiBuffers,
53 numSamples);
54 }
55};
56
57//==============================================================================
58struct ClearChannelOp : public AudioGraphRenderingOp<ClearChannelOp>
59{
60 ClearChannelOp (const int channel, const bool cv) noexcept
61 : channelNum (channel), isCV (cv) {}
62
63 void perform (AudioSampleBuffer& sharedAudioBufferChans,
64 AudioSampleBuffer& sharedCVBufferChans,
66 const int numSamples)
67 {
68 if (isCV)
69 sharedCVBufferChans.clear (channelNum, 0, numSamples);
70 else
71 sharedAudioBufferChans.clear (channelNum, 0, numSamples);
72 }
73
74 const int channelNum;
75 const bool isCV;
76
78};
79
80//==============================================================================
81struct CopyChannelOp : public AudioGraphRenderingOp<CopyChannelOp>
82{
83 CopyChannelOp (const int srcChan, const int dstChan, const bool cv) noexcept
84 : srcChannelNum (srcChan), dstChannelNum (dstChan), isCV (cv) {}
85
86 void perform (AudioSampleBuffer& sharedAudioBufferChans,
87 AudioSampleBuffer& sharedCVBufferChans,
89 const int numSamples)
90 {
91 if (isCV)
92 sharedCVBufferChans.copyFrom (dstChannelNum, 0, sharedCVBufferChans, srcChannelNum, 0, numSamples);
93 else
94 sharedAudioBufferChans.copyFrom (dstChannelNum, 0, sharedAudioBufferChans, srcChannelNum, 0, numSamples);
95 }
96
98 const bool isCV;
99
101};
102
103//==============================================================================
104struct AddChannelOp : public AudioGraphRenderingOp<AddChannelOp>
105{
106 AddChannelOp (const int srcChan, const int dstChan, const bool cv) noexcept
107 : srcChannelNum (srcChan), dstChannelNum (dstChan), isCV (cv) {}
108
109 void perform (AudioSampleBuffer& sharedAudioBufferChans,
110 AudioSampleBuffer& sharedCVBufferChans,
112 const int numSamples)
113 {
114 if (isCV)
115 sharedCVBufferChans.addFrom (dstChannelNum, 0, sharedCVBufferChans, srcChannelNum, 0, numSamples);
116 else
117 sharedAudioBufferChans.addFrom (dstChannelNum, 0, sharedAudioBufferChans, srcChannelNum, 0, numSamples);
118 }
119
121 const bool isCV;
122
124};
125
126//==============================================================================
127struct ClearMidiBufferOp : public AudioGraphRenderingOp<ClearMidiBufferOp>
128{
129 ClearMidiBufferOp (const int buffer) noexcept : bufferNum (buffer) {}
130
132 const OwnedArray<MidiBuffer>& sharedMidiBuffers,
133 const int)
134 {
135 sharedMidiBuffers.getUnchecked (bufferNum)->clear();
136 }
137
138 const int bufferNum;
139
141};
142
143//==============================================================================
144struct CopyMidiBufferOp : public AudioGraphRenderingOp<CopyMidiBufferOp>
145{
146 CopyMidiBufferOp (const int srcBuffer, const int dstBuffer) noexcept
147 : srcBufferNum (srcBuffer), dstBufferNum (dstBuffer)
148 {}
149
151 const OwnedArray<MidiBuffer>& sharedMidiBuffers,
152 const int)
153 {
154 *sharedMidiBuffers.getUnchecked (dstBufferNum) = *sharedMidiBuffers.getUnchecked (srcBufferNum);
155 }
156
158
160};
161
162//==============================================================================
163struct AddMidiBufferOp : public AudioGraphRenderingOp<AddMidiBufferOp>
164{
165 AddMidiBufferOp (const int srcBuffer, const int dstBuffer)
166 : srcBufferNum (srcBuffer), dstBufferNum (dstBuffer)
167 {}
168
170 const OwnedArray<MidiBuffer>& sharedMidiBuffers,
171 const int numSamples)
172 {
173 sharedMidiBuffers.getUnchecked (dstBufferNum)
174 ->addEvents (*sharedMidiBuffers.getUnchecked (srcBufferNum), 0, numSamples, 0);
175 }
176
178
180};
181
182//==============================================================================
183struct DelayChannelOp : public AudioGraphRenderingOp<DelayChannelOp>
184{
185 DelayChannelOp (const int chan, const int delaySize, const bool cv)
186 : channel (chan),
187 bufferSize (delaySize + 1),
188 readIndex (0), writeIndex (delaySize),
189 isCV (cv)
190 {
191 buffer.calloc ((size_t) bufferSize);
192 }
193
194 void perform (AudioSampleBuffer& sharedAudioBufferChans,
195 AudioSampleBuffer& sharedCVBufferChans,
197 const int numSamples)
198 {
199 float* data = isCV
200 ? sharedCVBufferChans.getWritePointer (channel, 0)
201 : sharedAudioBufferChans.getWritePointer (channel, 0);
202 HeapBlock<float>& block = buffer;
203
204 for (int i = numSamples; --i >= 0;)
205 {
206 block [writeIndex] = *data;
207 *data++ = block [readIndex];
208
209 if (++readIndex >= bufferSize) readIndex = 0;
210 if (++writeIndex >= bufferSize) writeIndex = 0;
211 }
212 }
213
214private:
216 const int channel, bufferSize;
218 const bool isCV;
219
221};
222
223//==============================================================================
224struct ProcessBufferOp : public AudioGraphRenderingOp<ProcessBufferOp>
225{
227 const Array<uint>& audioChannelsUsed,
228 const uint totalNumChans,
229 const Array<uint>& cvInChannelsUsed,
230 const Array<uint>& cvOutChannelsUsed,
231 const int midiBuffer)
232 : node (n),
233 processor (n->getProcessor()),
234 audioChannelsToUse (audioChannelsUsed),
235 cvInChannelsToUse (cvInChannelsUsed),
236 cvOutChannelsToUse (cvOutChannelsUsed),
237 totalAudioChans (jmax (1U, totalNumChans)),
238 totalCVIns (cvInChannelsUsed.size()),
239 totalCVOuts (cvOutChannelsUsed.size()),
240 midiBufferToUse (midiBuffer)
241 {
243 cvInChannels.calloc (totalCVIns);
244 cvOutChannels.calloc (totalCVOuts);
245
246 while (audioChannelsToUse.size() < static_cast<int>(totalAudioChans))
247 audioChannelsToUse.add (0);
248 }
249
250 void perform (AudioSampleBuffer& sharedAudioBufferChans,
251 AudioSampleBuffer& sharedCVBufferChans,
252 const OwnedArray<MidiBuffer>& sharedMidiBuffers,
253 const int numSamples)
254 {
255 HeapBlock<float*>& audioChannelsCopy = audioChannels;
256 HeapBlock<float*>& cvInChannelsCopy = cvInChannels;
257 HeapBlock<float*>& cvOutChannelsCopy = cvOutChannels;
258
259 for (uint i = 0; i < totalAudioChans; ++i)
260 audioChannelsCopy[i] = sharedAudioBufferChans.getWritePointer (audioChannelsToUse.getUnchecked (i), 0);
261
262 for (uint i = 0; i < totalCVIns; ++i)
263 cvInChannels[i] = sharedCVBufferChans.getWritePointer (cvInChannelsToUse.getUnchecked (i), 0);
264
265 for (uint i = 0; i < totalCVOuts; ++i)
266 cvOutChannels[i] = sharedCVBufferChans.getWritePointer (cvOutChannelsToUse.getUnchecked (i), 0);
267
268 AudioSampleBuffer audioBuffer (audioChannelsCopy, totalAudioChans, numSamples);
269 AudioSampleBuffer cvInBuffer (cvInChannelsCopy, totalCVIns, numSamples);
270 AudioSampleBuffer cvOutBuffer (cvOutChannelsCopy, totalCVOuts, numSamples);
271
272 if (processor->isSuspended())
273 {
274 audioBuffer.clear();
275 cvOutBuffer.clear();
276 }
277 else
278 {
279 const CarlaRecursiveMutexLocker cml (processor->getCallbackLock());
280
281 callProcess (audioBuffer, cvInBuffer, cvOutBuffer, *sharedMidiBuffers.getUnchecked (midiBufferToUse));
282 }
283 }
284
285 void callProcess (AudioSampleBuffer& audioBuffer,
286 AudioSampleBuffer& cvInBuffer,
287 AudioSampleBuffer& cvOutBuffer,
288 MidiBuffer& midiMessages)
289 {
290 processor->processBlockWithCV (audioBuffer, cvInBuffer, cvOutBuffer, midiMessages);
291 }
292
295
296private:
308
310};
311
312//==============================================================================
317{
320 Array<void*>& renderingOps)
321 : graph (g),
322 orderedNodes (nodes),
323 totalLatency (0)
324 {
325 audioNodeIds.add ((uint32) zeroNodeID); // first buffer is read-only zeros
326 audioChannels.add (0);
327
329 cvChannels.add (0);
330
332
333 for (int i = 0; i < orderedNodes.size(); ++i)
334 {
335 createRenderingOpsForNode (*orderedNodes.getUnchecked(i), renderingOps, i);
337 }
338
339 graph.setLatencySamples (totalLatency);
340 }
341
345
346private:
347 //==============================================================================
352
353 enum { freeNodeID = 0xffffffff, zeroNodeID = 0xfffffffe, anonymousNodeID = 0xfffffffd };
354
355 static bool isNodeBusy (uint32 nodeID) noexcept { return nodeID != freeNodeID; }
356
360
361 int getNodeDelay (const uint32 nodeID) const { return nodeDelays [nodeDelayIDs.indexOf (nodeID)]; }
362
363 void setNodeDelay (const uint32 nodeID, const int latency)
364 {
365 const int index = nodeDelayIDs.indexOf (nodeID);
366
367 if (index >= 0)
368 {
369 nodeDelays.set (index, latency);
370 }
371 else
372 {
373 nodeDelayIDs.add (nodeID);
374 nodeDelays.add (latency);
375 }
376 }
377
378 int getInputLatencyForNode (const uint32 nodeID) const
379 {
380 int maxLatency = 0;
381
382 for (int i = graph.getNumConnections(); --i >= 0;)
383 {
384 const AudioProcessorGraph::Connection* const c = graph.getConnection (i);
385
386 if (c->destNodeId == nodeID)
387 maxLatency = jmax (maxLatency, getNodeDelay (c->sourceNodeId));
388 }
389
390 return maxLatency;
391 }
392
393 //==============================================================================
395 Array<void*>& renderingOps,
396 const int ourRenderingIndex)
397 {
398 AudioProcessor& processor = *node.getProcessor();
403 const uint totalAudioChans = jmax (numAudioIns, numAudioOuts);
404
405 Array<uint> audioChannelsToUse, cvInChannelsToUse, cvOutChannelsToUse;
406 int midiBufferToUse = -1;
407
408 int maxLatency = getInputLatencyForNode (node.nodeId);
409
410 for (uint inputChan = 0; inputChan < numAudioIns; ++inputChan)
411 {
412 // get a list of all the inputs to this node
413 Array<uint32> sourceNodes;
414 Array<uint> sourceOutputChans;
415
416 for (int i = graph.getNumConnections(); --i >= 0;)
417 {
418 const AudioProcessorGraph::Connection* const c = graph.getConnection (i);
419
420 if (c->destNodeId == node.nodeId
421 && c->destChannelIndex == inputChan
422 && c->channelType == AudioProcessor::ChannelTypeAudio)
423 {
424 sourceNodes.add (c->sourceNodeId);
425 sourceOutputChans.add (c->sourceChannelIndex);
426 }
427 }
428
429 int bufIndex = -1;
430
431 if (sourceNodes.size() == 0)
432 {
433 // unconnected input channel
435 renderingOps.add (new ClearChannelOp (bufIndex, false));
436 }
437 else if (sourceNodes.size() == 1)
438 {
439 // channel with a straightforward single input..
440 const uint32 srcNode = sourceNodes.getUnchecked(0);
441 const uint srcChan = sourceOutputChans.getUnchecked(0);
442
443 bufIndex = getBufferContaining (AudioProcessor::ChannelTypeAudio, srcNode, srcChan);
444
445 if (bufIndex < 0)
446 {
447 // if not found, this is probably a feedback loop
448 bufIndex = getReadOnlyEmptyBuffer();
449 wassert (bufIndex >= 0);
450 }
451
452 if (inputChan < numAudioOuts
454 ourRenderingIndex,
455 inputChan,
456 srcNode, srcChan))
457 {
458 // can't mess up this channel because it's needed later by another node, so we
459 // need to use a copy of it..
460 const int newFreeBuffer = getFreeBuffer (AudioProcessor::ChannelTypeAudio);
461
462 renderingOps.add (new CopyChannelOp (bufIndex, newFreeBuffer, false));
463
464 bufIndex = newFreeBuffer;
465 }
466
467 const int nodeDelay = getNodeDelay (srcNode);
468
469 if (nodeDelay < maxLatency)
470 renderingOps.add (new DelayChannelOp (bufIndex, maxLatency - nodeDelay, false));
471 }
472 else
473 {
474 // channel with a mix of several inputs..
475
476 // try to find a re-usable channel from our inputs..
477 int reusableInputIndex = -1;
478
479 for (int i = 0; i < sourceNodes.size(); ++i)
480 {
481 const int sourceBufIndex = getBufferContaining (AudioProcessor::ChannelTypeAudio,
482 sourceNodes.getUnchecked(i),
483 sourceOutputChans.getUnchecked(i));
484
485 if (sourceBufIndex >= 0
487 ourRenderingIndex,
488 inputChan,
489 sourceNodes.getUnchecked(i),
490 sourceOutputChans.getUnchecked(i)))
491 {
492 // we've found one of our input chans that can be re-used..
493 reusableInputIndex = i;
494 bufIndex = sourceBufIndex;
495
496 const int nodeDelay = getNodeDelay (sourceNodes.getUnchecked (i));
497 if (nodeDelay < maxLatency)
498 renderingOps.add (new DelayChannelOp (sourceBufIndex, maxLatency - nodeDelay, false));
499
500 break;
501 }
502 }
503
504 if (reusableInputIndex < 0)
505 {
506 // can't re-use any of our input chans, so get a new one and copy everything into it..
508 wassert (bufIndex != 0);
509
511 bufIndex, static_cast<uint32> (anonymousNodeID), 0);
512
514 sourceNodes.getUnchecked (0),
515 sourceOutputChans.getUnchecked (0));
516 if (srcIndex < 0)
517 {
518 // if not found, this is probably a feedback loop
519 renderingOps.add (new ClearChannelOp (bufIndex, false));
520 }
521 else
522 {
523 renderingOps.add (new CopyChannelOp (srcIndex, bufIndex, false));
524 }
525
526 reusableInputIndex = 0;
527 const int nodeDelay = getNodeDelay (sourceNodes.getFirst());
528
529 if (nodeDelay < maxLatency)
530 renderingOps.add (new DelayChannelOp (bufIndex, maxLatency - nodeDelay, false));
531 }
532
533 for (int j = 0; j < sourceNodes.size(); ++j)
534 {
535 if (j != reusableInputIndex)
536 {
538 sourceNodes.getUnchecked(j),
539 sourceOutputChans.getUnchecked(j));
540 if (srcIndex >= 0)
541 {
542 const int nodeDelay = getNodeDelay (sourceNodes.getUnchecked (j));
543
544 if (nodeDelay < maxLatency)
545 {
547 ourRenderingIndex, inputChan,
548 sourceNodes.getUnchecked(j),
549 sourceOutputChans.getUnchecked(j)))
550 {
551 renderingOps.add (new DelayChannelOp (srcIndex, maxLatency - nodeDelay, false));
552 }
553 else // buffer is reused elsewhere, can't be delayed
554 {
555 const int bufferToDelay = getFreeBuffer (AudioProcessor::ChannelTypeAudio);
556 renderingOps.add (new CopyChannelOp (srcIndex, bufferToDelay, false));
557 renderingOps.add (new DelayChannelOp (bufferToDelay, maxLatency - nodeDelay, false));
558 srcIndex = bufferToDelay;
559 }
560 }
561
562 renderingOps.add (new AddChannelOp (srcIndex, bufIndex, false));
563 }
564 }
565 }
566 }
567
568 CARLA_SAFE_ASSERT_CONTINUE (bufIndex >= 0);
569 audioChannelsToUse.add (bufIndex);
570
571 if (inputChan < numAudioOuts)
573 }
574
575 for (uint outputChan = numAudioIns; outputChan < numAudioOuts; ++outputChan)
576 {
577 const int bufIndex = getFreeBuffer (AudioProcessor::ChannelTypeAudio);
578 CARLA_SAFE_ASSERT_CONTINUE (bufIndex > 0);
579 audioChannelsToUse.add (bufIndex);
581 }
582
583 for (uint inputChan = 0; inputChan < numCVIns; ++inputChan)
584 {
585 // get a list of all the inputs to this node
586 Array<uint32> sourceNodes;
587 Array<uint> sourceOutputChans;
588
589 for (int i = graph.getNumConnections(); --i >= 0;)
590 {
591 const AudioProcessorGraph::Connection* const c = graph.getConnection (i);
592
593 if (c->destNodeId == node.nodeId
594 && c->destChannelIndex == inputChan
595 && c->channelType == AudioProcessor::ChannelTypeCV)
596 {
597 sourceNodes.add (c->sourceNodeId);
598 sourceOutputChans.add (c->sourceChannelIndex);
599 }
600 }
601
602 int bufIndex = -1;
603
604 if (sourceNodes.size() == 0)
605 {
606 // unconnected input channel
608 renderingOps.add (new ClearChannelOp (bufIndex, true));
609 }
610 else if (sourceNodes.size() == 1)
611 {
612 // channel with a straightforward single input..
613 const uint32 srcNode = sourceNodes.getUnchecked(0);
614 const uint srcChan = sourceOutputChans.getUnchecked(0);
615
616 bufIndex = getBufferContaining (AudioProcessor::ChannelTypeCV, srcNode, srcChan);
617
618 if (bufIndex < 0)
619 {
620 // if not found, this is probably a feedback loop
621 bufIndex = getReadOnlyEmptyBuffer();
622 wassert (bufIndex >= 0);
623 }
624
625 const int newFreeBuffer = getFreeBuffer (AudioProcessor::ChannelTypeCV);
626
627 renderingOps.add (new CopyChannelOp (bufIndex, newFreeBuffer, true));
628
629 bufIndex = newFreeBuffer;
630
631 const int nodeDelay = getNodeDelay (srcNode);
632
633 if (nodeDelay < maxLatency)
634 renderingOps.add (new DelayChannelOp (bufIndex, maxLatency - nodeDelay, true));
635 }
636 else
637 {
638 // channel with a mix of several inputs..
639
640 {
642 wassert (bufIndex != 0);
643
645 sourceNodes.getUnchecked (0),
646 sourceOutputChans.getUnchecked (0));
647 if (srcIndex < 0)
648 {
649 // if not found, this is probably a feedback loop
650 renderingOps.add (new ClearChannelOp (bufIndex, true));
651 }
652 else
653 {
654 renderingOps.add (new CopyChannelOp (srcIndex, bufIndex, true));
655 }
656
657 const int nodeDelay = getNodeDelay (sourceNodes.getFirst());
658
659 if (nodeDelay < maxLatency)
660 renderingOps.add (new DelayChannelOp (bufIndex, maxLatency - nodeDelay, true));
661 }
662
663 for (int j = 1; j < sourceNodes.size(); ++j)
664 {
666 sourceNodes.getUnchecked(j),
667 sourceOutputChans.getUnchecked(j));
668 if (srcIndex >= 0)
669 {
670 const int nodeDelay = getNodeDelay (sourceNodes.getUnchecked (j));
671
672 if (nodeDelay < maxLatency)
673 {
674 const int bufferToDelay = getFreeBuffer (AudioProcessor::ChannelTypeCV);
675 renderingOps.add (new CopyChannelOp (srcIndex, bufferToDelay, true));
676 renderingOps.add (new DelayChannelOp (bufferToDelay, maxLatency - nodeDelay, true));
677 srcIndex = bufferToDelay;
678 }
679
680 renderingOps.add (new AddChannelOp (srcIndex, bufIndex, true));
681 }
682 }
683 }
684
685 CARLA_SAFE_ASSERT_CONTINUE (bufIndex >= 0);
686 cvInChannelsToUse.add (bufIndex);
688 }
689
690 for (uint outputChan = 0; outputChan < numCVOuts; ++outputChan)
691 {
692 const int bufIndex = getFreeBuffer (AudioProcessor::ChannelTypeCV);
693 CARLA_SAFE_ASSERT_CONTINUE (bufIndex > 0);
694 cvOutChannelsToUse.add (bufIndex);
695 markBufferAsContaining (AudioProcessor::ChannelTypeCV, bufIndex, node.nodeId, outputChan);
696 }
697
698 // Now the same thing for midi..
699 Array<uint32> midiSourceNodes;
700
701 for (int i = graph.getNumConnections(); --i >= 0;)
702 {
703 const AudioProcessorGraph::Connection* const c = graph.getConnection (i);
704
705 if (c->destNodeId == node.nodeId && c->channelType == AudioProcessor::ChannelTypeMIDI)
706 midiSourceNodes.add (c->sourceNodeId);
707 }
708
709 if (midiSourceNodes.size() == 0)
710 {
711 // No midi inputs..
712 midiBufferToUse = getFreeBuffer (AudioProcessor::ChannelTypeMIDI); // need to pick a buffer even if the processor doesn't use midi
713
714 if (processor.acceptsMidi() || processor.producesMidi())
715 renderingOps.add (new ClearMidiBufferOp (midiBufferToUse));
716 }
717 else if (midiSourceNodes.size() == 1)
718 {
719 // One midi input..
721 midiSourceNodes.getUnchecked(0),
722 0);
723 if (midiBufferToUse >= 0)
724 {
726 ourRenderingIndex, 0,
727 midiSourceNodes.getUnchecked(0), 0))
728 {
729 // can't mess up this channel because it's needed later by another node, so we
730 // need to use a copy of it..
731 const int newFreeBuffer = getFreeBuffer (AudioProcessor::ChannelTypeMIDI);
732 renderingOps.add (new CopyMidiBufferOp (midiBufferToUse, newFreeBuffer));
733 midiBufferToUse = newFreeBuffer;
734 }
735 }
736 else
737 {
738 // probably a feedback loop, so just use an empty one..
739 midiBufferToUse = getFreeBuffer (AudioProcessor::ChannelTypeMIDI); // need to pick a buffer even if the processor doesn't use midi
740 }
741 }
742 else
743 {
744 // More than one midi input being mixed..
745 int reusableInputIndex = -1;
746
747 for (int i = 0; i < midiSourceNodes.size(); ++i)
748 {
749 const int sourceBufIndex = getBufferContaining (AudioProcessor::ChannelTypeMIDI,
750 midiSourceNodes.getUnchecked(i),
751 0);
752
753 if (sourceBufIndex >= 0
755 ourRenderingIndex, 0,
756 midiSourceNodes.getUnchecked(i), 0))
757 {
758 // we've found one of our input buffers that can be re-used..
759 reusableInputIndex = i;
760 midiBufferToUse = sourceBufIndex;
761 break;
762 }
763 }
764
765 if (reusableInputIndex < 0)
766 {
767 // can't re-use any of our input buffers, so get a new one and copy everything into it..
769 wassert (midiBufferToUse >= 0);
770
772 midiSourceNodes.getUnchecked(0),
773 0);
774 if (srcIndex >= 0)
775 renderingOps.add (new CopyMidiBufferOp (srcIndex, midiBufferToUse));
776 else
777 renderingOps.add (new ClearMidiBufferOp (midiBufferToUse));
778
779 reusableInputIndex = 0;
780 }
781
782 for (int j = 0; j < midiSourceNodes.size(); ++j)
783 {
784 if (j != reusableInputIndex)
785 {
787 midiSourceNodes.getUnchecked(j),
788 0);
789 if (srcIndex >= 0)
790 renderingOps.add (new AddMidiBufferOp (srcIndex, midiBufferToUse));
791 }
792 }
793 }
794
795 if (processor.producesMidi())
797 midiBufferToUse, node.nodeId,
798 0);
799
800 setNodeDelay (node.nodeId, maxLatency + processor.getLatencySamples());
801
802 if (numAudioOuts == 0)
803 totalLatency = maxLatency;
804
805 renderingOps.add (new ProcessBufferOp (&node,
806 audioChannelsToUse,
807 totalAudioChans,
808 cvInChannelsToUse,
809 cvOutChannelsToUse,
810 midiBufferToUse));
811 }
812
813 //==============================================================================
815 {
816 switch (channelType)
817 {
819 for (int i = 1; i < audioNodeIds.size(); ++i)
820 if (audioNodeIds.getUnchecked(i) == freeNodeID)
821 return i;
822
824 audioChannels.add (0);
825 return audioNodeIds.size() - 1;
826
828 for (int i = 1; i < cvNodeIds.size(); ++i)
829 if (cvNodeIds.getUnchecked(i) == freeNodeID)
830 return i;
831
833 cvChannels.add (0);
834 return cvNodeIds.size() - 1;
835
837 for (int i = 1; i < midiNodeIds.size(); ++i)
838 if (midiNodeIds.getUnchecked(i) == freeNodeID)
839 return i;
840
842 return midiNodeIds.size() - 1;
843 }
844
845 return -1;
846 }
847
849 {
850 return 0;
851 }
852
854 const uint32 nodeId,
855 const uint outputChannel) const noexcept
856 {
857 switch (channelType)
858 {
860 for (int i = audioNodeIds.size(); --i >= 0;)
861 if (audioNodeIds.getUnchecked(i) == nodeId && audioChannels.getUnchecked(i) == outputChannel)
862 return i;
863 break;
864
866 for (int i = cvNodeIds.size(); --i >= 0;)
867 if (cvNodeIds.getUnchecked(i) == nodeId && cvChannels.getUnchecked(i) == outputChannel)
868 return i;
869 break;
870
872 for (int i = midiNodeIds.size(); --i >= 0;)
873 {
874 if (midiNodeIds.getUnchecked(i) == nodeId)
875 return i;
876 }
877 break;
878 }
879
880 return -1;
881 }
882
883 void markAnyUnusedBuffersAsFree (const int stepIndex)
884 {
885 for (int i = 0; i < audioNodeIds.size(); ++i)
886 {
887 if (isNodeBusy (audioNodeIds.getUnchecked(i))
889 stepIndex, -1,
890 audioNodeIds.getUnchecked(i),
891 audioChannels.getUnchecked(i)))
892 {
894 }
895 }
896
897 // NOTE: CV skipped on purpose
898
899 for (int i = 0; i < midiNodeIds.size(); ++i)
900 {
901 if (isNodeBusy (midiNodeIds.getUnchecked(i))
903 stepIndex, -1,
904 midiNodeIds.getUnchecked(i), 0))
905 {
907 }
908 }
909 }
910
912 int stepIndexToSearchFrom,
913 uint inputChannelOfIndexToIgnore,
914 const uint32 nodeId,
915 const uint outputChanIndex) const
916 {
917 while (stepIndexToSearchFrom < orderedNodes.size())
918 {
919 const AudioProcessorGraph::Node* const node = (const AudioProcessorGraph::Node*) orderedNodes.getUnchecked (stepIndexToSearchFrom);
920
921 for (uint i = 0; i < node->getProcessor()->getTotalNumInputChannels(channelType); ++i)
922 if (i != inputChannelOfIndexToIgnore
923 && graph.getConnectionBetween (channelType,
924 nodeId, outputChanIndex,
925 node->nodeId, i) != nullptr)
926 return true;
927
928 inputChannelOfIndexToIgnore = (uint)-1;
929 ++stepIndexToSearchFrom;
930 }
931
932 return false;
933 }
934
936 int bufferNum, uint32 nodeId, int outputIndex)
937 {
938 switch (channelType)
939 {
941 CARLA_SAFE_ASSERT_BREAK (bufferNum >= 0 && bufferNum < audioNodeIds.size());
942 audioNodeIds.set (bufferNum, nodeId);
943 audioChannels.set (bufferNum, outputIndex);
944 break;
945
947 CARLA_SAFE_ASSERT_BREAK (bufferNum >= 0 && bufferNum < cvNodeIds.size());
948 cvNodeIds.set (bufferNum, nodeId);
949 cvChannels.set (bufferNum, outputIndex);
950 break;
951
953 CARLA_SAFE_ASSERT_BREAK (bufferNum > 0 && bufferNum < midiNodeIds.size());
954 midiNodeIds.set (bufferNum, nodeId);
955 break;
956 }
957 }
958
960};
961
962//==============================================================================
963// Holds a fast lookup table for checking which nodes are inputs to others.
965{
966public:
968 {
969 for (int i = 0; i < static_cast<int>(connections.size()); ++i)
970 {
971 const AudioProcessorGraph::Connection* const c = connections.getUnchecked(i);
972
973 int index;
974 Entry* entry = findEntry (c->destNodeId, index);
975
976 if (entry == nullptr)
977 {
978 entry = new Entry (c->destNodeId);
979 entries.insert (index, entry);
980 }
981
982 entry->srcNodes.add (c->sourceNodeId);
983 }
984 }
985
986 bool isAnInputTo (const uint32 possibleInputId,
987 const uint32 possibleDestinationId) const noexcept
988 {
989 return isAnInputToRecursive (possibleInputId, possibleDestinationId, entries.size());
990 }
991
992private:
993 //==============================================================================
994 struct Entry
995 {
996 explicit Entry (const uint32 destNodeId_) noexcept : destNodeId (destNodeId_) {}
997
1000
1002 };
1003
1005
1006 bool isAnInputToRecursive (const uint32 possibleInputId,
1007 const uint32 possibleDestinationId,
1008 int recursionCheck) const noexcept
1009 {
1010 int index;
1011
1012 if (const Entry* const entry = findEntry (possibleDestinationId, index))
1013 {
1014 const SortedSet<uint32>& srcNodes = entry->srcNodes;
1015
1016 if (srcNodes.contains (possibleInputId))
1017 return true;
1018
1019 if (--recursionCheck >= 0)
1020 {
1021 for (int i = 0; i < srcNodes.size(); ++i)
1022 if (isAnInputToRecursive (possibleInputId, srcNodes.getUnchecked(i), recursionCheck))
1023 return true;
1024 }
1025 }
1026
1027 return false;
1028 }
1029
1030 Entry* findEntry (const uint32 destNodeId, int& insertIndex) const noexcept
1031 {
1032 Entry* result = nullptr;
1033
1034 int start = 0;
1035 int end = entries.size();
1036
1037 for (;;)
1038 {
1039 if (start >= end)
1040 {
1041 break;
1042 }
1043 else if (destNodeId == entries.getUnchecked (start)->destNodeId)
1044 {
1045 result = entries.getUnchecked (start);
1046 break;
1047 }
1048 else
1049 {
1050 const int halfway = (start + end) / 2;
1051
1052 if (halfway == start)
1053 {
1054 if (destNodeId >= entries.getUnchecked (halfway)->destNodeId)
1055 ++start;
1056
1057 break;
1058 }
1059 else if (destNodeId >= entries.getUnchecked (halfway)->destNodeId)
1060 start = halfway;
1061 else
1062 end = halfway;
1063 }
1064 }
1065
1066 insertIndex = start;
1067 return result;
1068 }
1069
1071};
1072
1073//==============================================================================
1075{
1076 static int compareElements (const AudioProcessorGraph::Connection* const first,
1077 const AudioProcessorGraph::Connection* const second) noexcept
1078 {
1079 if (first->sourceNodeId < second->sourceNodeId) return -1;
1080 if (first->sourceNodeId > second->sourceNodeId) return 1;
1081 if (first->destNodeId < second->destNodeId) return -1;
1082 if (first->destNodeId > second->destNodeId) return 1;
1083 if (first->sourceChannelIndex < second->sourceChannelIndex) return -1;
1084 if (first->sourceChannelIndex > second->sourceChannelIndex) return 1;
1085 if (first->destChannelIndex < second->destChannelIndex) return -1;
1086 if (first->destChannelIndex > second->destChannelIndex) return 1;
1087
1088 return 0;
1089 }
1090};
1091
1092}
1093
1094//==============================================================================
1096 const uint32 sourceID, const uint sourceChannel,
1097 const uint32 destID, const uint destChannel) noexcept
1098 : channelType (ct),
1099 sourceNodeId (sourceID), sourceChannelIndex (sourceChannel),
1100 destNodeId (destID), destChannelIndex (destChannel)
1101{
1102}
1103
1104//==============================================================================
1106 : nodeId (nodeID), processor (p), isPrepared (false)
1107{
1108 wassert (processor != nullptr);
1109}
1110
1111void AudioProcessorGraph::Node::prepare (const double newSampleRate, const int newBlockSize,
1112 AudioProcessorGraph* const graph)
1113{
1114 if (! isPrepared)
1115 {
1116 setParentGraph (graph);
1117
1118 processor->setRateAndBufferSizeDetails (newSampleRate, newBlockSize);
1119 processor->prepareToPlay (newSampleRate, newBlockSize);
1120 isPrepared = true;
1121 }
1122}
1123
1125{
1126 if (isPrepared)
1127 {
1128 isPrepared = false;
1129 processor->releaseResources();
1130 }
1131}
1132
1134{
1137 ioProc->setParentGraph (graph);
1138}
1139
1140//==============================================================================
1142{
1146
1147 void setRenderingBufferSize (int newNumAudioChannels, int newNumCVChannels, int newNumSamples) noexcept
1148 {
1149 renderingAudioBuffers.setSize (newNumAudioChannels, newNumSamples);
1150 renderingAudioBuffers.clear();
1151
1152 renderingCVBuffers.setSize (newNumCVChannels, newNumSamples);
1153 renderingCVBuffers.clear();
1154 }
1155
1157 {
1158 renderingAudioBuffers.setSize (1, 1);
1159 currentAudioInputBuffer = nullptr;
1160 currentCVInputBuffer = nullptr;
1161 currentAudioOutputBuffer.setSize (1, 1);
1162 currentCVOutputBuffer.setSize (1, 1);
1163
1164 renderingCVBuffers.setSize (1, 1);
1165 }
1166
1167 void prepareInOutBuffers (int newNumAudioChannels, int newNumCVChannels, int newNumSamples) noexcept
1168 {
1169 currentAudioInputBuffer = nullptr;
1170 currentCVInputBuffer = nullptr;
1171 currentAudioOutputBuffer.setSize (newNumAudioChannels, newNumSamples);
1172 currentCVOutputBuffer.setSize (newNumCVChannels, newNumSamples);
1173 }
1174
1181};
1182
1183//==============================================================================
1189
1195
1197{
1198 return "Audio Graph";
1199}
1200
1201//==============================================================================
1203{
1204 nodes.clear();
1205 connections.clear();
1206 needsReorder = true;
1207}
1208
1210{
1211 for (int i = nodes.size(); --i >= 0;)
1212 if (nodes.getUnchecked(i)->nodeId == nodeId)
1213 return nodes.getUnchecked(i);
1214
1215 return nullptr;
1216}
1217
1219{
1220 CARLA_SAFE_ASSERT_RETURN (newProcessor != nullptr && newProcessor != this, nullptr);
1221
1222 for (int i = nodes.size(); --i >= 0;)
1223 {
1224 CARLA_SAFE_ASSERT_RETURN (nodes.getUnchecked(i)->getProcessor() != newProcessor, nullptr);
1225 }
1226
1227 if (nodeId == 0)
1228 {
1229 nodeId = ++lastNodeId;
1230 }
1231 else
1232 {
1233 // you can't add a node with an id that already exists in the graph..
1234 CARLA_SAFE_ASSERT_RETURN (getNodeForId (nodeId) == nullptr, nullptr);
1235 removeNode (nodeId);
1236
1237 if (nodeId > lastNodeId)
1238 lastNodeId = nodeId;
1239 }
1240
1241 Node* const n = new Node (nodeId, newProcessor);
1242 nodes.add (n);
1243
1244 if (isPrepared)
1245 needsReorder = true;
1246
1247 n->setParentGraph (this);
1248 return n;
1249}
1250
1252{
1253 disconnectNode (nodeId);
1254
1255 for (int i = nodes.size(); --i >= 0;)
1256 {
1257 if (nodes.getUnchecked(i)->nodeId == nodeId)
1258 {
1259 nodes.remove (i);
1260
1261 if (isPrepared)
1262 needsReorder = true;
1263
1264 return true;
1265 }
1266 }
1267
1268 return false;
1269}
1270
1272{
1273 CARLA_SAFE_ASSERT_RETURN(node != nullptr, false);
1274
1275 return removeNode (node->nodeId);
1276}
1277
1278//==============================================================================
1280 const uint32 sourceNodeId,
1281 const uint sourceChannelIndex,
1282 const uint32 destNodeId,
1283 const uint destChannelIndex) const
1284{
1285 const Connection c (ct, sourceNodeId, sourceChannelIndex, destNodeId, destChannelIndex);
1287 return connections [connections.indexOfSorted (sorter, &c)];
1288}
1289
1290bool AudioProcessorGraph::isConnected (const uint32 possibleSourceNodeId,
1291 const uint32 possibleDestNodeId) const
1292{
1293 for (int i = connections.size(); --i >= 0;)
1294 {
1295 const Connection* const c = connections.getUnchecked(i);
1296
1297 if (c->sourceNodeId == possibleSourceNodeId
1298 && c->destNodeId == possibleDestNodeId)
1299 {
1300 return true;
1301 }
1302 }
1303
1304 return false;
1305}
1306
1308 const uint32 sourceNodeId,
1309 const uint sourceChannelIndex,
1310 const uint32 destNodeId,
1311 const uint destChannelIndex) const
1312{
1313 if (sourceNodeId == destNodeId)
1314 return false;
1315
1316 const Node* const source = getNodeForId (sourceNodeId);
1317
1318 if (source == nullptr
1319 || (ct != ChannelTypeMIDI && sourceChannelIndex >= source->processor->getTotalNumOutputChannels(ct))
1320 || (ct == ChannelTypeMIDI && ! source->processor->producesMidi()))
1321 return false;
1322
1323 const Node* const dest = getNodeForId (destNodeId);
1324
1325 if (dest == nullptr
1326 || (ct != ChannelTypeMIDI && destChannelIndex >= dest->processor->getTotalNumInputChannels(ct))
1327 || (ct == ChannelTypeMIDI && ! dest->processor->acceptsMidi()))
1328 return false;
1329
1330 return getConnectionBetween (ct,
1331 sourceNodeId, sourceChannelIndex,
1332 destNodeId, destChannelIndex) == nullptr;
1333}
1334
1336 const uint32 sourceNodeId,
1337 const uint sourceChannelIndex,
1338 const uint32 destNodeId,
1339 const uint destChannelIndex)
1340{
1341 if (! canConnect (ct, sourceNodeId, sourceChannelIndex, destNodeId, destChannelIndex))
1342 return false;
1343
1345 connections.addSorted (sorter, new Connection (ct,
1346 sourceNodeId, sourceChannelIndex,
1347 destNodeId, destChannelIndex));
1348
1349 if (isPrepared)
1350 needsReorder = true;
1351
1352 return true;
1353}
1354
1356{
1357 connections.remove (index);
1358
1359 if (isPrepared)
1360 needsReorder = true;
1361}
1362
1364 const uint32 sourceNodeId, const uint sourceChannelIndex,
1365 const uint32 destNodeId, const uint destChannelIndex)
1366{
1367 bool doneAnything = false;
1368
1369 for (int i = connections.size(); --i >= 0;)
1370 {
1371 const Connection* const c = connections.getUnchecked(i);
1372
1373 if (c->channelType == ct
1374 && c->sourceNodeId == sourceNodeId
1375 && c->destNodeId == destNodeId
1376 && c->sourceChannelIndex == sourceChannelIndex
1377 && c->destChannelIndex == destChannelIndex)
1378 {
1380 doneAnything = true;
1381 }
1382 }
1383
1384 return doneAnything;
1385}
1386
1388{
1389 bool doneAnything = false;
1390
1391 for (int i = connections.size(); --i >= 0;)
1392 {
1393 const Connection* const c = connections.getUnchecked(i);
1394
1395 if (c->sourceNodeId == nodeId || c->destNodeId == nodeId)
1396 {
1398 doneAnything = true;
1399 }
1400 }
1401
1402 return doneAnything;
1403}
1404
1406{
1407 CARLA_SAFE_ASSERT_RETURN (c != nullptr, false);
1408
1409 const Node* const source = getNodeForId (c->sourceNodeId);
1410 const Node* const dest = getNodeForId (c->destNodeId);
1411
1412 return source != nullptr
1413 && dest != nullptr
1414 && (c->channelType != ChannelTypeMIDI ? (c->sourceChannelIndex < source->processor->getTotalNumOutputChannels(c->channelType))
1415 : source->processor->producesMidi())
1416 && (c->channelType != ChannelTypeMIDI ? (c->destChannelIndex < dest->processor->getTotalNumInputChannels(c->channelType))
1417 : dest->processor->acceptsMidi());
1418}
1419
1421{
1422 bool doneAnything = false;
1423
1424 for (int i = connections.size(); --i >= 0;)
1425 {
1426 if (! isConnectionLegal (connections.getUnchecked(i)))
1427 {
1429 doneAnything = true;
1430 }
1431 }
1432
1433 return doneAnything;
1434}
1435
1436//==============================================================================
1438{
1439 for (int i = ops.size(); --i >= 0;)
1441}
1442
1444{
1445 Array<void*> oldOps;
1446
1447 {
1448 const CarlaRecursiveMutexLocker cml (getCallbackLock());
1449 renderingOps.swapWith (oldOps);
1450 }
1451
1452 deleteRenderOpArray (oldOps);
1453}
1454
1455bool AudioProcessorGraph::isAnInputTo (const uint32 possibleInputId,
1456 const uint32 possibleDestinationId,
1457 const int recursionCheck) const
1458{
1459 if (recursionCheck > 0)
1460 {
1461 for (int i = connections.size(); --i >= 0;)
1462 {
1463 const AudioProcessorGraph::Connection* const c = connections.getUnchecked (i);
1464
1465 if (c->destNodeId == possibleDestinationId
1466 && (c->sourceNodeId == possibleInputId
1467 || isAnInputTo (possibleInputId, c->sourceNodeId, recursionCheck - 1)))
1468 return true;
1469 }
1470 }
1471
1472 return false;
1473}
1474
1476{
1477 Array<void*> newRenderingOps;
1478 int numAudioRenderingBuffersNeeded = 2;
1479 int numCVRenderingBuffersNeeded = 0;
1480 int numMidiBuffersNeeded = 1;
1481
1482 {
1483 const CarlaRecursiveMutexLocker cml (reorderMutex);
1484
1485 Array<Node*> orderedNodes;
1486
1487 {
1489
1490 for (int i = 0; i < nodes.size(); ++i)
1491 {
1492 Node* const node = nodes.getUnchecked(i);
1493
1494 node->prepare (getSampleRate(), getBlockSize(), this);
1495
1496 int j = 0;
1497 for (; j < orderedNodes.size(); ++j)
1498 if (table.isAnInputTo (node->nodeId, ((Node*) orderedNodes.getUnchecked(j))->nodeId))
1499 break;
1500
1501 orderedNodes.insert (j, node);
1502 }
1503 }
1504
1505 GraphRenderingOps::RenderingOpSequenceCalculator calculator (*this, orderedNodes, newRenderingOps);
1506
1507 numAudioRenderingBuffersNeeded = calculator.getNumAudioBuffersNeeded();
1508 numCVRenderingBuffersNeeded = calculator.getNumCVBuffersNeeded();
1509 numMidiBuffersNeeded = calculator.getNumMidiBuffersNeeded();
1510 }
1511
1512 {
1513 // swap over to the new rendering sequence..
1514 const CarlaRecursiveMutexLocker cml (getCallbackLock());
1515
1516 audioAndCVBuffers->setRenderingBufferSize (numAudioRenderingBuffersNeeded,
1517 numCVRenderingBuffersNeeded,
1518 getBlockSize());
1519
1520 for (int i = static_cast<int>(midiBuffers.size()); --i >= 0;)
1521 midiBuffers.getUnchecked(i)->clear();
1522
1523 while (static_cast<int>(midiBuffers.size()) < numMidiBuffersNeeded)
1524 midiBuffers.add (new MidiBuffer());
1525
1526 renderingOps.swapWith (newRenderingOps);
1527 }
1528
1529 // delete the old ones..
1530 deleteRenderOpArray (newRenderingOps);
1531}
1532
1533//==============================================================================
1534void AudioProcessorGraph::prepareToPlay (double sampleRate, int estimatedSamplesPerBlock)
1535{
1536 setRateAndBufferSizeDetails(sampleRate, estimatedSamplesPerBlock);
1537
1540 estimatedSamplesPerBlock);
1541
1542 currentMidiInputBuffer = nullptr;
1544
1547
1548 isPrepared = true;
1549}
1550
1552{
1553 isPrepared = false;
1554
1555 for (int i = 0; i < nodes.size(); ++i)
1556 nodes.getUnchecked(i)->unprepare();
1557
1558 audioAndCVBuffers->release();
1559 midiBuffers.clear();
1560
1561 currentMidiInputBuffer = nullptr;
1563}
1564
1566{
1567 const CarlaRecursiveMutexLocker cml (getCallbackLock());
1568
1569 for (int i = 0; i < nodes.size(); ++i)
1570 nodes.getUnchecked(i)->getProcessor()->reset();
1571}
1572
1573void AudioProcessorGraph::setNonRealtime (bool isProcessingNonRealtime) noexcept
1574{
1575 const CarlaRecursiveMutexLocker cml (getCallbackLock());
1576
1577 AudioProcessor::setNonRealtime (isProcessingNonRealtime);
1578
1579 for (int i = 0; i < nodes.size(); ++i)
1580 nodes.getUnchecked(i)->getProcessor()->setNonRealtime (isProcessingNonRealtime);
1581}
1582
1583/*
1584void AudioProcessorGraph::processAudio (AudioSampleBuffer& audioBuffer, MidiBuffer& midiMessages)
1585{
1586 AudioSampleBuffer*& currentAudioInputBuffer = audioAndCVBuffers->currentAudioInputBuffer;
1587 AudioSampleBuffer& currentAudioOutputBuffer = audioAndCVBuffers->currentAudioOutputBuffer;
1588 AudioSampleBuffer& renderingAudioBuffers = audioAndCVBuffers->renderingAudioBuffers;
1589 AudioSampleBuffer& renderingCVBuffers = audioAndCVBuffers->renderingCVBuffers;
1590
1591 const int numSamples = audioBuffer.getNumSamples();
1592
1593 if (! audioAndCVBuffers->currentAudioOutputBuffer.setSizeRT(numSamples))
1594 return;
1595 if (! audioAndCVBuffers->renderingAudioBuffers.setSizeRT(numSamples))
1596 return;
1597 if (! audioAndCVBuffers->renderingCVBuffers.setSizeRT(numSamples))
1598 return;
1599
1600 currentAudioInputBuffer = &audioBuffer;
1601 currentAudioOutputBuffer.clear();
1602 currentMidiInputBuffer = &midiMessages;
1603 currentMidiOutputBuffer.clear();
1604
1605 for (int i = 0; i < renderingOps.size(); ++i)
1606 {
1607 GraphRenderingOps::AudioGraphRenderingOpBase* const op
1608 = (GraphRenderingOps::AudioGraphRenderingOpBase*) renderingOps.getUnchecked(i);
1609
1610 op->perform (renderingAudioBuffers, renderingCVBuffers, midiBuffers, numSamples);
1611 }
1612
1613 for (uint32_t i = 0; i < audioBuffer.getNumChannels(); ++i)
1614 audioBuffer.copyFrom (i, 0, currentAudioOutputBuffer, i, 0, numSamples);
1615
1616 midiMessages.clear();
1617 midiMessages.addEvents (currentMidiOutputBuffer, 0, audioBuffer.getNumSamples(), 0);
1618}
1619*/
1620
1622 const AudioSampleBuffer& cvInBuffer,
1623 AudioSampleBuffer& cvOutBuffer,
1624 MidiBuffer& midiMessages)
1625{
1626 AudioSampleBuffer*& currentAudioInputBuffer = audioAndCVBuffers->currentAudioInputBuffer;
1627 const AudioSampleBuffer*& currentCVInputBuffer = audioAndCVBuffers->currentCVInputBuffer;
1628 AudioSampleBuffer& currentAudioOutputBuffer = audioAndCVBuffers->currentAudioOutputBuffer;
1629 AudioSampleBuffer& currentCVOutputBuffer = audioAndCVBuffers->currentCVOutputBuffer;
1630 AudioSampleBuffer& renderingAudioBuffers = audioAndCVBuffers->renderingAudioBuffers;
1631 AudioSampleBuffer& renderingCVBuffers = audioAndCVBuffers->renderingCVBuffers;
1632
1633 const int numSamples = audioBuffer.getNumSamples();
1634
1635 if (! audioAndCVBuffers->currentAudioOutputBuffer.setSizeRT(numSamples))
1636 return;
1637 if (! audioAndCVBuffers->currentCVOutputBuffer.setSizeRT(numSamples))
1638 return;
1639 if (! audioAndCVBuffers->renderingAudioBuffers.setSizeRT(numSamples))
1640 return;
1641 if (! audioAndCVBuffers->renderingCVBuffers.setSizeRT(numSamples))
1642 return;
1643
1644 currentAudioInputBuffer = &audioBuffer;
1645 currentCVInputBuffer = &cvInBuffer;
1646 currentMidiInputBuffer = &midiMessages;
1647 currentAudioOutputBuffer.clear();
1648 currentCVOutputBuffer.clear();
1650
1651 for (int i = 0; i < renderingOps.size(); ++i)
1652 {
1655
1656 op->perform (renderingAudioBuffers, renderingCVBuffers, midiBuffers, numSamples);
1657 }
1658
1659 for (uint32_t i = 0; i < audioBuffer.getNumChannels(); ++i)
1660 audioBuffer.copyFrom (i, 0, currentAudioOutputBuffer, i, 0, numSamples);
1661
1662 for (uint32_t i = 0; i < cvOutBuffer.getNumChannels(); ++i)
1663 cvOutBuffer.copyFrom (i, 0, currentCVOutputBuffer, i, 0, numSamples);
1664
1665 midiMessages.clear();
1666 midiMessages.addEvents (currentMidiOutputBuffer, 0, audioBuffer.getNumSamples(), 0);
1667}
1668
1669bool AudioProcessorGraph::acceptsMidi() const { return true; }
1670bool AudioProcessorGraph::producesMidi() const { return true; }
1671
1672/*
1673void AudioProcessorGraph::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
1674{
1675 processAudio (buffer, midiMessages);
1676}
1677*/
1678
1680 const AudioSampleBuffer& cvInBuffer,
1681 AudioSampleBuffer& cvOutBuffer,
1682 MidiBuffer& midiMessages)
1683{
1684 processAudioAndCV (audioBuffer, cvInBuffer, cvOutBuffer, midiMessages);
1685}
1686
1688{
1689 if (needsReorder)
1690 {
1691 needsReorder = false;
1693 }
1694}
1695
1696const CarlaRecursiveMutex& AudioProcessorGraph::getReorderMutex() const
1697{
1698 return reorderMutex;
1699}
1700
1701//==============================================================================
1706
1710
1712{
1713 switch (type)
1714 {
1715 case audioOutputNode: return "Audio Output";
1716 case audioInputNode: return "Audio Input";
1717 case cvOutputNode: return "CV Output";
1718 case cvInputNode: return "CV Input";
1719 case midiOutputNode: return "Midi Output";
1720 case midiInputNode: return "Midi Input";
1721 default: break;
1722 }
1723
1724 return String();
1725}
1726
1731
1735
1737 const AudioSampleBuffer& cvInBuffer,
1738 AudioSampleBuffer& cvOutBuffer,
1739 MidiBuffer& midiMessages)
1740{
1741 CARLA_SAFE_ASSERT_RETURN(graph != nullptr,);
1742
1743 switch (type)
1744 {
1745 case audioOutputNode:
1746 {
1747 AudioSampleBuffer& currentAudioOutputBuffer =
1748 graph->audioAndCVBuffers->currentAudioOutputBuffer;
1749
1750 for (int i = jmin (currentAudioOutputBuffer.getNumChannels(),
1751 audioBuffer.getNumChannels()); --i >= 0;)
1752 {
1753 currentAudioOutputBuffer.addFrom (i, 0, audioBuffer, i, 0, audioBuffer.getNumSamples());
1754 }
1755
1756 break;
1757 }
1758
1759 case audioInputNode:
1760 {
1761 AudioSampleBuffer*& currentAudioInputBuffer =
1762 graph->audioAndCVBuffers->currentAudioInputBuffer;
1763
1764 for (int i = jmin (currentAudioInputBuffer->getNumChannels(),
1765 audioBuffer.getNumChannels()); --i >= 0;)
1766 {
1767 audioBuffer.copyFrom (i, 0, *currentAudioInputBuffer, i, 0, audioBuffer.getNumSamples());
1768 }
1769
1770 break;
1771 }
1772
1773 case cvOutputNode:
1774 {
1775 AudioSampleBuffer& currentCVOutputBuffer =
1776 graph->audioAndCVBuffers->currentCVOutputBuffer;
1777
1778 for (int i = jmin (currentCVOutputBuffer.getNumChannels(),
1779 cvInBuffer.getNumChannels()); --i >= 0;)
1780 {
1781 currentCVOutputBuffer.addFrom (i, 0, cvInBuffer, i, 0, cvInBuffer.getNumSamples());
1782 }
1783
1784 break;
1785 }
1786
1787 case cvInputNode:
1788 {
1789 const AudioSampleBuffer*& currentCVInputBuffer =
1790 graph->audioAndCVBuffers->currentCVInputBuffer;
1791
1792 for (int i = jmin (currentCVInputBuffer->getNumChannels(),
1793 cvOutBuffer.getNumChannels()); --i >= 0;)
1794 {
1795 cvOutBuffer.copyFrom (i, 0, *currentCVInputBuffer, i, 0, cvOutBuffer.getNumSamples());
1796 }
1797
1798 break;
1799 }
1800
1801 case midiOutputNode:
1802 graph->currentMidiOutputBuffer.addEvents (midiMessages, 0, audioBuffer.getNumSamples(), 0);
1803 break;
1804
1805 case midiInputNode:
1806 midiMessages.addEvents (*graph->currentMidiInputBuffer, 0, audioBuffer.getNumSamples(), 0);
1807 break;
1808
1809 default:
1810 break;
1811 }
1812}
1813
1815 const AudioSampleBuffer& cvInBuffer,
1816 AudioSampleBuffer& cvOutBuffer,
1817 MidiBuffer& midiMessages)
1818{
1819 processAudioAndCV (audioBuffer, cvInBuffer, cvOutBuffer, midiMessages);
1820}
1821
1826
1831
1836
1841
1843{
1844 graph = newGraph;
1845
1846 if (graph != nullptr)
1847 {
1849 ? graph->getTotalNumOutputChannels(AudioProcessor::ChannelTypeAudio)
1850 : 0,
1852 ? graph->getTotalNumInputChannels(AudioProcessor::ChannelTypeAudio)
1853 : 0,
1855 ? graph->getTotalNumOutputChannels(AudioProcessor::ChannelTypeCV)
1856 : 0,
1857 type == cvInputNode
1858 ? graph->getTotalNumInputChannels(AudioProcessor::ChannelTypeCV)
1859 : 0,
1861 ? graph->getTotalNumOutputChannels(AudioProcessor::ChannelTypeMIDI)
1862 : 0,
1864 ? graph->getTotalNumInputChannels(AudioProcessor::ChannelTypeMIDI)
1865 : 0,
1866 getSampleRate(),
1867 getBlockSize());
1868 }
1869}
1870
1871}
#define CARLA_SAFE_ASSERT_CONTINUE(cond)
Definition CarlaDefines.h:189
#define CARLA_SAFE_ASSERT_RETURN(cond, ret)
Definition CarlaDefines.h:190
unsigned int uint
Definition CarlaDefines.h:327
#define CARLA_SAFE_ASSERT_BREAK(cond)
Definition CarlaDefines.h:188
#define CARLA_SAFE_ASSERT(cond)
Definition CarlaDefines.h:182
#define CARLA_DECLARE_NON_COPYABLE(ClassName)
Definition CarlaDefines.h:242
#define noexcept
Definition DistrhoDefines.h:72
#define nullptr
Definition DistrhoDefines.h:75
Definition Array.h:57
bool add(const ElementType &newElement) noexcept
Definition Array.h:354
int size() const noexcept
Definition Array.h:187
ElementType getUnchecked(const int index) const
Definition Array.h:228
bool insert(int indexToInsertAt, ParameterType newElement) noexcept
Definition Array.h:375
ElementType getFirst() const
Definition Array.h:253
Definition AudioProcessorGraph.h:306
bool isInput() const noexcept
Definition AudioProcessorGraph.cpp:1832
bool acceptsMidi() const override
Definition AudioProcessorGraph.cpp:1822
IODeviceType
Definition AudioProcessorGraph.h:311
@ audioInputNode
Definition AudioProcessorGraph.h:312
@ cvOutputNode
Definition AudioProcessorGraph.h:324
@ midiInputNode
Definition AudioProcessorGraph.h:318
@ midiOutputNode
Definition AudioProcessorGraph.h:321
@ cvInputNode
Definition AudioProcessorGraph.h:324
@ audioOutputNode
Definition AudioProcessorGraph.h:315
bool producesMidi() const override
Definition AudioProcessorGraph.cpp:1827
void prepareToPlay(double newSampleRate, int estimatedSamplesPerBlock) override
Definition AudioProcessorGraph.cpp:1727
~AudioGraphIOProcessor()
Definition AudioProcessorGraph.cpp:1707
void setParentGraph(AudioProcessorGraph *)
Definition AudioProcessorGraph.cpp:1842
AudioGraphIOProcessor(const IODeviceType type)
Definition AudioProcessorGraph.cpp:1702
void releaseResources() override
Definition AudioProcessorGraph.cpp:1732
const IODeviceType type
Definition AudioProcessorGraph.h:359
const String getName() const override
Definition AudioProcessorGraph.cpp:1711
bool isOutput() const noexcept
Definition AudioProcessorGraph.cpp:1837
AudioProcessorGraph * graph
Definition AudioProcessorGraph.h:360
void processBlockWithCV(AudioSampleBuffer &audioBuffer, const AudioSampleBuffer &cvInBuffer, AudioSampleBuffer &cvOutBuffer, MidiBuffer &midiMessages) override
Definition AudioProcessorGraph.cpp:1814
void processAudioAndCV(AudioSampleBuffer &audioBuffer, const AudioSampleBuffer &cvInBuffer, AudioSampleBuffer &cvOutBuffer, MidiBuffer &midiMessages)
Definition AudioProcessorGraph.cpp:1736
Definition AudioProcessorGraph.h:63
ReferenceCountedObjectPtr< Node > Ptr
Definition AudioProcessorGraph.h:109
Node(uint32 nodeId, AudioProcessor *) noexcept
Definition AudioProcessorGraph.cpp:1105
void setParentGraph(AudioProcessorGraph *) const
Definition AudioProcessorGraph.cpp:1133
AudioProcessor * getProcessor() const noexcept
Definition AudioProcessorGraph.h:72
const CarlaScopedPointer< AudioProcessor > processor
Definition AudioProcessorGraph.h:115
bool isPrepared
Definition AudioProcessorGraph.h:116
void unprepare()
Definition AudioProcessorGraph.cpp:1124
const uint32 nodeId
Definition AudioProcessorGraph.h:69
friend class AudioProcessorGraph
Definition AudioProcessorGraph.h:113
void prepare(double newSampleRate, int newBlockSize, AudioProcessorGraph *)
Definition AudioProcessorGraph.cpp:1111
Definition AudioProcessorGraph.h:46
AudioProcessorGraph()
Definition AudioProcessorGraph.cpp:1184
const Connection * getConnectionBetween(ChannelType channelType, uint32 sourceNodeId, uint sourceChannelIndex, uint32 destNodeId, uint destChannelIndex) const
Definition AudioProcessorGraph.cpp:1279
OwnedArray< Connection > connections
Definition AudioProcessorGraph.h:401
ReferenceCountedArray< Node > nodes
Definition AudioProcessorGraph.h:400
Array< void * > renderingOps
Definition AudioProcessorGraph.h:404
void setNonRealtime(bool) noexcept override
Definition AudioProcessorGraph.cpp:1573
MidiBuffer * currentMidiInputBuffer
Definition AudioProcessorGraph.h:410
void reorderNowIfNeeded()
Definition AudioProcessorGraph.cpp:1687
bool canConnect(ChannelType channelType, uint32 sourceNodeId, uint sourceChannelIndex, uint32 destNodeId, uint destChannelIndex) const
Definition AudioProcessorGraph.cpp:1307
void reset() override
Definition AudioProcessorGraph.cpp:1565
const CarlaRecursiveMutex & getReorderMutex() const
Definition AudioProcessorGraph.cpp:1696
bool addConnection(ChannelType channelType, uint32 sourceNodeId, uint sourceChannelIndex, uint32 destNodeId, uint destChannelIndex)
Definition AudioProcessorGraph.cpp:1335
bool removeNode(uint32 nodeId)
Definition AudioProcessorGraph.cpp:1251
void buildRenderingSequence()
Definition AudioProcessorGraph.cpp:1475
~AudioProcessorGraph()
Definition AudioProcessorGraph.cpp:1190
MidiBuffer currentMidiOutputBuffer
Definition AudioProcessorGraph.h:411
void prepareToPlay(double, int) override
Definition AudioProcessorGraph.cpp:1534
void processAudioAndCV(AudioSampleBuffer &audioBuffer, const AudioSampleBuffer &cvInBuffer, AudioSampleBuffer &cvOutBuffer, MidiBuffer &midiMessages)
Definition AudioProcessorGraph.cpp:1621
Node * getNodeForId(const uint32 nodeId) const
Definition AudioProcessorGraph.cpp:1209
uint32 lastNodeId
Definition AudioProcessorGraph.h:402
bool needsReorder
Definition AudioProcessorGraph.h:413
const String getName() const override
Definition AudioProcessorGraph.cpp:1196
OwnedArray< MidiBuffer > midiBuffers
Definition AudioProcessorGraph.h:403
void removeConnection(int index)
Definition AudioProcessorGraph.cpp:1355
bool isConnected(uint32 possibleSourceNodeId, uint32 possibleDestNodeId) const
Definition AudioProcessorGraph.cpp:1290
CarlaScopedPointer< AudioProcessorGraphBufferHelpers > audioAndCVBuffers
Definition AudioProcessorGraph.h:408
bool producesMidi() const override
Definition AudioProcessorGraph.cpp:1670
bool acceptsMidi() const override
Definition AudioProcessorGraph.cpp:1669
bool isPrepared
Definition AudioProcessorGraph.h:413
CarlaRecursiveMutex reorderMutex
Definition AudioProcessorGraph.h:414
Node * addNode(AudioProcessor *newProcessor, uint32 nodeId=0)
Definition AudioProcessorGraph.cpp:1218
bool removeIllegalConnections()
Definition AudioProcessorGraph.cpp:1420
bool isAnInputTo(uint32 possibleInputId, uint32 possibleDestinationId, int recursionCheck) const
Definition AudioProcessorGraph.cpp:1455
void clear()
Definition AudioProcessorGraph.cpp:1202
bool disconnectNode(uint32 nodeId)
Definition AudioProcessorGraph.cpp:1387
void releaseResources() override
Definition AudioProcessorGraph.cpp:1551
bool isConnectionLegal(const Connection *connection) const
Definition AudioProcessorGraph.cpp:1405
void clearRenderingSequence()
Definition AudioProcessorGraph.cpp:1443
void processBlockWithCV(AudioSampleBuffer &audioBuffer, const AudioSampleBuffer &cvInBuffer, AudioSampleBuffer &cvOutBuffer, MidiBuffer &midiMessages) override
Definition AudioProcessorGraph.cpp:1679
Definition AudioProcessor.h:46
int getBlockSize() const noexcept
Definition AudioProcessor.h:186
double getSampleRate() const noexcept
Definition AudioProcessor.h:175
virtual void setNonRealtime(bool isNonRealtime) noexcept
Definition AudioProcessor.cpp:72
uint getTotalNumOutputChannels(ChannelType t) const noexcept
Definition AudioProcessor.cpp:107
void setPlayConfigDetails(uint numAudioIns, uint numAudioOuts, uint numCVIns, uint numCVOuts, uint numMIDIIns, uint numMIDIOuts, double sampleRate, int blockSize)
Definition AudioProcessor.cpp:47
const CarlaRecursiveMutex & getCallbackLock() const noexcept
Definition AudioProcessor.h:229
int getLatencySamples() const noexcept
Definition AudioProcessor.h:196
uint getTotalNumInputChannels(ChannelType t) const noexcept
Definition AudioProcessor.cpp:92
virtual bool producesMidi() const =0
AudioProcessor()
Definition AudioProcessor.cpp:25
virtual bool acceptsMidi() const =0
ChannelType
Definition AudioProcessor.h:58
@ ChannelTypeCV
Definition AudioProcessor.h:60
@ ChannelTypeMIDI
Definition AudioProcessor.h:61
@ ChannelTypeAudio
Definition AudioProcessor.h:59
void setRateAndBufferSizeDetails(double sampleRate, int blockSize) noexcept
Definition AudioProcessor.cpp:65
Definition AudioSampleBuffer.h:42
uint32_t getNumSamples() const noexcept
Definition AudioSampleBuffer.h:217
uint32_t getNumChannels() const noexcept
Definition AudioSampleBuffer.h:212
void addFrom(const uint32_t destChannel, const uint32_t destStartSample, const AudioSampleBuffer &source, const uint32_t sourceChannel, const uint32_t sourceStartSample, const uint32_t numSamples, const float gainToApplyToSource=1.0f) noexcept
Definition AudioSampleBuffer.h:466
void copyFrom(const uint32_t destChannel, const uint32_t destStartSample, const AudioSampleBuffer &source, const uint32_t sourceChannel, const uint32_t sourceStartSample, const uint32_t numSamples) noexcept
Definition AudioSampleBuffer.h:560
float * getWritePointer(const uint32_t channelNumber) noexcept
Definition AudioSampleBuffer.h:254
void clear() noexcept
Definition AudioSampleBuffer.h:397
Definition AudioProcessorGraph.cpp:965
bool isAnInputToRecursive(const uint32 possibleInputId, const uint32 possibleDestinationId, int recursionCheck) const noexcept
Definition AudioProcessorGraph.cpp:1006
Entry * findEntry(const uint32 destNodeId, int &insertIndex) const noexcept
Definition AudioProcessorGraph.cpp:1030
OwnedArray< Entry > entries
Definition AudioProcessorGraph.cpp:1004
bool isAnInputTo(const uint32 possibleInputId, const uint32 possibleDestinationId) const noexcept
Definition AudioProcessorGraph.cpp:986
ConnectionLookupTable(const OwnedArray< AudioProcessorGraph::Connection > &connections)
Definition AudioProcessorGraph.cpp:967
Definition HeapBlock.h:77
Definition MidiBuffer.h:48
void addEvents(const MidiBuffer &otherBuffer, int startSample, int numSamples, int sampleDeltaToAdd)
Definition MidiBuffer.cpp:141
void clear() noexcept
Definition MidiBuffer.cpp:106
Definition OwnedArray.h:57
ObjectClass * getUnchecked(const int index) const noexcept
Definition OwnedArray.h:136
size_t size() const noexcept
Definition OwnedArray.h:101
Definition SortedSet.h:57
bool contains(const ElementType &elementToLookFor) const noexcept
Definition SortedSet.h:255
ElementType getUnchecked(const int index) const noexcept
Definition SortedSet.h:165
bool add(const ElementType &newElement) noexcept
Definition SortedSet.h:272
int size() const noexcept
Definition SortedSet.h:130
Definition String.h:48
register unsigned j
Definition inflate.c:1576
int g
Definition inflate.c:1573
register unsigned i
Definition inflate.c:1575
virtual ASIOError start()=0
JSAMPIMAGE data
Definition jpeglib.h:945
#define wassert(expression)
unsigned int uint32_t
Definition mid.cpp:100
Definition AudioProcessorGraph.cpp:28
Definition AudioSampleBuffer.h:33
unsigned int uint32
Definition water.h:98
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
static void deleteRenderOpArray(Array< void * > &ops)
Definition AudioProcessorGraph.cpp:1437
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
#define false
Definition ordinals.h:83
const AudioSampleBuffer * currentCVInputBuffer
Definition AudioProcessorGraph.cpp:1178
void prepareInOutBuffers(int newNumAudioChannels, int newNumCVChannels, int newNumSamples) noexcept
Definition AudioProcessorGraph.cpp:1167
AudioSampleBuffer renderingCVBuffers
Definition AudioProcessorGraph.cpp:1176
AudioSampleBuffer renderingAudioBuffers
Definition AudioProcessorGraph.cpp:1175
AudioSampleBuffer * currentAudioInputBuffer
Definition AudioProcessorGraph.cpp:1177
AudioSampleBuffer currentCVOutputBuffer
Definition AudioProcessorGraph.cpp:1180
void setRenderingBufferSize(int newNumAudioChannels, int newNumCVChannels, int newNumSamples) noexcept
Definition AudioProcessorGraph.cpp:1147
void release() noexcept
Definition AudioProcessorGraph.cpp:1156
AudioProcessorGraphBufferHelpers() noexcept
Definition AudioProcessorGraph.cpp:1143
AudioSampleBuffer currentAudioOutputBuffer
Definition AudioProcessorGraph.cpp:1179
Definition AudioProcessorGraph.h:133
uint sourceChannelIndex
Definition AudioProcessorGraph.h:156
ChannelType channelType
Definition AudioProcessorGraph.h:142
Connection(ChannelType channelType, uint32 sourceNodeId, uint sourceChannelIndex, uint32 destNodeId, uint destChannelIndex) noexcept
Definition AudioProcessorGraph.cpp:1095
uint destChannelIndex
Definition AudioProcessorGraph.h:170
uint32 destNodeId
Definition AudioProcessorGraph.h:161
uint32 sourceNodeId
Definition AudioProcessorGraph.h:147
Definition AudioProcessorGraph.cpp:105
AddChannelOp(const int srcChan, const int dstChan, const bool cv) noexcept
Definition AudioProcessorGraph.cpp:106
const bool isCV
Definition AudioProcessorGraph.cpp:121
const int dstChannelNum
Definition AudioProcessorGraph.cpp:120
void perform(AudioSampleBuffer &sharedAudioBufferChans, AudioSampleBuffer &sharedCVBufferChans, const OwnedArray< MidiBuffer > &, const int numSamples)
Definition AudioProcessorGraph.cpp:109
const int srcChannelNum
Definition AudioProcessorGraph.cpp:120
Definition AudioProcessorGraph.cpp:164
void perform(AudioSampleBuffer &, AudioSampleBuffer &, const OwnedArray< MidiBuffer > &sharedMidiBuffers, const int numSamples)
Definition AudioProcessorGraph.cpp:169
const int srcBufferNum
Definition AudioProcessorGraph.cpp:177
AddMidiBufferOp(const int srcBuffer, const int dstBuffer)
Definition AudioProcessorGraph.cpp:165
const int dstBufferNum
Definition AudioProcessorGraph.cpp:177
Definition AudioProcessorGraph.cpp:31
AudioGraphRenderingOpBase() noexcept
Definition AudioProcessorGraph.cpp:32
virtual void perform(AudioSampleBuffer &sharedAudioBufferChans, AudioSampleBuffer &sharedCVBufferChans, const OwnedArray< MidiBuffer > &sharedMidiBuffers, const int numSamples)=0
virtual ~AudioGraphRenderingOpBase()
Definition AudioProcessorGraph.cpp:33
Definition AudioProcessorGraph.cpp:44
void perform(AudioSampleBuffer &sharedAudioBufferChans, AudioSampleBuffer &sharedCVBufferChans, const OwnedArray< MidiBuffer > &sharedMidiBuffers, const int numSamples) override
Definition AudioProcessorGraph.cpp:45
Definition AudioProcessorGraph.cpp:59
ClearChannelOp(const int channel, const bool cv) noexcept
Definition AudioProcessorGraph.cpp:60
const int channelNum
Definition AudioProcessorGraph.cpp:74
void perform(AudioSampleBuffer &sharedAudioBufferChans, AudioSampleBuffer &sharedCVBufferChans, const OwnedArray< MidiBuffer > &, const int numSamples)
Definition AudioProcessorGraph.cpp:63
const bool isCV
Definition AudioProcessorGraph.cpp:75
Definition AudioProcessorGraph.cpp:128
ClearMidiBufferOp(const int buffer) noexcept
Definition AudioProcessorGraph.cpp:129
const int bufferNum
Definition AudioProcessorGraph.cpp:138
void perform(AudioSampleBuffer &, AudioSampleBuffer &, const OwnedArray< MidiBuffer > &sharedMidiBuffers, const int)
Definition AudioProcessorGraph.cpp:131
Definition AudioProcessorGraph.cpp:995
const uint32 destNodeId
Definition AudioProcessorGraph.cpp:998
Entry(const uint32 destNodeId_) noexcept
Definition AudioProcessorGraph.cpp:996
SortedSet< uint32 > srcNodes
Definition AudioProcessorGraph.cpp:999
Definition AudioProcessorGraph.cpp:1075
static int compareElements(const AudioProcessorGraph::Connection *const first, const AudioProcessorGraph::Connection *const second) noexcept
Definition AudioProcessorGraph.cpp:1076
Definition AudioProcessorGraph.cpp:82
const int dstChannelNum
Definition AudioProcessorGraph.cpp:97
void perform(AudioSampleBuffer &sharedAudioBufferChans, AudioSampleBuffer &sharedCVBufferChans, const OwnedArray< MidiBuffer > &, const int numSamples)
Definition AudioProcessorGraph.cpp:86
const int srcChannelNum
Definition AudioProcessorGraph.cpp:97
CopyChannelOp(const int srcChan, const int dstChan, const bool cv) noexcept
Definition AudioProcessorGraph.cpp:83
const bool isCV
Definition AudioProcessorGraph.cpp:98
Definition AudioProcessorGraph.cpp:145
CopyMidiBufferOp(const int srcBuffer, const int dstBuffer) noexcept
Definition AudioProcessorGraph.cpp:146
const int srcBufferNum
Definition AudioProcessorGraph.cpp:157
void perform(AudioSampleBuffer &, AudioSampleBuffer &, const OwnedArray< MidiBuffer > &sharedMidiBuffers, const int)
Definition AudioProcessorGraph.cpp:150
const int dstBufferNum
Definition AudioProcessorGraph.cpp:157
Definition AudioProcessorGraph.cpp:184
void perform(AudioSampleBuffer &sharedAudioBufferChans, AudioSampleBuffer &sharedCVBufferChans, const OwnedArray< MidiBuffer > &, const int numSamples)
Definition AudioProcessorGraph.cpp:194
int writeIndex
Definition AudioProcessorGraph.cpp:217
const bool isCV
Definition AudioProcessorGraph.cpp:218
int readIndex
Definition AudioProcessorGraph.cpp:217
const int bufferSize
Definition AudioProcessorGraph.cpp:216
const int channel
Definition AudioProcessorGraph.cpp:216
HeapBlock< float > buffer
Definition AudioProcessorGraph.cpp:215
DelayChannelOp(const int chan, const int delaySize, const bool cv)
Definition AudioProcessorGraph.cpp:185
Definition AudioProcessorGraph.cpp:225
const uint totalCVIns
Definition AudioProcessorGraph.cpp:305
const AudioProcessorGraph::Node::Ptr node
Definition AudioProcessorGraph.cpp:293
AudioProcessor *const processor
Definition AudioProcessorGraph.cpp:294
Array< uint > cvOutChannelsToUse
Definition AudioProcessorGraph.cpp:299
Array< uint > audioChannelsToUse
Definition AudioProcessorGraph.cpp:297
AudioSampleBuffer tempBuffer
Definition AudioProcessorGraph.cpp:303
const uint totalCVOuts
Definition AudioProcessorGraph.cpp:306
HeapBlock< float * > audioChannels
Definition AudioProcessorGraph.cpp:300
Array< uint > cvInChannelsToUse
Definition AudioProcessorGraph.cpp:298
HeapBlock< float * > cvInChannels
Definition AudioProcessorGraph.cpp:301
HeapBlock< float * > cvOutChannels
Definition AudioProcessorGraph.cpp:302
void callProcess(AudioSampleBuffer &audioBuffer, AudioSampleBuffer &cvInBuffer, AudioSampleBuffer &cvOutBuffer, MidiBuffer &midiMessages)
Definition AudioProcessorGraph.cpp:285
void perform(AudioSampleBuffer &sharedAudioBufferChans, AudioSampleBuffer &sharedCVBufferChans, const OwnedArray< MidiBuffer > &sharedMidiBuffers, const int numSamples)
Definition AudioProcessorGraph.cpp:250
const uint totalAudioChans
Definition AudioProcessorGraph.cpp:304
const int midiBufferToUse
Definition AudioProcessorGraph.cpp:307
ProcessBufferOp(const AudioProcessorGraph::Node::Ptr &n, const Array< uint > &audioChannelsUsed, const uint totalNumChans, const Array< uint > &cvInChannelsUsed, const Array< uint > &cvOutChannelsUsed, const int midiBuffer)
Definition AudioProcessorGraph.cpp:226
Definition AudioProcessorGraph.cpp:317
Array< uint > cvChannels
Definition AudioProcessorGraph.cpp:350
int getNumAudioBuffersNeeded() const noexcept
Definition AudioProcessorGraph.cpp:342
static bool isNodeBusy(uint32 nodeID) noexcept
Definition AudioProcessorGraph.cpp:355
int getFreeBuffer(const AudioProcessor::ChannelType channelType)
Definition AudioProcessorGraph.cpp:814
Array< uint > audioChannels
Definition AudioProcessorGraph.cpp:350
void markAnyUnusedBuffersAsFree(const int stepIndex)
Definition AudioProcessorGraph.cpp:883
RenderingOpSequenceCalculator(AudioProcessorGraph &g, const Array< AudioProcessorGraph::Node * > &nodes, Array< void * > &renderingOps)
Definition AudioProcessorGraph.cpp:318
int getBufferContaining(const AudioProcessor::ChannelType channelType, const uint32 nodeId, const uint outputChannel) const noexcept
Definition AudioProcessorGraph.cpp:853
Array< uint32 > nodeDelayIDs
Definition AudioProcessorGraph.cpp:357
void markBufferAsContaining(const AudioProcessor::ChannelType channelType, int bufferNum, uint32 nodeId, int outputIndex)
Definition AudioProcessorGraph.cpp:935
bool isBufferNeededLater(const AudioProcessor::ChannelType channelType, int stepIndexToSearchFrom, uint inputChannelOfIndexToIgnore, const uint32 nodeId, const uint outputChanIndex) const
Definition AudioProcessorGraph.cpp:911
const Array< AudioProcessorGraph::Node * > & orderedNodes
Definition AudioProcessorGraph.cpp:349
Array< uint32 > audioNodeIds
Definition AudioProcessorGraph.cpp:351
Array< uint32 > cvNodeIds
Definition AudioProcessorGraph.cpp:351
int getNodeDelay(const uint32 nodeID) const
Definition AudioProcessorGraph.cpp:361
int getNumCVBuffersNeeded() const noexcept
Definition AudioProcessorGraph.cpp:343
@ zeroNodeID
Definition AudioProcessorGraph.cpp:353
@ freeNodeID
Definition AudioProcessorGraph.cpp:353
@ anonymousNodeID
Definition AudioProcessorGraph.cpp:353
Array< int > nodeDelays
Definition AudioProcessorGraph.cpp:358
int getReadOnlyEmptyBuffer() const noexcept
Definition AudioProcessorGraph.cpp:848
void createRenderingOpsForNode(AudioProcessorGraph::Node &node, Array< void * > &renderingOps, const int ourRenderingIndex)
Definition AudioProcessorGraph.cpp:394
int getNumMidiBuffersNeeded() const noexcept
Definition AudioProcessorGraph.cpp:344
int totalLatency
Definition AudioProcessorGraph.cpp:359
int getInputLatencyForNode(const uint32 nodeID) const
Definition AudioProcessorGraph.cpp:378
Array< uint32 > midiNodeIds
Definition AudioProcessorGraph.cpp:351
AudioProcessorGraph & graph
Definition AudioProcessorGraph.cpp:348
void setNodeDelay(const uint32 nodeID, const int latency)
Definition AudioProcessorGraph.cpp:363
int n
Definition crypt.c:458
uch * p
Definition crypt.c:594
return c
Definition crypt.c:175
ulg size
Definition extract.c:2350
int result
Definition process.c:1455
#define const
Definition zconf.h:137