tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_ArrangerLauncherSwitchingNode.h
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11#pragma once
12
13namespace tracktion { inline namespace engine
14{
15
16
18{
19public:
20 SampleFader() = default;
21
22 SampleFader (size_t numChannels)
23 {
24 reset (numChannels);
25 }
26
27 void reset (size_t numChannels)
28 {
29 samples = std::vector<float> (numChannels, 0.0f);
30 }
31
32 size_t getNumChannels() const
33 {
34 return samples.size();
35 }
36
37 template<typename Buffer>
38 void push (const Buffer& buffer)
39 {
40 pushSingleFrame (buffer.getEnd (1));
41 }
42
43 void trigger (size_t numFramesToFade_)
44 {
45 numFramesToFade = numFramesToFade_;
46 currentFadeFrameCountDown = numFramesToFade;
47 }
48
49 enum class FadeType
50 {
51 fadeOut,
52 crossfade
53 };
54
55 template<typename Buffer>
56 void apply (Buffer&& buffer, FadeType fadeType)
57 {
58 if (currentFadeFrameCountDown == 0 || numFramesToFade == 0)
59 return;
60
61 const auto numFrames = static_cast<size_t> (buffer.getNumFrames());
62 const auto numChannels = buffer.getNumChannels();
63 const size_t numThisTime = std::min (numFrames, currentFadeFrameCountDown);
64
65 for (choc::buffer::ChannelCount channel = 0; channel < numChannels; ++channel)
66 {
67 const auto dest = buffer.getIterator (channel).sample;
68 const auto lastSample = samples[static_cast<size_t> (channel)];
69 auto channelCurrentFadeFrameCountDown = currentFadeFrameCountDown;
70
71 for (size_t i = 0; i < numThisTime; ++i)
72 {
73 const auto frameNum = numFramesToFade - channelCurrentFadeFrameCountDown;
74 auto alpha = frameNum / static_cast<float> (numFramesToFade);
75 assert (alpha >= 0.0f && alpha <= 1.0f);
76
77 if (fadeType == FadeType::fadeOut)
78 dest[i] = dest[i] + (lastSample * (1.0f - alpha));
79 else if (fadeType == FadeType::crossfade)
80 dest[i] = (alpha * dest[i]) + (lastSample * (1.0f - alpha));
81
82 --channelCurrentFadeFrameCountDown;
83 }
84 }
85
86 assert ((static_cast<int> (currentFadeFrameCountDown) - static_cast<int> (numThisTime)) >= 0);
87 currentFadeFrameCountDown -= numThisTime;
88 }
89
90 template<typename Buffer>
91 void applyAt (Buffer& buffer, choc::buffer::FrameCount frameNum, FadeType fadeType)
92 {
93 apply (buffer.getFrameRange (choc::buffer::FrameRange { .start = frameNum, .end = buffer.getNumFrames() - frameNum }),
94 fadeType);
95 }
96
97private:
98 std::vector<float> samples;
99 size_t numFramesToFade = 0, currentFadeFrameCountDown = 0;
100
101 template<typename Buffer>
102 void pushSingleFrame (const Buffer& buffer)
103 {
104 const auto numChannels = buffer.getNumChannels();
105 assert (numChannels == samples.size());
106 assert (buffer.getNumFrames() == 1u);
107
108 for (auto chan = 0u; chan < numChannels; ++chan)
109 samples[static_cast<size_t> (chan)] = buffer.getSample (chan, 0);
110 }
111};
112
113class SlotControlNode;
114
115//==============================================================================
116//==============================================================================
121 public TracktionEngineNode,
122 public SharedTimer::Listener
123{
124public:
126 AudioTrack&,
127 std::unique_ptr<Node> arrangerNode,
129
132
134 void prepareToPlay (const PlaybackInitialisationInfo&) override;
135
136 bool isReadyToProcess() override;
137 void prefetchBlock (juce::Range<int64_t> /*referenceSampleRange*/) override;
138 void process (ProcessContext&) override;
139
140private:
141 //==============================================================================
142 struct SlotClipStatus;
143
144 AudioTrack::Ptr track;
145 std::unique_ptr<Node> arrangerNode;
147 std::vector<SlotControlNode*> launcherNodesCopy;
148 std::shared_ptr<SampleFader> launcherSampleFader, arrangerSampleFader;
149 std::shared_ptr<ActiveNoteList> arrangerActiveNoteList;
151 MidiMessageArray::MPESourceID midiSourceID = MidiMessageArray::createUniqueMPESourceID();
152 ScopedListener playSlotsUpdaterListener { track->edit.engine.getBackToArrangerUpdateTimer(), *this };
153
154 //==============================================================================
155 void processLauncher (ProcessContext&, const SlotClipStatus&);
156 void processArranger (ProcessContext&, const SlotClipStatus&);
157
158 void sortPlayingOrQueuedClipsFirst();
159 void updatePlaySlotsState();
160
161 //==============================================================================
162 static choc::buffer::FrameCount beatToSamplePosition (std::optional<BeatDuration> beat, BeatDuration numBeats, choc::buffer::FrameCount);
163
164 struct SlotClipStatus
165 {
166 bool anyClipsPlaying = false;
167 bool anyClipsQueued = false;
168 std::optional<BeatDuration> beatsUntilQueuedStart;
169 std::optional<BeatDuration> beatsUntilQueuedStartTrimmedToBlock;
170 std::optional<BeatDuration> beatsUntilQueuedStopTrimmedToBlock;
171 };
172
173 static SlotClipStatus getSlotsStatus (const std::vector<std::unique_ptr<SlotControlNode>>&,
174 BeatRange editBeatRange, MonotonicBeat);
175
176 //==============================================================================
177 void sharedTimerCallback() override;
178};
179
180}} // namespace tracktion { inline namespace engine
assert
A Node that switches between two of its inputs based on a flag.
void process(ProcessContext &) override
Called when the node is to be processed.
tracktion::graph::NodeProperties getNodeProperties() override
Should return the properties of the node.
void prefetchBlock(juce::Range< int64_t >) override
Called before once on all Nodes before they are processed.
bool isReadyToProcess() override
Should return true when this node is ready to be processed.
std::vector< Node * > getInternalNodes() override
Can return Nodes that are internal to this Node but don't make up the main graph constructed from get...
std::vector< Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this node.
Manages adding and removing listeners in an RAII way so you don't forget to unregister a listener.
Base class for Nodes that provides information about the current process call.
Main graph Node processor class.
Struct to describe a single iteration of a process call.
T min(T... args)
Passed into AudioNodes when they are being initialised, to give them useful contextual information th...
T size(T... args)
Represents a duration in beats.
Holds the state of a process call.
Holds some really basic properties of a node.