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

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_PlayHead.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 graph
15{
16
17#if GRAPH_UNIT_TESTS_PLAYHEAD
18
19//==============================================================================
20//==============================================================================
21class PlayHeadTests : public juce::UnitTest
22{
23public:
24 PlayHeadTests()
25 : juce::UnitTest ("PlayHead", "tracktion_graph")
26 {
27 }
28
29 void runTest() override
30 {
31 runBasicTests();
32 }
33
34private:
35 //==============================================================================
36 //==============================================================================
37 void runBasicTests()
38 {
39 beginTest ("SplitTimelineRange");
40 {
41 PlayHead playHead;
42 playHead.play ({ 0, 1000 }, true);
43
44 {
45 const auto tr = referenceSampleRangeToSplitTimelineRange (playHead, { 250, 750 });
46 expect (! tr.isSplit);
47 expectEquals<int64_t> (tr.timelineRange1.getStart(), 250);
48 expectEquals<int64_t> (tr.timelineRange1.getEnd(), 750);
49 expectEquals<int64_t> (tr.timelineRange2.getStart(), 0);
50 expectEquals<int64_t> (tr.timelineRange2.getEnd(), 0);
51 }
52
53 {
54 const auto tr = referenceSampleRangeToSplitTimelineRange (playHead, { 750, 1250 });
55 expect (tr.isSplit);
56 expectEquals<int64_t> (tr.timelineRange1.getStart(), 750);
57 expectEquals<int64_t> (tr.timelineRange1.getEnd(), 1000);
58 expectEquals<int64_t> (tr.timelineRange2.getStart(), 0);
59 expectEquals<int64_t> (tr.timelineRange2.getEnd(), 250);
60 }
61
62 {
63 playHead.play ({ 0, 1500 }, false);
64 const auto tr = referenceSampleRangeToSplitTimelineRange (playHead, { 500, 1500 });
65 expect (! tr.isSplit);
66 expectEquals<int64_t> (tr.timelineRange1.getStart(), 500);
67 expectEquals<int64_t> (tr.timelineRange1.getEnd(), 1500);
68 expectEquals<int64_t> (tr.timelineRange2.getStart(), 0);
69 expectEquals<int64_t> (tr.timelineRange2.getEnd(), 0);
70 }
71 }
72
73 beginTest ("PlayHead playing");
74 {
75 {
76 PlayHead playHead;
77 playHead.play ({ 0, 10'000 }, false);
78 juce::Range<int64_t> referenceRange;
79
80 expectEquals<int64_t> (playHead.getPosition(), 0);
81 expectEquals<int64_t> (playHead.referenceSamplePositionToTimelinePosition (0), 0);
82
83 referenceRange += 500;
84 playHead.setReferenceSampleRange (referenceRange);
85 expectEquals<int64_t> (playHead.getPosition(), 500);
86 expectEquals<int64_t> (playHead.referenceSamplePositionToTimelinePosition (0), 0);
87
88 referenceRange += 1000;
89 playHead.setReferenceSampleRange (referenceRange);
90 expectEquals<int64_t> (playHead.getPosition(), 1500);
91 expectEquals<int64_t> (playHead.referenceSamplePositionToTimelinePosition (0), 0);
92
93 playHead.stop();
94 referenceRange += 500;
95 playHead.setReferenceSampleRange (referenceRange);
96 expectEquals<int64_t> (playHead.getPosition(), 1500); // timeline position hasn't moved
97 expectEquals<int64_t> (playHead.referenceSamplePositionToTimelinePosition (0), 1500); // ref position is at the previous timeline pos
98
99 playHead.play();
100 expectEquals<int64_t> (playHead.getPosition(), 1500);
101 // ref position is now synced to the last timeline pos (2000)
102 expectEquals<int64_t> (playHead.referenceSamplePositionToTimelinePosition (0), -500);
103 expectEquals<int64_t> (playHead.getPosition(), 1500);
104 referenceRange += 500;
105 playHead.setReferenceSampleRange (referenceRange);
106 expectEquals<int64_t> (playHead.getPosition(), 2000);
107 expectEquals<int64_t> (playHead.referenceSamplePositionToTimelinePosition (0), -500);
108 }
109
110 {
111 PlayHead playHead;
112 playHead.play ({ 0, 2'000 }, true);
113 int64_t referencePos = 0;
114
115 auto incrementReferencePos = [&] (int64_t numSamples)
116 {
117 referencePos += numSamples;
118 playHead.setReferenceSampleRange ({ referencePos, referencePos });
119 };
120
121 expectEquals<int64_t> (playHead.getPosition(), 0);
122 incrementReferencePos (1000);
123 expectEquals<int64_t> (playHead.getPosition(), 1000);
124 expectEquals<int64_t> (playHead.referenceSamplePositionToTimelinePosition (referencePos), playHead.getPosition());
125
126 {
127 const auto tr = referenceSampleRangeToSplitTimelineRange (playHead, { referencePos, referencePos + 500 });
128
129 expect (! tr.isSplit);
130 expectEquals<int64_t> (tr.timelineRange1.getStart(), 1000);
131 expectEquals<int64_t> (tr.timelineRange1.getEnd(), 1500);
132 expectEquals<int64_t> (tr.timelineRange2.getStart(), 0);
133 expectEquals<int64_t> (tr.timelineRange2.getEnd(), 0);
134 }
135
136 incrementReferencePos (500);
137 expectEquals<int64_t> (playHead.getPosition(), 1500);
138 expectEquals<int64_t> (playHead.referenceSamplePositionToTimelinePosition (referencePos), playHead.getPosition());
139
140 {
141 const auto tr = referenceSampleRangeToSplitTimelineRange (playHead, { referencePos, referencePos + 1000 });
142
143 expect (tr.isSplit);
144 expectEquals<int64_t> (tr.timelineRange1.getStart(), 1500);
145 expectEquals<int64_t> (tr.timelineRange1.getEnd(), 2000);
146 expectEquals<int64_t> (tr.timelineRange2.getStart(), 0);
147 expectEquals<int64_t> (tr.timelineRange2.getEnd(), 500);
148 }
149 }
150
151 {
152 PlayHead playHead;
153 playHead.play ({ 1'000, 3'000 }, true);
154 int64_t referencePos = 0;
155
156 auto incrementReferencePos = [&] (int64_t numSamples)
157 {
158 referencePos += numSamples;
159 playHead.setReferenceSampleRange ({ referencePos, referencePos });
160 };
161
162 expectEquals<int64_t> (playHead.getPosition(), 1'000);
163 incrementReferencePos (1'000);
164 expectEquals<int64_t> (playHead.getPosition(), 2'000);
165 expectEquals<int64_t> (playHead.referenceSamplePositionToTimelinePosition (referencePos), playHead.getPosition());
166
167 {
168 const auto tr = referenceSampleRangeToSplitTimelineRange (playHead, { referencePos, referencePos + 500 });
169
170 expect (! tr.isSplit);
171 expectEquals<int64_t> (tr.timelineRange1.getStart(), 2'000);
172 expectEquals<int64_t> (tr.timelineRange1.getEnd(), 2'500);
173 expectEquals<int64_t> (tr.timelineRange2.getStart(), 0);
174 expectEquals<int64_t> (tr.timelineRange2.getEnd(), 0);
175 }
176
177 incrementReferencePos (500);
178 expectEquals<int64_t> (playHead.getPosition(), 2'500);
179 expectEquals<int64_t> (playHead.referenceSamplePositionToTimelinePosition (referencePos), playHead.getPosition());
180
181 {
182 const auto tr = referenceSampleRangeToSplitTimelineRange (playHead, { referencePos, referencePos + 1'000 });
183
184 expect (tr.isSplit);
185 expectEquals<int64_t> (tr.timelineRange1.getStart(), 2'500);
186 expectEquals<int64_t> (tr.timelineRange1.getEnd(), 3'000);
187 expectEquals<int64_t> (tr.timelineRange2.getStart(), 1'000);
188 expectEquals<int64_t> (tr.timelineRange2.getEnd(), 1'500);
189 }
190 }
191
192 {
193 PlayHead playHead;
194 playHead.play ({ 1'000, 3'000 }, true);
195 playHead.setRollInToLoop (500);
196 expect (playHead.isPlaying());
197 expect (playHead.isLooping());
198 expect (playHead.isRollingIntoLoop());
199
200 expectEquals<int64_t> (playHead.getPosition(), 500);
201 playHead.setReferenceSampleRange ({ 500, 500 });
202 expectEquals<int64_t> (playHead.getPosition(), 1'000);
203 expect (! playHead.isRollingIntoLoop());
204 }
205 }
206 }
207};
208
209static PlayHeadTests playHeadTests;
210
211#endif
212
213}}
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...
typedef int64_t