11namespace tracktion {
inline namespace engine
16 inline int timeToSample (
int numSamples, TimeRange editTime, TimePosition t)
18 return (
int) (((t - editTime.getStart()) / editTime.getLength() * numSamples) + 0.5);
21 inline void processSection (choc::buffer::ChannelArrayView<float> audio, TimeRange editTime,
24 bool clearExtraSamples)
26 const auto numSamples = (
int) audio.getNumFrames();
28 if (editTime.overlaps (fadeIn) && fadeIn.getLength() > 0s)
31 auto startSamp = timeToSample (numSamples, editTime, fadeIn.getStart());
35 if (clearExtraSamples)
36 audio.getStart ((choc::buffer::FrameCount) startSamp).clear();
40 alpha1 = (editTime.getStart() - fadeIn.getStart()) / fadeIn.getLength();
47 if (editTime.getEnd() >= fadeIn.getEnd())
49 endSamp = timeToSample (numSamples, editTime, fadeIn.getEnd());
55 alpha2 =
std::max (0.0, (editTime.getEnd() - fadeIn.getStart()) / fadeIn.getLength());
58 if (endSamp > startSamp)
60 auto buffer = tracktion::graph::toAudioBuffer (audio);
61 AudioFadeCurve::applyCrossfadeSection (buffer,
62 startSamp, endSamp - startSamp,
69 if (editTime.overlaps (fadeOut) && fadeOut.getLength() > 0s)
72 auto startSamp = timeToSample (numSamples, editTime, fadeOut.getStart());
77 alpha1 = (editTime.getStart() - fadeOut.getStart()) / fadeOut.getLength();
83 if (editTime.getEnd() >= fadeOut.getEnd())
85 endSamp = timeToSample (numSamples, editTime, fadeOut.getEnd());
88 if (clearExtraSamples && endSamp < numSamples)
89 audio.getEnd ((choc::buffer::FrameCount) endSamp);
94 alpha2 = (editTime.getEnd() - fadeOut.getStart()) / fadeOut.getLength();
97 if (endSamp > startSamp)
99 auto buffer = tracktion::graph::toAudioBuffer (audio);
100 AudioFadeCurve::applyCrossfadeSection (buffer,
101 startSamp, endSamp - startSamp,
115 TimeRange in, TimeRange out,
117 bool clearSamplesOutsideFade)
118 : TracktionEngineNode (ps),
122 fadeInType (fadeInType_),
123 fadeOutType (fadeOutType_),
124 clearExtraSamples (clearSamplesOutsideFade)
126 jassert (! (fadeIn.isEmpty() && fadeOut.isEmpty()));
128 setOptimisations ({ tracktion::graph::ClearBuffers::no,
129 tracktion::graph::AllocateAudioBuffer::yes });
135 dynamicOffset = newOffset;
140 auto props = input->getNodeProperties();
148 return { input.get() };
151bool FadeInOutNode::isReadyToProcess()
153 return input->hasProcessed();
158 const auto editTimeRange = getEditTimeRange();
160 auto sourceBuffers = input->getProcessedOutput();
161 auto destAudioBlock = pc.buffers.audio;
162 auto& destMidiBlock = pc.buffers.midi;
163 jassert (sourceBuffers.audio.getSize() == destAudioBlock.getSize());
165 destMidiBlock.copyFrom (sourceBuffers.midi);
167 if (! renderingNeeded (editTimeRange))
170 setAudioOutput (input.get(), sourceBuffers.audio);
175 graph::copyIfNotAliased (destAudioBlock, sourceBuffers.audio);
177 fade_utils::processSection (destAudioBlock, editTimeRange,
178 fadeIn + dynamicOffset, fadeInType,
179 fadeOut + dynamicOffset, fadeOutType,
183bool FadeInOutNode::renderingNeeded (
const TimeRange timelineRange)
185 if (! getPlayHead().isPlaying())
188 return (fadeIn + dynamicOffset).intersects (timelineRange)
189 || (fadeOut + dynamicOffset).intersects (timelineRange)
190 || (clearExtraSamples && (timelineRange.getStart() <= (fadeIn.getStart() + dynamicOffset)
191 || timelineRange.getEnd() >= (fadeOut.getEnd() + dynamicOffset)));
Struct to describe a single iteration of a process call.
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Represents a duration in real-life time.
Type
A enumeration of the curve classes available.
Holds some really basic properties of a node.