Audacity 3.2.0
Classes | Public Member Functions | Private Member Functions | Private Attributes | List of all members
NewDefaultPlaybackPolicy Class Referencefinal

#include <PlaybackSchedule.h>

Inheritance diagram for NewDefaultPlaybackPolicy:
[legend]
Collaboration diagram for NewDefaultPlaybackPolicy:
[legend]

Classes

struct  SlotData
 

Public Member Functions

 NewDefaultPlaybackPolicy (AudacityProject &project, double trackEndTime, double loopEndTime, bool loopEnabled, bool variableSpeed)
 
 ~NewDefaultPlaybackPolicy () override
 
void Initialize (PlaybackSchedule &schedule, double rate) override
 Called before starting an audio stream. More...
 
Mixer::WarpOptions MixerWarpOptions (PlaybackSchedule &schedule) override
 Options to use when constructing mixers for each playback track. More...
 
BufferTimes SuggestedBufferTimes (PlaybackSchedule &schedule) override
 Provide hints for construction of playback RingBuffer objects. More...
 
bool Done (PlaybackSchedule &schedule, unsigned long) override
 Returns true if schedule.GetTrackTime() has reached the end of playback. More...
 
PlaybackSlice GetPlaybackSlice (PlaybackSchedule &schedule, size_t available) override
 Choose length of one fetch of samples from tracks in a call to AudioIO::FillPlayBuffers. More...
 
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. More...
 
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 speed. More...
 
bool Looping (const PlaybackSchedule &) const override
 
- Public Member Functions inherited from PlaybackPolicy
virtual ~PlaybackPolicy ()=0
 
virtual void Initialize (PlaybackSchedule &schedule, double rate)
 Called before starting an audio stream. More...
 
virtual void Finalize (PlaybackSchedule &schedule)
 Called after stopping of an audio stream or an unsuccessful start. More...
 
virtual Mixer::WarpOptions MixerWarpOptions (PlaybackSchedule &schedule)
 Options to use when constructing mixers for each playback track. More...
 
virtual BufferTimes SuggestedBufferTimes (PlaybackSchedule &schedule)
 Provide hints for construction of playback RingBuffer objects. More...
 
virtual bool AllowSeek (PlaybackSchedule &schedule)
 Whether repositioning commands are allowed during playback. More...
 
virtual bool Done (PlaybackSchedule &schedule, unsigned long outputFrames)
 Returns true if schedule.GetTrackTime() has reached the end of playback. More...
 
virtual double OffsetTrackTime (PlaybackSchedule &schedule, double offset)
 Called when the play head needs to jump a certain distance. More...
 
virtual std::chrono::milliseconds SleepInterval (PlaybackSchedule &schedule)
 How long to wait between calls to AudioIO::TrackBufferExchange. More...
 
virtual PlaybackSlice GetPlaybackSlice (PlaybackSchedule &schedule, size_t available)
 Choose length of one fetch of samples from tracks in a call to AudioIO::FillPlayBuffers. More...
 
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. More...
 
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 speed. More...
 
virtual bool Looping (const PlaybackSchedule &schedule) const
 

Private Member Functions

bool RevertToOldDefault (const PlaybackSchedule &schedule) const
 
void WriteMessage ()
 
double GetPlaySpeed ()
 

Private Attributes

AudacityProjectmProject
 
MessageBuffer< SlotDatamMessageChannel
 
Observer::Subscription mRegionSubscription
 
Observer::Subscription mSpeedSubscription
 
double mLastPlaySpeed { 1.0 }
 
const double mTrackEndTime
 
double mLoopEndTime
 
size_t mRemaining { 0 }
 
bool mProgress { true }
 
bool mLoopEnabled { true }
 
bool mVariableSpeed { false }
 

Additional Inherited Members

- Public Types inherited from PlaybackPolicy
using Duration = std::chrono::duration< double >
 
using Mixers = std::vector< std::unique_ptr< Mixer > >
 
