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

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_PlayHeadPositionNode.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
11namespace tracktion { inline namespace engine
12{
13
19{
20public:
22 std::atomic<double>& playHeadTimeToUpdate)
23 : TracktionEngineNode (processStateToUse),
24 input (std::move (inputNode)),
25 playHeadTime (playHeadTimeToUpdate)
26 {
27 setOptimisations ({ ClearBuffers::no,
28 AllocateAudioBuffer::no });
29 }
30
32 {
33 auto props = input->getNodeProperties();
34
35 constexpr size_t playHeadPositionNodeMagicHash = size_t (0x706c617948656164);
36
37 if (props.nodeID != 0)
38 hash_combine (props.nodeID, playHeadPositionNodeMagicHash);
39
40 return props;
41 }
42
44 bool isReadyToProcess() override { return input->hasProcessed(); }
45
47 {
48 latencyNumSamples = info.nodeGraph.rootNode->getNodeProperties().latencyNumSamples;
49
50 // Member variables have to be updated from the previous Node or if the graph gets
51 // rebuilt during the countdown period, the playhead time will jump back
52 updateFromPreviousNode (info.nodeGraphToReplace);
53 }
54
55 void process (ProcessContext& pc) override
56 {
57 // Copy the input buffers to the outputs
58 auto sourceBuffers = input->getProcessedOutput();
59 jassert (sourceBuffers.audio.getNumChannels() == pc.buffers.audio.getNumChannels());
60
61 pc.buffers.midi.copyFrom (sourceBuffers.midi);
62 setAudioOutput (input.get(), sourceBuffers.audio);
63 updatePlayHeadTime (pc.referenceSampleRange.getLength());
64 }
65
66private:
68 std::atomic<double>& playHeadTime;
69
70 int latencyNumSamples = 0;
71 bool updateReferencePositionOnJump = true;
72
73 struct State
74 {
75 int64_t numLatencySamplesToCountDown = 0;
76 int64_t referencePositionOnJump = 0;
77 };
78
80
81 void updatePlayHeadTime (int64_t numSamples)
82 {
83 int64_t referenceSamplePosition = getReferenceSampleRange().getStart();
84
85 if (getPlayHeadState().didPlayheadJump() || updateReferencePositionOnJump)
86 {
87 state->numLatencySamplesToCountDown = latencyNumSamples;
88 state->referencePositionOnJump = referenceSamplePosition;
89 }
90
91 if (state->numLatencySamplesToCountDown > 0)
92 {
93 const int64_t numSamplesToDecrement = std::min (state->numLatencySamplesToCountDown, numSamples);
94 state->numLatencySamplesToCountDown -= numSamplesToDecrement;
95 }
96
97 if (getPlayHead().isPlaying() && state->numLatencySamplesToCountDown <= 0)
98 {
99 referenceSamplePosition -= latencyNumSamples;
100 }
101 else
102 {
103 referenceSamplePosition = state->referencePositionOnJump;
104 }
105
106 const int64_t timelinePosition = getPlayHead().referenceSamplePositionToTimelinePosition (referenceSamplePosition);
107 const double time = tracktion::graph::sampleToTime (timelinePosition, getSampleRate());
108
109 playHeadTime = time;
110 updateReferencePositionOnJump = false;
111 }
112
113 void updateFromPreviousNode (NodeGraph* nodeGraphToReplace)
114 {
115 if (auto oldNode = findNodeWithIDIfNonZero<PlayHeadPositionNode> (nodeGraphToReplace, getNodeProperties().nodeID))
116 {
117 state = oldNode->state;
118 updateReferencePositionOnJump = false;
119 }
120 }
121};
122
123}} // namespace tracktion { inline namespace engine
constexpr ValueType getStart() const noexcept
constexpr ValueType getLength() const noexcept
A Node that calculates a position to show visually what time is currently being processed by the grap...
tracktion::graph::NodeProperties getNodeProperties() override
Should return the properties of the node.
bool isReadyToProcess() override
Should return true when this node is ready to be processed.
std::vector< tracktion::graph::Node * > getDirectInputNodes() override
Should return all the inputs directly feeding in to this node.
void prepareToPlay(const tracktion::graph::PlaybackInitialisationInfo &info) override
Called once before playback begins for each node.
void process(ProcessContext &pc) override
Called when the node is to be processed.
Base class for Nodes that provides information about the current process call.
juce::Range< int64_t > getReferenceSampleRange() const
Returns the reference sample range (from the DeviceManager) of the current process block.
double getSampleRate() const
Returns the sample rate of the current process block.
tracktion::graph::PlayHeadState & getPlayHeadState()
Returns the PlayHeadState in use.
tracktion::graph::PlayHead & getPlayHead()
Returns the PlayHead in use.
Main graph Node processor class.
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...
Struct to describe a single iteration of a process call.
int64_t referenceSamplePositionToTimelinePosition(int64_t referenceSamplePosition) const
Converts a reference sample position to a timeline position.
T get(T... args)
T is_pointer_v
#define jassert(expression)
T min(T... args)
typedef int64_t
Holds the state of a process call.
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
time