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

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_ModifierNode.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
11#pragma once
12
13
14namespace tracktion { inline namespace engine
15{
16
18 tracktion::engine::Modifier::Ptr modifierToProcess,
19 double sampleRateToUse, int blockSizeToUse,
20 const TrackMuteState* trackMuteStateToUse,
21 tracktion::graph::PlayHeadState& playHeadStateToUse, bool rendering)
22 : input (std::move (inputNode)),
23 modifier (std::move (modifierToProcess)),
24 trackMuteState (trackMuteStateToUse),
25 playHeadState (&playHeadStateToUse),
26 isRendering (rendering)
27{
28 jassert (input != nullptr);
29 jassert (modifier != nullptr);
30 initialiseModifier (sampleRateToUse, blockSizeToUse);
31}
32
34 tracktion::engine::Modifier::Ptr modifierToProcess,
35 double sampleRateToUse, int blockSizeToUse,
36 std::shared_ptr<InputProvider> contextProvider)
37 : input (std::move (inputNode)),
38 modifier (std::move (modifierToProcess)),
39 audioRenderContextProvider (std::move (contextProvider))
40{
41 jassert (input != nullptr);
42 jassert (modifier != nullptr);
43 initialiseModifier (sampleRateToUse, blockSizeToUse);
44}
45
47{
48 if (isInitialised && ! modifier->baseClassNeedsInitialising())
49 modifier->baseClassDeinitialise();
50}
51
52//==============================================================================
54{
55 auto props = input->getNodeProperties();
56
57 props.numberOfChannels = juce::jmax (props.numberOfChannels, modifier->getAudioInputNames().size());
58 props.hasAudio = props.hasAudio || modifier->getAudioInputNames().size() > 0;
59 props.hasMidi = props.hasMidi || modifier->getMidiInputNames().size() > 0;
60 props.nodeID = (size_t) modifier->itemID.getRawID();
61
62 return props;
63}
64
66{
67 juce::ignoreUnused (info);
68 jassert (sampleRate == info.sampleRate);
69
70 auto props = getNodeProperties();
71
72 if (props.latencyNumSamples > 0)
73 automationAdjustmentTime = TimeDuration::fromSamples (-props.latencyNumSamples, sampleRate);
74}
75
77{
78 auto inputBuffers = input->getProcessedOutput();
79 auto& inputAudioBlock = inputBuffers.audio;
80
81 auto& outputBuffers = pc.buffers;
82 auto& outputAudioBlock = outputBuffers.audio;
83
84 // Copy the inputs to the outputs, then process using the
85 // output buffers as that will be the correct size
86 if (auto numInputChannelsToCopy = std::min (inputAudioBlock.getNumChannels(),
87 outputAudioBlock.getNumChannels()))
88 {
89 jassert (inputAudioBlock.getNumFrames() == outputAudioBlock.getNumFrames());
90 copy (outputAudioBlock.getFirstChannels (numInputChannelsToCopy),
91 inputAudioBlock.getFirstChannels (numInputChannelsToCopy));
92 }
93
94 // Setup audio buffers
95 auto outputAudioBuffer = tracktion::graph::toAudioBuffer (outputAudioBlock);
96
97 // Then MIDI buffers
98 midiMessageArray.copyFrom (inputBuffers.midi);
99 bool shouldProcess = getBoolParamValue (*modifier->enabledParam);
100
101 if (playHeadState != nullptr && playHeadState->didPlayheadJump())
102 midiMessageArray.isAllNotesOff = true;
103
104 if (trackMuteState != nullptr)
105 {
106 if (! trackMuteState->shouldTrackContentsBeProcessed())
107 {
108 shouldProcess = shouldProcess && trackMuteState->shouldTrackBeAudible();
109
110 if (trackMuteState->wasJustMuted())
111 midiMessageArray.isAllNotesOff = true;
112 }
113 }
114
115 // Process the plugin
116 if (shouldProcess)
117 modifier->baseClassApplyToBuffer (getPluginRenderContext (pc.referenceSampleRange, outputAudioBuffer));
118
119 // Then copy the buffers to the outputs
120 outputBuffers.midi.copyFrom (midiMessageArray);
121}
122
123//==============================================================================
124void ModifierNode::initialiseModifier (double sampleRateToUse, int blockSizeToUse)
125{
126 sampleRate = sampleRateToUse;
127 modifier->baseClassInitialise (sampleRate, blockSizeToUse);
128 isInitialised = true;
129}
130
131PluginRenderContext ModifierNode::getPluginRenderContext (juce::Range<int64_t> referenceSampleRange, juce::AudioBuffer<float>& destBuffer)
132{
133 if (audioRenderContextProvider != nullptr)
134 {
135 tracktion::engine::PluginRenderContext rc (audioRenderContextProvider->getContext());
136 rc.destBuffer = &destBuffer;
137 rc.bufferStartSample = 0;
138 rc.bufferNumSamples = destBuffer.getNumSamples();
139 rc.bufferForMidiMessages = &midiMessageArray;
140 rc.midiBufferOffset = 0.0;
141
142 return rc;
143 }
144
145 jassert (playHeadState != nullptr);
146 auto& playHead = playHeadState->playHead;
147
148 const auto timelineRange = referenceSampleRangeToSplitTimelineRange (playHead, referenceSampleRange);
149 jassert (! timelineRange.isSplit);
150
151 return { &destBuffer,
153 0, destBuffer.getNumSamples(),
154 &midiMessageArray, 0.0,
155 timeRangeFromSamples (timelineRange.timelineRange1, sampleRate) + automationAdjustmentTime,
156 playHead.isPlaying(), playHead.isUserDragging(), isRendering, false };
157}
158
159}} // namespace tracktion { inline namespace engine
int getNumChannels() const noexcept
int getNumSamples() const noexcept
static AudioChannelSet JUCE_CALLTYPE canonicalChannelSet(int numChannels)
void prepareToPlay(const tracktion::graph::PlaybackInitialisationInfo &) override
Called once before playback begins for each node.
void process(ProcessContext &) override
Called when the node is to be processed.
ModifierNode(std::unique_ptr< Node > input, tracktion::engine::Modifier::Ptr, double sampleRateToUse, int blockSizeToUse, const TrackMuteState *, tracktion::graph::PlayHeadState &, bool rendering)
Creates a ModifierNode to process a Modifier.
tracktion::graph::NodeProperties getNodeProperties() override
Should return the properties of the node.
Holds the state of a Track and if its contents/plugins should be played or not.
bool shouldTrackBeAudible() const
Returns true if the track's mix bus should be audible.
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.
Struct to describe a single iteration of a process call.
Determines how this block releates to other previous render blocks and if the play head has jumped in...
bool didPlayheadJump() noexcept
Returns true if the play head jumped.
#define jassert(expression)
T min(T... args)
constexpr Type jmax(Type a, Type b)
void ignoreUnused(Types &&...) noexcept
bool getBoolParamValue(const AutomatableParameter &ap)
Returns a bool version of an AutomatableParameter.
The context passed to plugin render methods to provide it with buffers to fill.
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