- Protected Attributes inherited from PlaybackPolicy
double mRate = 0
 

Detailed Description

Definition at line 329 of file PlaybackSchedule.h.

Constructor & Destructor Documentation

◆ NewDefaultPlaybackPolicy()

NewDefaultPlaybackPolicy::NewDefaultPlaybackPolicy ( AudacityProject project,
double  trackEndTime,
double  loopEndTime,
bool  loopEnabled,
bool  variableSpeed 
)

Definition at line 169 of file PlaybackSchedule.cpp.

172 : mProject{ project }
173 , mTrackEndTime{ trackEndTime }
174 , mLoopEndTime{ loopEndTime }
175 , mLoopEnabled{ loopEnabled }
176 , mVariableSpeed{ variableSpeed }
177{}
AudacityProject & mProject

◆ ~NewDefaultPlaybackPolicy()

NewDefaultPlaybackPolicy::~NewDefaultPlaybackPolicy ( )
overridedefault

Member Function Documentation

◆ AdvancedTrackTime()

std::pair< double, double > NewDefaultPlaybackPolicy::AdvancedTrackTime ( PlaybackSchedule schedule,
double  trackTime,
size_t  nSamples 
)
overridevirtual

Compute a new point in a track's timeline from an old point and a real duration.

Needed because playback might be at non-unit speed.

Called one or more times between GetPlaybackSlice and RepositionPlayback, until the sum of the nSamples values equals the most recent playback slice (including any trailing silence).

Returns
a pair, which indicates a discontinuous jump when its members are not equal, or specially the end of playback when the second member is infinite

Reimplemented from PlaybackPolicy.

Definition at line 274 of file PlaybackSchedule.cpp.

276{
277 bool revert = RevertToOldDefault(schedule);
278 if (!mVariableSpeed && revert)
279 return PlaybackPolicy::AdvancedTrackTime(schedule, trackTime, nSamples);
280
281 mRemaining -= std::min(mRemaining, nSamples);
282 if ( mRemaining == 0 && !revert )
283 // Wrap to start
284 return { schedule.mT1, schedule.mT0 };
285
286 // Defense against cases that might cause loops not to terminate
287 if ( fabs(schedule.mT0 - schedule.mT1) < 1e-9 )
288 return {schedule.mT0, schedule.mT0};
289
290 auto realDuration = (nSamples / mRate) * mLastPlaySpeed;
291 if (schedule.ReversedTime())
292 realDuration *= -1.0;
293
294 if (schedule.mEnvelope)
295 trackTime =
296 schedule.SolveWarpedLength(trackTime, realDuration);
297 else
298 trackTime += realDuration;
299
300 return { trackTime, trackTime };
301}
int min(int a, int b)
bool RevertToOldDefault(const PlaybackSchedule &schedule) const
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.
double mT0
Playback starts at offset of mT0, which is measured in seconds.
double mT1
Playback ends at offset of mT1, which is measured in seconds. Note that mT1 may be less than mT0 duri...
double SolveWarpedLength(double t0, double length) const
Compute how much unwarped time must have elapsed if length seconds of warped time has elapsed,...
bool ReversedTime() const
True if the end time is before the start time.
const BoundedEnvelope * mEnvelope

References PlaybackPolicy::AdvancedTrackTime(), PlaybackSchedule::mEnvelope, min(), mLastPlaySpeed, PlaybackPolicy::mRate, mRemaining, PlaybackSchedule::mT0, PlaybackSchedule::mT1, mVariableSpeed, PlaybackSchedule::ReversedTime(), RevertToOldDefault(), and PlaybackSchedule::SolveWarpedLength().

Here is the call graph for this function:

◆ Done()

bool NewDefaultPlaybackPolicy::Done ( PlaybackSchedule schedule,
unsigned long  outputFrames 
)
overridevirtual

Returns true if schedule.GetTrackTime() has reached the end of playback.

