11namespace tracktion {
inline namespace engine
14FadeInOutAudioNode::FadeInOutAudioNode (AudioNode* inp,
15 legacy::EditTimeRange in, legacy::EditTimeRange out,
18 bool clearSamplesOutsideFade)
19 : SingleInputAudioNode (inp),
22 fadeInType (fadeInType_),
23 fadeOutType (fadeOutType_),
24 clearExtraSamples (clearSamplesOutsideFade)
26 jassert (! (fadeIn.isEmpty() && fadeOut.isEmpty()));
29FadeInOutAudioNode::~FadeInOutAudioNode()
33int FadeInOutAudioNode::timeToSample (
const AudioRenderContext& rc, legacy::EditTimeRange editTime,
double t)
35 return (
int) (rc.bufferNumSamples * (t - editTime.getStart()) / editTime.getLength() + 0.5);
38void FadeInOutAudioNode::renderSection (
const AudioRenderContext& rc, legacy::EditTimeRange editTime)
40 if (editTime.overlaps (fadeIn) && fadeIn.getLength() > 0.0)
43 auto startSamp = timeToSample (rc, editTime, fadeIn.getStart());
47 if (clearExtraSamples)
48 rc.destBuffer->clear (rc.bufferStartSample, startSamp);
52 alpha1 = (editTime.getStart() - fadeIn.getStart()) / fadeIn.getLength();
59 if (editTime.getEnd() >= fadeIn.getEnd())
61 endSamp = timeToSample (rc, editTime, fadeIn.getEnd());
66 endSamp = rc.bufferNumSamples;
67 alpha2 =
std::max (0.0, (editTime.getEnd() - fadeIn.getStart()) / fadeIn.getLength());
70 if (endSamp > startSamp)
71 AudioFadeCurve::applyCrossfadeSection (*rc.destBuffer,
72 rc.bufferStartSample + startSamp, endSamp - startSamp,
78 if (editTime.overlaps (fadeOut) && fadeOut.getLength() > 0.0)
81 auto startSamp = timeToSample (rc, editTime, fadeOut.getStart());
86 alpha1 = (editTime.getStart() - fadeOut.getStart()) / fadeOut.getLength();
92 if (editTime.getEnd() >= fadeOut.getEnd())
94 endSamp = timeToSample (rc, editTime, fadeOut.getEnd());
97 if (clearExtraSamples && endSamp < rc.bufferNumSamples)
98 rc.destBuffer->clear (rc.bufferStartSample + endSamp,
99 rc.bufferNumSamples - endSamp);
103 endSamp = rc.bufferNumSamples;
104 alpha2 = (editTime.getEnd() - fadeOut.getStart()) / fadeOut.getLength();
107 if (endSamp > startSamp)
108 AudioFadeCurve::applyCrossfadeSection (*rc.destBuffer,
109 rc.bufferStartSample + startSamp, endSamp - startSamp,
116bool FadeInOutAudioNode::renderingNeeded (
const AudioRenderContext& rc)
const
118 if (rc.destBuffer ==
nullptr || ! rc.playhead.isPlaying())
121 auto editTime = rc.getEditTime();
123 if (editTime.isSplit)
125 return fadeIn.overlaps (editTime.editRange1)
126 || fadeIn.overlaps (editTime.editRange2)
127 || fadeOut.overlaps (editTime.editRange1)
128 || fadeOut.overlaps (editTime.editRange2);
131 return fadeIn.overlaps (editTime.editRange1)
132 || fadeOut.overlaps (editTime.editRange1);
135void FadeInOutAudioNode::renderOver (
const AudioRenderContext& rc)
137 input->renderOver (rc);
139 if (renderingNeeded (rc))
140 invokeSplitRender (rc, *
this);
143void FadeInOutAudioNode::renderAdding (
const AudioRenderContext& rc)
145 if (renderingNeeded (rc))
148 input->renderAdding (rc);
151AudioNode* FadeInOutAudioNode::createForEdit (Edit& edit, AudioNode* source)
153 if (edit.masterFadeIn.get() > 0s || edit.masterFadeOut.get() > 0s)
155 auto length = edit.getLength();
157 return new FadeInOutAudioNode (source,
158 { 0.0, edit.masterFadeIn.get().inSeconds() },
159 { length.inSeconds() - edit.masterFadeOut.get().inSeconds(), length.inSeconds() },
160 edit.masterFadeInType,
161 edit.masterFadeOutType);
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Type
A enumeration of the curve classes available.