Audacity  3.0.3
PlaybackSchedule.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  PlaybackSchedule.cpp
6 
7  Paul Licameli split from AudioIOBase.cpp
8 
9  **********************************************************************/
10 
11 #include "PlaybackSchedule.h"
12 
13 #include "AudioIOBase.h"
14 #include "Envelope.h"
15 #include "Mix.h"
16 #include "SampleCount.h"
17 
18 #include <cmath>
19 
22 {
23  mRate = rate;
24 }
26 
28 {
29  return Mixer::WarpOptions{ schedule.mEnvelope };
30 }
31 
34 {
35  return { 4.0, 4.0, 10.0 };
36 }
37 
39 {
40  return true;
41 }
42 
44  unsigned long outputFrames)
45 {
46  auto diff = schedule.GetTrackTime() - schedule.mT1;
47  if (schedule.ReversedTime())
48  diff *= -1;
49  return sampleCount(floor(diff * mRate + 0.5)) >= 0 &&
50  // Require also that output frames are all consumed from ring buffer
51  outputFrames == 0;
52 }
53 
55  PlaybackSchedule &schedule, double offset )
56 {
57  const auto time = schedule.ClampTrackTime(
58  schedule.GetTrackTime() + offset );
59  schedule.RealTimeInit( time );
60  return time;
61 }
62 
64 {
65 }
66 
67 std::chrono::milliseconds PlaybackPolicy::SleepInterval(PlaybackSchedule &)
68 {
69  using namespace std::chrono;
70  return 10ms;
71 }
72 
75 {
76  // How many samples to produce for each channel.
77  const auto realTimeRemaining = schedule.RealTimeRemaining();
78  auto frames = available;
79  auto toProduce = frames;
80  double deltat = frames / mRate;
81 
82  if (deltat > realTimeRemaining)
83  {
84  // Produce some extra silence so that the time queue consumer can
85  // satisfy its end condition
86  const double extraRealTime = (TimeQueueGrainSize + 1) / mRate;
87  auto extra = std::min( extraRealTime, deltat - realTimeRemaining );
88  auto realTime = realTimeRemaining + extra;
89  frames = realTime * mRate;
90  toProduce = realTimeRemaining * mRate;
91  schedule.RealTimeAdvance( realTime );
92  }
93  else
94  schedule.RealTimeAdvance( deltat );
95 
96  return { available, frames, toProduce };
97 }
98 
99 std::pair<double, double>
101  double trackTime, size_t nSamples )
102 {
103  auto realDuration = nSamples / mRate;
104  if (schedule.ReversedTime())
105  realDuration *= -1.0;
106 
107  if (schedule.mEnvelope)
108  trackTime =
109  schedule.SolveWarpedLength(trackTime, realDuration);
110  else
111  trackTime += realDuration;
112 
113  if ( trackTime >= schedule.mT1 )
114  return { schedule.mT1, std::numeric_limits<double>::infinity() };
115  else
116  return { trackTime, trackTime };
117 }
118 
120  PlaybackSchedule &, const Mixers &, size_t, size_t)
121 {
122  return true;
123 }
124 
126 {
127  return false;
128 }
129 
130 namespace {
132  ~DefaultPlaybackPolicy() override = default;
133 };
134 }
135 
137 {
138  if (mPolicyValid.load(std::memory_order_acquire) && mpPlaybackPolicy)
139  return *mpPlaybackPolicy;
140 
141  static DefaultPlaybackPolicy defaultPolicy;
142  return defaultPolicy;
143 }
144 
146 {
147  return const_cast<PlaybackSchedule&>(*this).GetPolicy();
148 }
149 
151 
154 {
155  // Shorter times than in the default policy so that responses to changes of
156  // selection don't lag too much
157  return { 0.5, 0.5, 1.0 };
158 }
159 
161 {
162  return false;
163 }
164 
167  PlaybackSchedule &schedule, size_t available)
168 {
169  // How many samples to produce for each channel.
170  const auto realTimeRemaining = std::max(0.0, schedule.RealTimeRemaining());
171  auto frames = available;
172  auto toProduce = frames;
173  double deltat = frames / mRate;
174 
175  mRemaining = realTimeRemaining * mRate;
176  if (deltat > realTimeRemaining)
177  {
178  toProduce = frames = mRemaining;
179  schedule.RealTimeAdvance( realTimeRemaining );
180  }
181  else
182  schedule.RealTimeAdvance( deltat );
183 
184  // Don't fall into an infinite loop, if loop-playing a selection
185  // that is so short, it has no samples: detect that case
186  if (frames == 0) {
187  bool progress = (schedule.mWarpedTime != 0.0);
188  if (!progress)
189  // Cause FillPlayBuffers to make progress, filling all available with 0
190  frames = available, toProduce = 0;
191  }
192  return { available, frames, toProduce };
193 }
194 
196  PlaybackSchedule &schedule, double trackTime, size_t nSamples )
197 {
198  mRemaining -= std::min(mRemaining, nSamples);
199  if ( mRemaining == 0 )
200  // Wrap to start
201  return { schedule.mT1, schedule.mT0 };
202 
203  // Defense against cases that might cause loops not to terminate
204  if ( fabs(schedule.mT0 - schedule.mT1) < 1e-9 )
205  return {schedule.mT0, schedule.mT0};
206 
207  auto realDuration = nSamples / mRate;
208  if (schedule.ReversedTime())
209  realDuration *= -1.0;
210 
211  if (schedule.mEnvelope)
212  trackTime =
213  schedule.SolveWarpedLength(trackTime, realDuration);
214  else
215  trackTime += realDuration;
216 
217  return { trackTime, trackTime };
218 }
219 
221 {
222  // This executes in the TrackBufferExchange thread
223  auto data = schedule.mMessageChannel.Read();
224  if (data.mT0 >= data.mT1)
225  // Ignore empty region
226  return;
227 
228  auto mine = std::tie(schedule.mT0, schedule.mT1);
229  auto theirs = std::tie(data.mT0, data.mT1);
230  if (mine != theirs) {
231  mine = theirs;
232  schedule.mWarpedLength = schedule.RealDuration(schedule.mT1);
233  auto newTime = std::clamp(
234  schedule.mTimeQueue.GetLastTime(), schedule.mT0, schedule.mT1);
235  if (newTime == schedule.mT1)
236  newTime = schedule.mT0;
237 
238  // So that the play head will redraw in the right place:
239  schedule.mTimeQueue.SetLastTime(newTime);
240 
241  // Setup for the next visit to RepositionPlayback:
242  schedule.RealTimeInit(newTime);
243  const auto realTimeRemaining = std::max(0.0, schedule.RealTimeRemaining());
244  mRemaining = realTimeRemaining * mRate;
245  mKicked = true;
246  }
247 }
248 
250  PlaybackSchedule &schedule, const Mixers &playbackMixers, size_t, size_t )
251 {
252  // msmeyer: If playing looped, check if we are at the end of the buffer
253  // and if yes, restart from the beginning.
254  if (mRemaining <= 0)
255  {
256  for (auto &pMixer : playbackMixers)
257  pMixer->SetTimesAndSpeed( schedule.mT0, schedule.mT1, 1.0, mKicked );
258  schedule.RealTimeRestart();
259  }
260  else if (mKicked)
261  {
262  const auto time = schedule.mTimeQueue.GetLastTime();
263  for (auto &pMixer : playbackMixers) {
264  // So that the mixer will fetch the next samples from the right place:
265  pMixer->SetTimesAndSpeed( schedule.mT0, schedule.mT1, 1.0 );
266  pMixer->Reposition(time, true);
267  }
268  }
269  mKicked = false; // Ow! Stop it! Mo-o-o-om!
270  return false;
271 }
272 
274 {
275  return true;
276 }
277 
279  const double t0, const double t1,
280  const AudioIOStartStreamOptions &options,
281  const RecordingSchedule *pRecordingSchedule )
282 {
283  mpPlaybackPolicy.reset();
284 
285  if ( pRecordingSchedule )
286  // It does not make sense to apply the time warp during overdub recording,
287  // which defeats the purpose of making the recording synchronized with
288  // the existing audio. (Unless we figured out the inverse warp of the
289  // captured samples in real time.)
290  // So just quietly ignore the time track.
291  mEnvelope = nullptr;
292  else
293  mEnvelope = options.envelope;
294 
295  mT0 = t0;
296  if (pRecordingSchedule)
297  mT0 -= pRecordingSchedule->mPreRoll;
298 
299  mT1 = t1;
300  if (pRecordingSchedule)
301  // adjust mT1 so that we don't give paComplete too soon to fill up the
302  // desired length of recording
303  mT1 -= pRecordingSchedule->mLatencyCorrection;
304 
305  // Main thread's initialization of mTime
306  SetTrackTime( mT0 );
307 
308  if (options.policyFactory)
309  mpPlaybackPolicy = options.policyFactory();
310 
311  mWarpedTime = 0.0;
312  mWarpedLength = RealDuration(mT1);
313 
314  mPolicyValid.store(true, std::memory_order_release);
315 
316  mMessageChannel.Initialize();
317  mMessageChannel.Write( { mT0, mT1 } );
318 }
319 
320 double PlaybackSchedule::ClampTrackTime( double trackTime ) const
321 {
322  if (ReversedTime())
323  return std::max(mT1, std::min(mT0, trackTime));
324  else
325  return std::max(mT0, std::min(mT1, trackTime));
326 }
327 
328 double PlaybackSchedule::ComputeWarpedLength(double t0, double t1) const
329 {
330  if (mEnvelope)
331  return mEnvelope->IntegralOfInverse(t0, t1);
332  else
333  return t1 - t0;
334 }
335 
336 double PlaybackSchedule::SolveWarpedLength(double t0, double length) const
337 {
338  if (mEnvelope)
339  return mEnvelope->SolveIntegralOfInverse(t0, length);
340  else
341  return t0 + length;
342 }
343 
344 double PlaybackSchedule::RealDuration(double trackTime1) const
345 {
346  return fabs(ComputeWarpedLength(mT0, trackTime1));
347 }
348 
350 {
351  return mWarpedLength - mWarpedTime;
352 }
353 
354 void PlaybackSchedule::RealTimeAdvance( double increment )
355 {
356  mWarpedTime += increment;
357 }
358 
359 void PlaybackSchedule::RealTimeInit( double trackTime )
360 {
361  mWarpedTime = RealDuration( trackTime );
362 }
363 
365 {
366  mWarpedTime = 0;
367 }
368 
370 {
371  return mDuration - Consumed();
372 }
373 
375 {
376  return std::max( 0.0, mPosition + TotalCorrection() );
377 }
378 
380 {
381  return std::max(0.0, -( mPosition + TotalCorrection() ) );
382 }
383 
385 {
386  mData = Records{};
387  mHead = {};
388  mTail = {};
389 }
390 
392 {
393  mData.resize(size);
394 }
395 
397  PlaybackSchedule &schedule, size_t nSamples )
398 {
399  auto &policy = schedule.GetPolicy();
400 
401  if ( mData.empty() )
402  // Recording only. Don't fill the queue.
403  return;
404 
405  // Don't check available space: assume it is enough because of coordination
406  // with RingBuffer.
407  auto index = mTail.mIndex;
408  auto time = mLastTime;
409  auto remainder = mTail.mRemainder;
410  auto space = TimeQueueGrainSize - remainder;
411  const auto size = mData.size();
412 
413  while ( nSamples >= space ) {
414  auto times = policy.AdvancedTrackTime( schedule, time, space );
415  time = times.second;
416  if (!std::isfinite(time))
417  time = times.first;
418  index = (index + 1) % size;
419  mData[ index ].timeValue = time;
420  nSamples -= space;
421  remainder = 0;
422  space = TimeQueueGrainSize;
423  }
424 
425  // Last odd lot
426  if ( nSamples > 0 ) {
427  auto times = policy.AdvancedTrackTime( schedule, time, nSamples );
428  time = times.second;
429  if (!std::isfinite(time))
430  time = times.first;
431  }
432 
433  mLastTime = time;
434  mTail.mRemainder = remainder + nSamples;
435  mTail.mIndex = index;
436 }
437 
439 {
440  return mLastTime;
441 }
442 
444 {
445  mLastTime = time;
446 }
447 
448 double PlaybackSchedule::TimeQueue::Consumer( size_t nSamples, double rate )
449 {
450  if ( mData.empty() ) {
451  // Recording only. No scrub or playback time warp. Don't use the queue.
452  return ( mLastTime += nSamples / rate );
453  }
454 
455  // Don't check available space: assume it is enough because of coordination
456  // with RingBuffer.
457  auto remainder = mHead.mRemainder;
458  auto space = TimeQueueGrainSize - remainder;
459  const auto size = mData.size();
460  if ( nSamples >= space ) {
461  remainder = 0,
462  mHead.mIndex = (mHead.mIndex + 1) % size,
463  nSamples -= space;
464  if ( nSamples >= TimeQueueGrainSize )
465  mHead.mIndex =
466  (mHead.mIndex + ( nSamples / TimeQueueGrainSize ) ) % size,
467  nSamples %= TimeQueueGrainSize;
468  }
469  mHead.mRemainder = remainder + nSamples;
470  return mData[ mHead.mIndex ].timeValue;
471 }
472 
474 {
475  mHead = mTail = {};
476  mLastTime = time;
477  if ( !mData.empty() )
478  mData[0].timeValue = time;
479 }
480 
481 #include "ViewInfo.h"
483 {
484  // This executes in the main thread
485  auto *pRegion = evt.pRegion.get();
486  if ( !pRegion )
487  return;
488  const auto &region = *pRegion;
489 
490  mMessageChannel.Write( { region.GetStart(), region.GetEnd() } );
491 }
size
size_t size
Definition: ffmpeg-2.3.6-single-header.h:412
AudioIOBase.h
RecordingSchedule::mLatencyCorrection
double mLatencyCorrection
Definition: PlaybackSchedule.h:133
PlaybackSchedule::TimeQueue::SetLastTime
void SetLastTime(double time)
Definition: PlaybackSchedule.cpp:443
LoopingPlaybackPolicy::MessageConsumer
void MessageConsumer(PlaybackSchedule &schedule) override
May be called between AdvancedTrackTime() and RepositionPlayback()
Definition: PlaybackSchedule.cpp:220
PlaybackSchedule::GetPolicy
PlaybackPolicy & GetPolicy()
Definition: PlaybackSchedule.cpp:136
PlaybackSchedule::mT1
double mT1
Playback ends at offset of mT1, which is measured in seconds. Note that mT1 may be less than mT0 duri...
Definition: PlaybackSchedule.h:273
PlaybackSchedule::mT0
double mT0
Playback starts at offset of mT0, which is measured in seconds.
Definition: PlaybackSchedule.h:271
PlaybackSchedule::mWarpedTime
double mWarpedTime
Definition: PlaybackSchedule.h:283
Mixer::WarpOptions
Definition: Mix.h:81
Mix.h
PlaybackSchedule::TimeQueue::Prime
void Prime(double time)
Empty the queue and reassign the last produced time.
Definition: PlaybackSchedule.cpp:473
PlaybackPolicy::MessageConsumer
virtual void MessageConsumer(PlaybackSchedule &schedule)
May be called between AdvancedTrackTime() and RepositionPlayback()
Definition: PlaybackSchedule.cpp:63
PlaybackSchedule::mMessageChannel
MessageBuffer< SlotData > mMessageChannel
Definition: PlaybackSchedule.h:372
PlaybackPolicy::Looping
virtual bool Looping(const PlaybackSchedule &schedule) const
Definition: PlaybackSchedule.cpp:125
PlaybackPolicy::~PlaybackPolicy
virtual ~PlaybackPolicy()=0
PlaybackPolicy::Done
virtual bool Done(PlaybackSchedule &schedule, unsigned long outputFrames)
Returns true if schedule.GetTrackTime() has reached the end of playback.
Definition: PlaybackSchedule.cpp:43
AudioIOStartStreamOptions::envelope
const BoundedEnvelope * envelope
Definition: AudioIOBase.h:57
AudioIOStartStreamOptions::policyFactory
PolicyFactory policyFactory
Definition: AudioIOBase.h:74
PlaybackSchedule::Init
void Init(double t0, double t1, const AudioIOStartStreamOptions &options, const RecordingSchedule *pRecordingSchedule)
Definition: PlaybackSchedule.cpp:278
LoopingPlaybackPolicy::Looping
bool Looping(const PlaybackSchedule &) const override
Definition: PlaybackSchedule.cpp:273
PlaybackSchedule::TimeQueue::Resize
void Resize(size_t size)
Definition: PlaybackSchedule.cpp:391
PlaybackPolicy::BufferTimes
Times are in seconds.
Definition: PlaybackSchedule.h:189
LoopingPlaybackPolicy::Done
bool Done(PlaybackSchedule &schedule, unsigned long) override
Returns true if schedule.GetTrackTime() has reached the end of playback.
Definition: PlaybackSchedule.cpp:160
LoopingPlaybackPolicy::GetPlaybackSlice
PlaybackSlice GetPlaybackSlice(PlaybackSchedule &schedule, size_t available) override
Choose length of one fetch of samples from tracks in a call to AudioIO::FillPlayBuffers.
Definition: PlaybackSchedule.cpp:166
LoopingPlaybackPolicy::RepositionPlayback
bool RepositionPlayback(PlaybackSchedule &schedule, const Mixers &playbackMixers, size_t frames, size_t available) override
AudioIO::FillPlayBuffers calls this to update its cursors into tracks for changes of position or spee...
Definition: PlaybackSchedule.cpp:249
PlaybackPolicy::Mixers
std::vector< std::unique_ptr< Mixer > > Mixers
Definition: PlaybackSchedule.h:248
PlaybackSchedule::mTimeQueue
class PlaybackSchedule::TimeQueue mTimeQueue
PlaybackPolicy::AdvancedTrackTime
virtual std::pair< double, double > AdvancedTrackTime(PlaybackSchedule &schedule, double trackTime, size_t nSamples)
Compute a new point in a track's timeline from an old point and a real duration.
Definition: PlaybackSchedule.cpp:100
PlayRegionEvent
Definition: ViewInfo.h:118
PlaybackPolicy::AllowSeek
virtual bool AllowSeek(PlaybackSchedule &schedule)
Whether repositioning commands are allowed during playback.
Definition: PlaybackSchedule.cpp:38
SampleCount.h
PlaybackSchedule.h
RecordingSchedule::ToConsume
double ToConsume() const
Definition: PlaybackSchedule.cpp:369
PlaybackSchedule::ReversedTime
bool ReversedTime() const
True if the end time is before the start time.
Definition: PlaybackSchedule.h:402
PlaybackPolicy::OffsetTrackTime
virtual double OffsetTrackTime(PlaybackSchedule &schedule, double offset)
Called when the play head needs to jump a certain distance.
Definition: PlaybackSchedule.cpp:54
PlaybackPolicy::SleepInterval
virtual std::chrono::milliseconds SleepInterval(PlaybackSchedule &schedule)
How long to wait between calls to AudioIO::TrackBufferExchange.
Definition: PlaybackSchedule.cpp:67
anonymous_namespace{PlaybackSchedule.cpp}::DefaultPlaybackPolicy::~DefaultPlaybackPolicy
~DefaultPlaybackPolicy() override=default
PlaybackSchedule::ClampTrackTime
double ClampTrackTime(double trackTime) const
Clamps argument to be between mT0 and mT1.
Definition: PlaybackSchedule.cpp:320
PlaybackSchedule::TimeQueue::Clear
void Clear()
Definition: PlaybackSchedule.cpp:384
PlaybackPolicy::MixerWarpOptions
virtual Mixer::WarpOptions MixerWarpOptions(PlaybackSchedule &schedule)
Options to use when constructing mixers for each playback track.
Definition: PlaybackSchedule.cpp:27
PlaybackSchedule
Definition: PlaybackSchedule.h:268
PlaybackSchedule::ComputeWarpedLength
double ComputeWarpedLength(double t0, double t1) const
Compute signed duration (in seconds at playback) of the specified region of the track.
Definition: PlaybackSchedule.cpp:328
PlaybackPolicy::RepositionPlayback
virtual bool RepositionPlayback(PlaybackSchedule &schedule, const Mixers &playbackMixers, size_t frames, size_t available)
AudioIO::FillPlayBuffers calls this to update its cursors into tracks for changes of position or spee...
Definition: PlaybackSchedule.cpp:119
PlaybackPolicy::Initialize
virtual void Initialize(PlaybackSchedule &schedule, double rate)
Called before starting an audio stream.
Definition: PlaybackSchedule.cpp:21
AudioIOStartStreamOptions
struct holding stream options, including a pointer to the time warp info and AudioIOListener and whet...
Definition: AudioIOBase.h:44
PlaybackPolicy::SuggestedBufferTimes
virtual BufferTimes SuggestedBufferTimes(PlaybackSchedule &schedule)
Provide hints for construction of playback RingBuffer objects.
Definition: PlaybackSchedule.cpp:33
ViewInfo.h
LoopingPlaybackPolicy::SuggestedBufferTimes
BufferTimes SuggestedBufferTimes(PlaybackSchedule &schedule) override
Provide hints for construction of playback RingBuffer objects.
Definition: PlaybackSchedule.cpp:153
Envelope.h
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
PlaybackSchedule::TimeQueue::Records
std::vector< Record > Records
Definition: PlaybackSchedule.h:352
PlaybackSchedule::RealTimeAdvance
void RealTimeAdvance(double increment)
Definition: PlaybackSchedule.cpp:354
TimeQueueGrainSize
constexpr size_t TimeQueueGrainSize
Definition: PlaybackSchedule.h:25
anonymous_namespace{Ruler.cpp}::ComputeWarpedLength
double ComputeWarpedLength(const Envelope &env, double t0, double t1)
Definition: Ruler.cpp:989
sampleCount
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
LoopingPlaybackPolicy::~LoopingPlaybackPolicy
~LoopingPlaybackPolicy() override
PlaybackPolicy::GetPlaybackSlice
virtual PlaybackSlice GetPlaybackSlice(PlaybackSchedule &schedule, size_t available)
Choose length of one fetch of samples from tracks in a call to AudioIO::FillPlayBuffers.
Definition: PlaybackSchedule.cpp:74
PlaybackSlice
Describes an amount of contiguous (but maybe time-warped) data to be extracted from tracks to play.
Definition: PlaybackSchedule.h:152
PlaybackSchedule::TimeQueue::GetLastTime
double GetLastTime() const
Return the last time saved by Producer.
Definition: PlaybackSchedule.cpp:438
PlaybackSchedule::GetTrackTime
double GetTrackTime() const
Get current track time value, unadjusted.
Definition: PlaybackSchedule.h:411
PlaybackSchedule::RealTimeInit
void RealTimeInit(double trackTime)
Definition: PlaybackSchedule.cpp:359
RecordingSchedule::ToDiscard
double ToDiscard() const
Definition: PlaybackSchedule.cpp:379
PlaybackSchedule::mWarpedLength
double mWarpedLength
Definition: PlaybackSchedule.h:288
RecordingSchedule
Definition: PlaybackSchedule.h:131
anonymous_namespace{PlaybackSchedule.cpp}::DefaultPlaybackPolicy
Definition: PlaybackSchedule.cpp:131
PlayRegionEvent::pRegion
wxWeakRef< PlayRegion > pRegion
Definition: ViewInfo.h:122
PlaybackPolicy::mRate
double mRate
Definition: PlaybackSchedule.h:265
PlaybackSchedule::SolveWarpedLength
double SolveWarpedLength(double t0, double length) const
Compute how much unwarped time must have elapsed if length seconds of warped time has elapsed,...
Definition: PlaybackSchedule.cpp:336
PlaybackSchedule::TimeQueue::Producer
void Producer(PlaybackSchedule &schedule, size_t nSamples)
Enqueue track time value advanced by nSamples according to schedule's PlaybackPolicy.
Definition: PlaybackSchedule.cpp:396
RecordingSchedule::Consumed
double Consumed() const
Definition: PlaybackSchedule.cpp:374
PlaybackPolicy::Finalize
virtual void Finalize(PlaybackSchedule &schedule)
Called after stopping of an audio stream or an unsuccessful start.
Definition: PlaybackSchedule.cpp:25
LoopingPlaybackPolicy::AdvancedTrackTime
std::pair< double, double > AdvancedTrackTime(PlaybackSchedule &schedule, double trackTime, size_t nSamples) override
Compute a new point in a track's timeline from an old point and a real duration.
Definition: PlaybackSchedule.cpp:195
PlaybackSchedule::mEnvelope
const BoundedEnvelope * mEnvelope
Definition: PlaybackSchedule.h:298
PlaybackSchedule::RealTimeRestart
void RealTimeRestart()
Definition: PlaybackSchedule.cpp:364
PlaybackSchedule::RealTimeRemaining
double RealTimeRemaining() const
Definition: PlaybackSchedule.cpp:349
PlaybackSchedule::RealDuration
double RealDuration(double trackTime1) const
Definition: PlaybackSchedule.cpp:344
PlaybackSchedule::TimeQueue::Consumer
double Consumer(size_t nSamples, double rate)
Find the track time value nSamples after the last consumed sample.
Definition: PlaybackSchedule.cpp:448
PlaybackPolicy
Directs which parts of tracks to fetch for playback.
Definition: PlaybackSchedule.h:173
RecordingSchedule::mPreRoll
double mPreRoll
Definition: PlaybackSchedule.h:132
PlaybackSchedule::MessageProducer
void MessageProducer(PlayRegionEvent &evt)
Definition: PlaybackSchedule.cpp:482