Parameters
outputFrameshow many playback frames were taken from RingBuffers

Reimplemented from PlaybackPolicy.

Definition at line 222 of file PlaybackSchedule.cpp.

224{
225 if (RevertToOldDefault(schedule)) {
226 auto diff = schedule.GetTrackTime() - schedule.mT1;
227 if (schedule.ReversedTime())
228 diff *= -1;
229 return sampleCount(floor(diff * mRate + 0.5)) >= 0;
230 }
231 return false;
232}
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
double GetTrackTime() const
Get current track time value, unadjusted.

References PlaybackSchedule::GetTrackTime(), PlaybackPolicy::mRate, PlaybackSchedule::mT1, PlaybackSchedule::ReversedTime(), and RevertToOldDefault().

Here is the call graph for this function:

◆ GetPlaybackSlice()

PlaybackSlice NewDefaultPlaybackPolicy::GetPlaybackSlice ( PlaybackSchedule schedule,
size_t  available 
)
overridevirtual

Choose length of one fetch of samples from tracks in a call to AudioIO::FillPlayBuffers.

Parameters
availableupper bound for the length of the fetch

Reimplemented from PlaybackPolicy.

Definition at line 235 of file PlaybackSchedule.cpp.

237{
238 // How many samples to produce for each channel.
239 const auto realTimeRemaining = std::max(0.0, schedule.RealTimeRemaining());
240 mRemaining = realTimeRemaining * mRate / mLastPlaySpeed;
241
242 auto frames = available;
243 auto toProduce = frames;
244 double deltat = (frames / mRate) * mLastPlaySpeed;
245
246 if (deltat > realTimeRemaining) {
247 toProduce = frames = 0.5 + (realTimeRemaining * mRate) / mLastPlaySpeed;
248 auto realTime = realTimeRemaining;
249 double extra = 0;
250 if (RevertToOldDefault(schedule)) {
251 // Produce some extra silence so that the time queue consumer can
252 // satisfy its end condition
253 const double extraRealTime =
255 extra = std::min( extraRealTime, deltat - realTimeRemaining );
256 frames = ((realTimeRemaining + extra) * mRate) / mLastPlaySpeed;
257 }
258 schedule.RealTimeAdvance( realTimeRemaining + extra );
259 }
260 else
261 schedule.RealTimeAdvance( deltat );
262
263 // Don't fall into an infinite loop, if loop-playing a selection
264 // that is so short, it has no samples: detect that case
265 if (frames == 0) {
266 bool progress = (schedule.mWarpedTime != 0.0);
267 if (!progress)
268 // Cause FillPlayBuffers to make progress, filling all available with 0
269 frames = available, toProduce = 0;
270 }
271 return { available, frames, toProduce };
272}
constexpr size_t TimeQueueGrainSize
double RealTimeRemaining() const
void RealTimeAdvance(double increment)

References min(), mLastPlaySpeed, PlaybackPolicy::mRate, mRemaining, PlaybackSchedule::mWarpedTime, PlaybackSchedule::RealTimeAdvance(), PlaybackSchedule::RealTimeRemaining(), RevertToOldDefault(), and TimeQueueGrainSize.

Here is the call graph for this function:

◆ GetPlaySpeed()

double NewDefaultPlaybackPolicy::GetPlaySpeed ( )
private

Definition at line 413 of file PlaybackSchedule.cpp.

414{
415 return mVariableSpeed
417 : 1.0;
418}
double GetPlaySpeed() const
static ProjectAudioIO & Get(AudacityProject &project)

References ProjectAudioIO::Get(), ProjectAudioIO::GetPlaySpeed(), mProject, and mVariableSpeed.

Referenced by Initialize(), MixerWarpOptions(), and WriteMessage().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Initialize()

void NewDefaultPlaybackPolicy::Initialize ( PlaybackSchedule schedule,
double  rate 
)
overridevirtual

Called before starting an audio stream.

Reimplemented from PlaybackPolicy.

