22 void setPosition (
double newTime)
24 if (newTime != getPosition())
27 overridePosition (newTime);
34 playRange = rangeToPlay;
35 setPosition (playRange.start);
37 looping = looped && (playRange.getLength() > 0.001);
45 setPosition (getPosition());
54 play (rangeToPlay,
false);
63 auto t = getPosition();
69 void setUserIsDragging (
bool b)
75 bool isUserDragging()
const {
return userDragging; }
76 juce::Time getLastUserInteractionTime()
const {
return userInteractionTime; }
82 : editRange1 (range1), isSplit (
false) {}
85 : editRange1 (range1), editRange2 (range2), isSplit (
true) {}
91 double streamTimeToSourceTime (
double streamTime)
const
96 return playoutSyncTime +
std::fmod (streamTime - streamSyncTime, getScrubbingBlockLengthSeconds());
98 if (looping && ! rollInToLoop)
99 return linearTimeToLoopTime (streamTimeToSourceTimeUnlooped (streamTime), playRange);
101 return streamTimeToSourceTimeUnlooped (streamTime);
104 double streamTimeToSourceTimeUnlooped (
double streamTime)
const
107 return playoutSyncTime + (streamTime - streamSyncTime) * speed;
110 static double linearTimeToLoopTime (
double time, legacy::EditTimeRange loop)
112 return linearTimeToLoopTime (time, loop.start, loop.getLength());
115 static double linearTimeToLoopTime (
double time,
double loopStart,
double loopLen)
117 return loopStart +
std::fmod (time - loopStart, loopLen);
120 EditTimeWindow streamTimeToEditWindow (legacy::EditTimeRange streamTime)
const
122 constexpr double errorMargin = 0.000001;
124 auto s = streamTimeToSourceTimeUnlooped (streamTime.start);
125 auto e = streamTimeToSourceTimeUnlooped (streamTime.end);
129 auto loopStart = [
this] {
const juce::ScopedLock sl (lock);
return playoutSyncTime; }();
130 auto loopLen = getScrubbingBlockLengthSeconds();
131 auto loopEnd = loopStart + loopLen;
133 s = linearTimeToLoopTime (s, loopStart, loopLen);
134 e = linearTimeToLoopTime (e, loopStart, loopLen);
138 if (s >= loopEnd - errorMargin)
139 return EditTimeWindow ({ loopStart, e });
141 if (e <= loopStart + errorMargin)
142 return EditTimeWindow ({ s, loopEnd });
144 return EditTimeWindow ({ s, loopEnd }, { loopStart, e });
148 if (looping && ! rollInToLoop)
150 const auto pr = getLoopTimes();
151 s = linearTimeToLoopTime (s, pr);
152 e = linearTimeToLoopTime (e, pr);
156 if (s >= pr.end - errorMargin)
return EditTimeWindow ({ pr.start, e });
157 if (e <= pr.start + errorMargin)
return EditTimeWindow ({ s, pr.end });
159 return EditTimeWindow ({ s, pr.end }, { pr.start, e });
163 return EditTimeWindow ({ s, e });
166 double getPosition()
const
169 return streamTimeToSourceTime (lastStreamTime);
172 double getUnloopedPosition()
const
175 return streamTimeToSourceTimeUnlooped (lastStreamTime);
180 void overridePosition (
double newTime)
184 if (looping && rollInToLoop)
185 newTime =
juce::jmin (newTime, playRange.end);
187 newTime = playRange.clipValue (newTime);
189 streamSyncTime = lastStreamTimeEnd;
190 playoutSyncTime = newTime;
199 legacy::EditTimeRange getLoopTimes() const noexcept {
const juce::ScopedLock sl (lock);
return playRange; }
201 void setLoopTimes (
bool loop, legacy::EditTimeRange times)
203 if (looping != loop || (loop && times != getLoopTimes()))
207 auto lastPos = getPosition();
210 setPosition (lastPos);
214 void setRollInToLoop (
double t)
219 streamSyncTime = lastStreamTime;
220 playoutSyncTime =
juce::jmin (t, playRange.end);
229 lastStreamTime = newTime;
230 lastStreamTimeEnd = newTimeEnd;
232 if (rollInToLoop && getPosition() > playRange.start + 1.0)
233 rollInToLoop =
false;
238 double streamSyncTime = 0, playoutSyncTime = 0;
239 legacy::EditTimeRange playRange;
240 double lastStreamTime = 0, lastStreamTimeEnd = 0;
243 std::atomic<bool> looping {
false }, userDragging {
false }, rollInToLoop {
false };
246 static constexpr double getScrubbingBlockLengthSeconds() {
return 0.08; }