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

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_TrackMutingNode.cpp
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
11namespace tracktion { inline namespace engine
12{
13
14TrackMuteState::TrackMuteState (Track& t, bool muteForInputsWhenRecording, bool processMidiWhenMuted_)
15 : edit (t.edit), track (&t),
16 processMidiWhileMuted (processMidiWhenMuted_)
17{
18 processMidiWhileMuted = true;
19 callInputWhileMuted = t.processAudioNodesWhileMuted();
20
21 if (muteForInputsWhenRecording)
22 if (auto at = dynamic_cast<AudioTrack*> (&t))
23 for (auto in : edit.getAllInputDevices())
24 if (in->isRecordingActive (t.itemID) && in->getTargets().contains (at->itemID))
25 inputDevicesToMuteFor.add (in);
26
27 wasBeingPlayedFlag = t.shouldBePlayed();
28}
29
31 : edit (e)
32{
33 wasBeingPlayedFlag = ! edit.areAnyTracksSolo();
34}
35
37{
38 const bool isPlayingNow = isBeingPlayed();
39 wasJustMutedFlag.store (wasBeingPlayedFlag && ! isPlayingNow, std::memory_order_release);
40 wasJustUnMutedFlag.store (! wasBeingPlayedFlag && isPlayingNow, std::memory_order_release);
41 wasBeingPlayedFlag = isPlayingNow;
42}
43
45{
46 return wasBeingPlayedFlag || wasJustMuted();
47}
48
50{
51 return callInputWhileMuted || wasBeingPlayedFlag;
52}
53
55{
56 return processMidiWhileMuted;
57}
58
59bool TrackMuteState::isBeingPlayed() const
60{
61 bool playing = track != nullptr ? track->shouldBePlayed() : ! edit.areAnyTracksSolo();
62
63 if (! playing)
64 return false;
65
66 for (int i = inputDevicesToMuteFor.size(); --i >= 0;)
67 if (inputDevicesToMuteFor.getUnchecked (i)->shouldTrackContentsBeMuted (*track))
68 return false;
69
70 return true;
71}
72
73//==============================================================================
75{
76 return track != nullptr ? (size_t) track->itemID.getRawID()
77 : (size_t) edit.getProjectItemID().getRawID();
78}
79
80
81//==============================================================================
82//==============================================================================
83TrackMutingNode::TrackMutingNode (std::unique_ptr<TrackMuteState> muteState, std::unique_ptr<tracktion::graph::Node> inputNode,
84 bool dontMuteIfTrackContentsShouldBeProcessed_)
85 : trackMuteState (std::move (muteState)), input (std::move (inputNode)),
86 dontMuteIfTrackContentsShouldBeProcessed (dontMuteIfTrackContentsShouldBeProcessed_)
87{
88 assert (trackMuteState);
89
90 setOptimisations ({ tracktion::graph::ClearBuffers::no,
91 tracktion::graph::AllocateAudioBuffer::yes });
92}
93
94//==============================================================================
96{
97 auto props = input->getNodeProperties();
98 hash_combine (props.nodeID, trackMuteState->getItemID());
99
100 return props;
101}
102
107
109{
110 if (! info.enableNodeMemorySharing)
111 return;
112
113 if (input->numOutputNodes > 1)
114 return;
115
116 const auto inputNumChannels = input->getNodeProperties().numberOfChannels;
117 const auto desiredNumChannels = getNodeProperties().numberOfChannels;
118
119 if (inputNumChannels >= desiredNumChannels)
120 {
121 canUseSourceBuffers = true;
122 setOptimisations ({ tracktion::graph::ClearBuffers::no,
123 tracktion::graph::AllocateAudioBuffer::no });
124 }
125}
126
128{
129 return input->hasProcessed();
130}
131
133{
134 trackMuteState->update();
135}
136
137void TrackMutingNode::preProcess (choc::buffer::FrameCount, juce::Range<int64_t>)
138{
139 if (canUseSourceBuffers)
140 setBufferViewToUse (input.get(), input->getProcessedOutput().audio);
141}
142
144{
145 auto sourceBuffers = input->getProcessedOutput();
146 auto destAudioView = pc.buffers.audio;
147 jassert (sourceBuffers.audio.getSize() == destAudioView.getSize());
148
149 const bool ignoreMuteStates = dontMuteIfTrackContentsShouldBeProcessed && trackMuteState->shouldTrackContentsBeProcessed();
150 const bool wasJustMuted = ! ignoreMuteStates && trackMuteState->wasJustMuted();
151 const bool wasJustUnMuted = ! ignoreMuteStates && trackMuteState->wasJustUnMuted();
152
153 if (trackMuteState->shouldTrackBeAudible() || ignoreMuteStates)
154 {
155 pc.buffers.midi.copyFrom (sourceBuffers.midi);
156
157 // If we've just been muted/unmuted we need to copy the data to
158 // apply a fade to, otherwise we can just pass on the view
159 if (wasJustMuted || wasJustUnMuted)
160 copyIfNotAliased (destAudioView, sourceBuffers.audio);
161 else
162 setAudioOutput (input.get(), sourceBuffers.audio);
163 }
164 else
165 {
166 destAudioView.clear();
167 pc.buffers.midi.clear();
168 }
169
170 if (wasJustMuted)
171 rampBlock (destAudioView, 1.0f, 0.0f);
172 else if (wasJustUnMuted)
173 rampBlock (destAudioView, 0.0f, 1.0f);
174}
175
176//==============================================================================
177void TrackMutingNode::rampBlock (choc::buffer::ChannelArrayView<float> view, float start, float end)
178{
179 if (view.getNumChannels() == 0)
180 return;
181
182 auto buffer = tracktion::graph::toAudioBuffer (view);
183 buffer.applyGainRamp (0, buffer.getNumSamples(), start, end);
184}
185
186}} // namespace tracktion { inline namespace engine
assert
The Tracktion Edit class!
bool areAnyTracksSolo() const
Returns true if any tracks are soloed.
juce::Array< InputDeviceInstance * > getAllInputDevices() const
Returns all the active InputDeviceInstance[s] in the Edit.
ProjectItemID getProjectItemID() const noexcept
Returns the ProjectItemID of the Edit.
int64_t getRawID() const noexcept
Returns a combined ID as an integer, useful for creating hashes.
bool shouldTrackBeAudible() const
Returns true if the track's mix bus should be audible.
void update()
Call once per block to update the mute status.
bool shouldTrackMidiBeProcessed() const
Returns true if the track's MIDI should be processed to avoid breaks in long notes.
TrackMuteState(Track &, bool muteForInputsWhenRecording, bool processMidiWhenMuted)
Creates a TrackMuteState for a Track.
size_t getItemID() const
Returns the ID for the relevant item, either the Track or Edit.
bool shouldTrackContentsBeProcessed() const
Returns true if the track's contents should be processed e.g.
bool wasJustMuted() const
Returns true if the last block was audible but this one isn't.
void process(ProcessContext &) override
Called when the node is to be processed.
void prepareToPlay(const tracktion::graph::PlaybackInitialisationInfo &) override
Called once before playback begins for each node.
bool isReadyToProcess() override
Should return true when this node is ready to be processed.
std::vector< Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this node.
void prefetchBlock(juce::Range< int64_t >) override
Called before once on all Nodes before they are processed.
void preProcess(choc::buffer::FrameCount, juce::Range< int64_t >) override
Called when the node is to be processed, just before process.
tracktion::graph::NodeProperties getNodeProperties() override
Should return the properties of the node.
Base class for tracks which contain clips and plugins and can be added to Edit[s].
void setAudioOutput(Node *sourceNode, const choc::buffer::ChannelArrayView< float > &)
This can be called during your process function to set a view to the output.
void setOptimisations(NodeOptimisations)
This can be called to provide some hints about allocating or playing back a Node to improve efficienc...
void setBufferViewToUse(Node *sourceNode, const choc::buffer::ChannelArrayView< float > &)
This can be called during prepareToPlay to set a BufferView to use which can improve efficiency.
Struct to describe a single iteration of a process call.
T get(T... args)
T is_pointer_v
#define jassert(expression)
T store(T... args)
Holds some really basic properties of a node.
Passed into Nodes when they are being initialised, to give them useful contextual information that th...
typedef size_t