Definition at line 181 of file PlaybackSchedule.cpp.

183{
184 PlaybackPolicy::Initialize(schedule, rate);
187 schedule.mT0, mLoopEndTime, mLoopEnabled } );
188
189 auto callback = [this](auto&){ WriteMessage(); };
192 if (mVariableSpeed)
194}
Observer::Subscription mSpeedSubscription
MessageBuffer< SlotData > mMessageChannel
Observer::Subscription mRegionSubscription
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
Definition: Observer.h:199
virtual void Initialize(PlaybackSchedule &schedule, double rate)
Called before starting an audio stream.
PlayRegion playRegion
Definition: ViewInfo.h:217
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235

References ViewInfo::Get(), ProjectAudioIO::Get(), GetPlaySpeed(), PlaybackPolicy::Initialize(), mLastPlaySpeed, mLoopEnabled, mLoopEndTime, mMessageChannel, mProject, mRegionSubscription, mSpeedSubscription, PlaybackSchedule::mT0, mVariableSpeed, ViewInfo::playRegion, Observer::Publisher< Message, NotifyAll >::Subscribe(), and WriteMessage().

Here is the call graph for this function:

◆ Looping()

bool NewDefaultPlaybackPolicy::Looping ( const PlaybackSchedule schedule) const
overridevirtual

be removed

Reimplemented from PlaybackPolicy.

Definition at line 400 of file PlaybackSchedule.cpp.

401{
402 return mLoopEnabled;
403}

References mLoopEnabled.

◆ MixerWarpOptions()

Mixer::WarpOptions NewDefaultPlaybackPolicy::MixerWarpOptions ( PlaybackSchedule schedule)
overridevirtual

Options to use when constructing mixers for each playback track.

Reimplemented from PlaybackPolicy.

Definition at line 196 of file PlaybackSchedule.cpp.

198{
199 if (mVariableSpeed)
200 // Enable variable rate mixing
201 return Mixer::WarpOptions(0.01, 32.0, GetPlaySpeed());
202 else
203 return PlaybackPolicy::MixerWarpOptions(schedule);
204}
MixerOptions::Warp WarpOptions
Definition: Mix.h:28
virtual Mixer::WarpOptions MixerWarpOptions(PlaybackSchedule &schedule)
Options to use when constructing mixers for each playback track.

References GetPlaySpeed(), PlaybackPolicy::MixerWarpOptions(), and mVariableSpeed.

Here is the call graph for this function:

◆ RepositionPlayback()

bool NewDefaultPlaybackPolicy::RepositionPlayback ( PlaybackSchedule schedule,
const Mixers playbackMixers,
size_t  frames,
size_t  available 
)
overridevirtual

AudioIO::FillPlayBuffers calls this to update its cursors into tracks for changes of position or speed.

Returns
if true, AudioIO::FillPlayBuffers stops producing samples even if space remains
Parameters
frameshow many samples were just now buffered for play
availablehow many more samples may be buffered

Reimplemented from PlaybackPolicy.

Definition at line 303 of file PlaybackSchedule.cpp.

