11namespace tracktion {
inline namespace engine
16static const double decayTimeAllowance = 5.0;
17static const int secondsPerGroup = 8;
19static inline int timeToGroupIndex (
double t)
noexcept
21 return ((
int) t) / secondsPerGroup;
33 int lastBufferSize = 0;
39 if (editTime.getEnd() >
time.end)
41 auto newLength =
time.end - editTime.getStart();
47 auto amountToSkip =
time.start - editTime.getStart();
64 node->renderAdding (context);
71CombiningAudioNode::CombiningAudioNode() {}
72CombiningAudioNode::~CombiningAudioNode() {}
76 if (inputNode ==
nullptr)
86 info.hasAudio =
false;
88 info.numberOfChannels = 0;
90 inputNode->getAudioNodeProperties (info);
92 hasAudio |= info.hasAudio;
93 hasMidi |= info.hasMidi;
95 maxNumberOfChannels =
std::max (maxNumberOfChannels, info.numberOfChannels);
98 for (i = 0; i < inputs.size(); ++i)
99 if (inputs.getUnchecked(i)->time.start >=
time.getStart())
107 auto start =
std::max (0, timeToGroupIndex (
time.start - (secondsPerGroup / 2 + 2)));
108 auto end =
std::max (0, timeToGroupIndex (
time.end + (secondsPerGroup / 2 + 2)));
110 while (groups.size() <= end)
113 for (i = start; i <= end; ++i)
115 auto g = groups.getUnchecked(i);
118 for (j = 0; j < g->size(); ++j)
119 if (g->getUnchecked(j)->time.start >=
time.start)
127void CombiningAudioNode::clear()
129 inputs.clearQuick (
true);
130 groups.clearQuick (
true);
137 info.hasAudio = hasAudio;
138 info.hasMidi = hasMidi;
139 info.numberOfChannels = maxNumberOfChannels;
142void CombiningAudioNode::visitNodes (
const VisitorFn& v)
146 for (
auto* n : inputs)
147 n->node->visitNodes (v);
152 for (
int i = inputs.size(); --i >= 0;)
154 auto input = inputs.getUnchecked(i);
156 if (! input->node->purgeSubNodes (keepAudio, keepMidi))
158 for (
int j = groups.size(); --j >= 0;)
159 groups.getUnchecked(j)->removeAllInstancesOf (input);
165 return ! inputs.isEmpty();
170 for (
auto* n : inputs)
173 info2.startTime -= n->time.start;
174 n->node->prepareAudioNodeToPlay (info2);
178bool CombiningAudioNode::isReadyToRender()
180 for (
auto* n : inputs)
181 if (! n->node->isReadyToRender())
189 for (
auto* n : inputs)
190 n->node->releaseAudioNodeResources();
195 callRenderAdding (rc);
202 if (hasAudio || hasMidi)
203 invokeSplitRender (rc, *
this);
206void CombiningAudioNode::renderSection (
const AudioRenderContext& rc, legacy::EditTimeRange editTime)
208 if (
auto g = groups[timeToGroupIndex (editTime.getStart())])
212 if (
tan->time.end > editTime.getStart())
214 if (
tan->time.start >= editTime.getEnd())
217 tan->render (rc, editTime);
223void CombiningAudioNode::prepareForNextBlock (
const AudioRenderContext& rc)
225 SCOPED_REALTIME_CHECK
227 auto time = rc.getEditTime().editRange1.getStart();
228 prefetchGroup (rc, time);
230 if (rc.playhead.isLooping() && time > rc.playhead.getLoopTimes().end - 4.0)
231 prefetchGroup (rc, rc.playhead.getLoopTimes().start);
234void CombiningAudioNode::prefetchGroup (
const AudioRenderContext& rc,
const double time)
236 if (
auto g = groups[timeToGroupIndex (time)])
238 tan->node->prepareForNextBlock (rc);
Base class for nodes in an audio playback graph.
bool purgeSubNodes(bool keepAudio, bool keepMidi) override
Tells the node to delete any sub-nodes that don't produce the required type of output.
void addInput(legacy::EditTimeRange time, AudioNode *inputNode)
Adds an input node to be played.
void prepareAudioNodeToPlay(const PlaybackInitialisationInfo &) override
tells the node to initialise itself ready for playing from the given time.
void releaseAudioNodeResources() override
tells the node that play has stopped, and it can free up anything it no longer needs.
static constexpr double maximumLength
The maximum length an Edit can be.
Holds some really basic properties of a node.
Passed into AudioNodes when they are being initialised, to give them useful contextual information th...
int bufferNumSamples
The number of samples to write into the audio buffer.
MidiMessageArray * bufferForMidiMessages
A buffer of MIDI events to process.
int bufferStartSample
The index of the start point in the audio buffer from which data must be written.
void sanityCheck() const
Does a quick check on the bounds of various values in the structure.
double midiBufferOffset
A time offset to add to the timestamp of any events in the MIDI buffer.
legacy::EditTimeRange streamTime
The time window which needs to be rendered into the current block.