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

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_TracktionEngineNode.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
15 : playHeadState (phs)
16{
17}
18
20 : ProcessState (phs, seq.getInternalSequence())
21{
22}
23
25 : playHeadState (phs),
26 tempoSequence (&seq),
27 tempoPosition (std::make_unique<tempo::Sequence::Position> (seq))
28{
29}
30
31void ProcessState::update (double newSampleRate, juce::Range<int64_t> newReferenceSampleRange, UpdateContinuityFlags updateContinuityFlags)
32{
33 if (sampleRate != newSampleRate)
34 playHeadState.playHead.setScrubbingBlockLength (toSamples (TimeDuration (0.08s), newSampleRate));
35
36 playHeadState.playHead.setReferenceSampleRange (newReferenceSampleRange);
37
38 if (updateContinuityFlags == UpdateContinuityFlags::yes)
39 playHeadState.update (newReferenceSampleRange);
40
41 sampleRate = newSampleRate;
42 numSamples = (int) newReferenceSampleRange.getLength();
43 referenceSampleRange = newReferenceSampleRange;
44
45 const auto splitTimelineRange = referenceSampleRangeToSplitTimelineRange (playHeadState.playHead, newReferenceSampleRange);
46 jassert (! splitTimelineRange.isSplit);
47 timelineSampleRange = splitTimelineRange.timelineRange1;
48 jassert (timelineSampleRange.getLength() == 0
49 || timelineSampleRange.getLength() == newReferenceSampleRange.getLength());
50
51 editTimeRange = timeRangeFromSamples (timelineSampleRange, sampleRate);
52
53 if (! tempoPosition)
54 return;
55
56 tempoPosition->set (editTimeRange.getStart());
57 const auto beatStart = tempoPosition->getBeats();
58 tempoPosition->set (editTimeRange.getEnd());
59 const auto beatEnd = tempoPosition->getBeats();
60 editBeatRange = { beatStart, beatEnd };
61
62 if (updateContinuityFlags == UpdateContinuityFlags::no)
63 return;
64
65 // Only update the sync range if the continuity is being updated as the player can call this
66 // multiple times and we don't want to increment the monotonic beat each call
67 const auto unloopTimelineSample = playHeadState.playHead.referenceSamplePositionToTimelinePositionUnlooped (referenceSampleRange.getEnd());
68 auto oldSyncPoint = getSyncPoint();
69 const auto newSyncPoint = SyncPoint ({
70 referenceSampleRange.getEnd(),
71 { oldSyncPoint.monotonicBeat.v + editBeatRange.getLength() },
72 TimePosition::fromSamples (unloopTimelineSample, sampleRate),
73 editTimeRange.getEnd(),
74 beatEnd
75 });
76
77 oldSyncPoint.time = editTimeRange.getStart();
78 oldSyncPoint.beat = beatStart;
79 syncRange.store ({ oldSyncPoint, newSyncPoint });
80
83}
84
86{
87 playbackSpeedRatio = newRatio;
88}
89
90void ProcessState::setTempoSequence (const tempo::Sequence* ts)
91{
92 if (tempoSequence == ts)
93 return;
94
95 tempoSequence = ts;
96
97 if (tempoSequence)
98 tempoPosition = std::make_unique<tempo::Sequence::Position> (*tempoSequence);
99 else
100 tempoPosition.reset();
101}
102
103const tempo::Sequence* ProcessState::getTempoSequence() const
104{
105 return tempoSequence;
106}
107
109{
110 return tempoPosition.get();
111}
112
114{
115 return getSyncRange().end;
116}
117
119{
120 return syncRange.load();
121}
122
123void ProcessState::setSyncRange (SyncRange r)
124{
125 syncRange.store (std::move (r));
126}
127
128//==============================================================================
129//==============================================================================
131 : processState (&ps)
132{
133}
134
136{
137 if (auto tempoPosition = processState->getTempoSequencePosition())
138 return tempoPosition->getKey();
139
140 return {};
141}
142
144{
145 return processState->playbackSpeedRatio;
146}
147
149{
150 if (auto tempoPosition = processState->getTempoSequencePosition())
151 return tempoPosition->getTimeOfNextChange();
152
153 return {};
154}
155
157{
158 if (auto tempoPosition = processState->getTempoSequencePosition())
159 return tempoPosition->getBeatOfNextChange();
160
161 return {};
162}
163
164void TracktionEngineNode::setProcessState (ProcessState& newProcessState)
165{
166 processState = &newProcessState;
167}
168
169}} // namespace tracktion { inline namespace engine
constexpr ValueType getEnd() const noexcept
constexpr ValueType getLength() const noexcept
Holds a list of TempoSetting objects, to form a sequence of tempo changes.
std::optional< TimePosition > getTimeOfNextChange() const
May return the time of the next tempo or time sig change.
TracktionEngineNode(ProcessState &)
Creates a TracktionEngineNode.
double getPlaybackSpeedRatio() const
Returns the playback speed ratio of the current process block.
tempo::Key getKey() const
Returns the key of the current process block.
std::optional< BeatPosition > getBeatOfNextChange() const
May return the time of the next tempo or time sig change.
Determines how this block releates to other previous render blocks and if the play head has jumped in...
void update(juce::Range< int64_t > referenceSampleRange)
Call once per block to update the jumped state.
int64_t referenceSamplePositionToTimelinePositionUnlooped(int64_t referenceSamplePosition) const
Converts a reference sample position to a timeline position as if there was no looping set.
void setScrubbingBlockLength(int64_t numSamples)
Sets the length of the small looped blocks to play while scrubbing.
void setReferenceSampleRange(juce::Range< int64_t > sampleRange)
Sets the reference sample count, adjusting the timeline if the play head is playing.
T is_pointer_v
#define jassert(expression)
typedef int
TimePosition time
The Edit timeline time.
Holds a reference sample position and the Edit time and beat that it corresponds to.
SplitTimelineRange referenceSampleRangeToSplitTimelineRange(const PlayHead &playHead, juce::Range< int64_t > referenceSampleRange)
Converts a reference sample range to a TimelinePositionWindow which could have two time ranges if the...
Represents a duration in real-life time.
A Sequence::Position is an iterator through a Sequence.
Holds the state of a process call.
const tempo::Sequence::Position * getTempoSequencePosition() const
Returns the tempo::Sequence::Position this state uses.
void update(double sampleRate, juce::Range< int64_t > referenceSampleRange, UpdateContinuityFlags)
Updates the internal state based on a reference sample range.
std::function< void()> onContinuityUpdated
Callback which can be set to be called when the continuity changes.
UpdateContinuityFlags
An enum to indicate if the PlayHeadState continuity should be updated.
SyncPoint getSyncPoint() const
Returns the end of the SyncRange.
ProcessState(tracktion::graph::PlayHeadState &)
Creates a ProcessState.
SyncRange getSyncRange() const
Returns the SyncRange for the current audio block.
void setPlaybackSpeedRatio(double newRatio)
Sets a playback speed ratio.
const tempo::Sequence * getTempoSequence() const
Returns the tempo::Sequence this state has been initialised with one.
void setTempoSequence(const tempo::Sequence *)
Sets the TempoSequence this state utilises.