306{
307 // This executes in the TrackBufferExchange thread
308 auto data = mMessageChannel.Read();
309
310 bool speedChange = false;
311 if (mVariableSpeed) {
312 speedChange = (mLastPlaySpeed != data.mPlaySpeed);
313 mLastPlaySpeed = data.mPlaySpeed;
314 }
315
316 bool empty = (data.mT0 >= data.mT1);
317 bool kicked = false;
318
319 // Amount in seconds by which right boundary can be moved left of the play
320 // head, yet loop play in progress will still capture the head
321 constexpr auto allowance = 0.5;
322
323 // Looping may become enabled if the main thread said so, but require too
324 // that the loop region is non-empty and the play head is not far to its
325 // right
326 bool loopWasEnabled = !RevertToOldDefault(schedule);
327 mLoopEnabled = data.mLoopEnabled && !empty &&
328 schedule.mTimeQueue.GetLastTime() <= data.mT1 + allowance;
329
330 // Four cases: looping transitions off, or transitions on, or stays on,
331 // or stays off.
332 // Besides which, the variable speed slider may have changed.
333
334 // If looping transitions on, or remains on and the region changed,
335 // adjust the schedule...
336 auto mine = std::tie(schedule.mT0, mLoopEndTime);
337 auto theirs = std::tie(data.mT0, data.mT1);
338 if ( mLoopEnabled ? (mine != theirs) : loopWasEnabled ) {
339 kicked = true;
340 if (!empty) {
341 mine = theirs;
342 schedule.mT1 = data.mT1;
343 }
344 if (!mLoopEnabled)
345 // Continue play to the end
346 schedule.mT1 = std::max(schedule.mT0, mTrackEndTime);
347 schedule.mWarpedLength = schedule.RealDuration(schedule.mT1);
348
349 auto newTime = schedule.mTimeQueue.GetLastTime();
350#if 0
351 // This would make play jump forward or backward into the adjusted
352 // looping region if not already in it
353 newTime = std::clamp(newTime, schedule.mT0, schedule.mT1);
354#endif
355
356 if (newTime >= schedule.mT1 && mLoopEnabled)
357 newTime = schedule.mT0;
358
359 // So that the play head will redraw in the right place:
360 schedule.mTimeQueue.SetLastTime(newTime);
361
362 schedule.RealTimeInit(newTime);
363 const auto realTimeRemaining = std::max(0.0, schedule.RealTimeRemaining());
364 mRemaining = realTimeRemaining * mRate / mLastPlaySpeed;
365 }
366 else if (speedChange)
367 // Don't return early
368 kicked = true;
369 else {
370 // ... else the region did not change, or looping is now off, in
371 // which case we have nothing special to do
372 if (RevertToOldDefault(schedule))
373 return PlaybackPolicy::RepositionPlayback( schedule, playbackMixers,
374 frames, available);
375 }
376
377 // msmeyer: If playing looped, check if we are at the end of the buffer
378 // and if yes, restart from the beginning.
379 if (mRemaining <= 0)
380 {
381 // Looping jumps left
382 for (auto &pMixer : playbackMixers)
383 pMixer->SetTimesAndSpeed(
384 schedule.mT0, schedule.mT1, mLastPlaySpeed, true );
385 schedule.RealTimeRestart();
386 }
387 else if (kicked)
388 {
389 // Play bounds need redefinition
390 const auto time = schedule.mTimeQueue.GetLastTime();
391 for (auto &pMixer : playbackMixers) {
392 // So that the mixer will fetch the next samples from the right place:
393 pMixer->SetTimesAndSpeed( time, schedule.mT1, mLastPlaySpeed );
394 pMixer->Reposition(time, true);
395 }
396 }
397 return false;
398}
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...
double GetLastTime() const
Return the last time saved by Producer.
class PlaybackSchedule::TimeQueue mTimeQueue
double RealDuration(double trackTime1) const
void RealTimeInit(double trackTime)

References PlaybackSchedule::TimeQueue::GetLastTime(), mLastPlaySpeed, mLoopEnabled, mLoopEndTime, mMessageChannel, PlaybackPolicy::mRate, mRemaining, PlaybackSchedule::mT0, PlaybackSchedule::mT1, PlaybackSchedule::mTimeQueue, mTrackEndTime, mVariableSpeed, PlaybackSchedule::mWarpedLength, PlaybackSchedule::RealDuration(), PlaybackSchedule::RealTimeInit(), PlaybackSchedule::RealTimeRemaining(), PlaybackSchedule::RealTimeRestart(), PlaybackPolicy::RepositionPlayback(), RevertToOldDefault(), and PlaybackSchedule::TimeQueue::SetLastTime().

Here is the call graph for this function:

◆ RevertToOldDefault()

bool NewDefaultPlaybackPolicy::RevertToOldDefault ( const PlaybackSchedule schedule) const
private

Definition at line 215 of file PlaybackSchedule.cpp.

216{
217 return !mLoopEnabled ||
218 // Even if loop is enabled, ignore it if right of looping region
220}

References PlaybackSchedule::TimeQueue::GetLastTime(), mLoopEnabled, mLoopEndTime, and PlaybackSchedule::mTimeQueue.

Referenced by AdvancedTrackTime(), Done(), GetPlaybackSlice(), and RepositionPlayback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SuggestedBufferTimes()

PlaybackPolicy::BufferTimes NewDefaultPlaybackPolicy::SuggestedBufferTimes ( PlaybackSchedule schedule)
overridevirtual

Provide hints for construction of playback RingBuffer objects.

Reimplemented from PlaybackPolicy.

Definition at line 207 of file PlaybackSchedule.cpp.

208{
209 // Shorter times than in the default policy so that responses to changes of
210 // loop region or speed slider don't lag too much
211 using namespace std::chrono;
212 return { 0.05s, 0.05s, 0.25s };
213}

◆ WriteMessage()

void NewDefaultPlaybackPolicy::WriteMessage ( )
private

Definition at line 405 of file PlaybackSchedule.cpp.

406{
407 const auto &region = ViewInfo::Get( mProject ).playRegion;
408 mMessageChannel.Write( { GetPlaySpeed(),
409 region.GetStart(), region.GetEnd(), region.Active()
410 } );
411}

References ViewInfo::Get(), GetPlaySpeed(), mMessageChannel, mProject, and ViewInfo::playRegion.

Referenced by Initialize().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ mLastPlaySpeed

double NewDefaultPlaybackPolicy::mLastPlaySpeed { 1.0 }
private

◆ mLoopEnabled

bool NewDefaultPlaybackPolicy::mLoopEnabled { true }
private

Definition at line 385 of file PlaybackSchedule.h.

Referenced by Initialize(), Looping(), RepositionPlayback(), and RevertToOldDefault().

◆ mLoopEndTime

double NewDefaultPlaybackPolicy::mLoopEndTime
private

Definition at line 382 of file PlaybackSchedule.h.

Referenced by Initialize(), RepositionPlayback(), and RevertToOldDefault().

◆ mMessageChannel

MessageBuffer<SlotData> NewDefaultPlaybackPolicy::mMessageChannel
private

Definition at line 375 of file PlaybackSchedule.h.

Referenced by Initialize(), RepositionPlayback(), and WriteMessage().

◆ mProgress

bool NewDefaultPlaybackPolicy::mProgress { true }
private

Definition at line 384 of file PlaybackSchedule.h.

◆ mProject

AudacityProject& NewDefaultPlaybackPolicy::mProject
private

Definition at line 365 of file PlaybackSchedule.h.

Referenced by GetPlaySpeed(), Initialize(), and WriteMessage().

◆ mRegionSubscription

Observer::Subscription NewDefaultPlaybackPolicy::mRegionSubscription
private

Definition at line 377 of file PlaybackSchedule.h.

Referenced by Initialize().

◆ mRemaining

size_t NewDefaultPlaybackPolicy::mRemaining { 0 }
private

Definition at line 383 of file PlaybackSchedule.h.

Referenced by AdvancedTrackTime(), GetPlaybackSlice(), and RepositionPlayback().

◆ mSpeedSubscription

Observer::Subscription NewDefaultPlaybackPolicy::mSpeedSubscription
private

Definition at line 378 of file PlaybackSchedule.h.

Referenced by Initialize().

◆ mTrackEndTime

const double NewDefaultPlaybackPolicy::mTrackEndTime
private

Definition at line 381 of file PlaybackSchedule.h.

Referenced by RepositionPlayback().

◆ mVariableSpeed

bool NewDefaultPlaybackPolicy::mVariableSpeed { false }
private

The documentation for this class was generated from the following files: