Audacity 3.2.0
PlaybackSchedule.h
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 @file PlaybackSchedule.h
6
7 Paul Licameli split from AudioIOBase.h
8
9 **********************************************************************/
10
11#ifndef __AUDACITY_PLAYBACK_SCHEDULE__
12#define __AUDACITY_PLAYBACK_SCHEDULE__
13
14#include "MemoryX.h"
15#include "MessageBuffer.h"
16#include "Mix.h"
17#include "Observer.h"
18#include <atomic>
19#include <chrono>
20#include <vector>
21
22class AudacityProject;
24class BoundedEnvelope;
25using PRCrossfadeData = std::vector< std::vector < float > >;
26
27constexpr size_t TimeQueueGrainSize = 2000;
28
30 double mPreRoll{};
31 double mLatencyCorrection{}; // negative value usually
32 double mDuration{};
34
35 // These are initialized by the main thread, then updated
36 // only by the thread calling SequenceBufferExchange:
37 double mPosition{};
39
40 double TotalCorrection() const { return mLatencyCorrection - mPreRoll; }
41 double ToConsume() const;
42 double Consumed() const;
43 double ToDiscard() const;
44};
45
46class Mixer;
47struct PlaybackSchedule;
48
51 const size_t frames;
52 const size_t toProduce;
53
55
58 size_t available, size_t frames_, size_t toProduce_)
59 : frames{ std::min(available, frames_) }
60 , toProduce{ std::min(toProduce_, frames) }
61 {}
62};
63
65
71class AUDIO_IO_API PlaybackPolicy {
72public:
73 using Duration = std::chrono::duration<double>;
74
76
77 virtual ~PlaybackPolicy() = 0;
78
80 virtual void Initialize( PlaybackSchedule &schedule, double rate );
81
83 virtual void Finalize( PlaybackSchedule &schedule );
84
86 virtual Mixer::WarpOptions MixerWarpOptions(PlaybackSchedule &schedule);
87
89 struct BufferTimes {
93 };
95 virtual BufferTimes SuggestedBufferTimes(PlaybackSchedule &schedule);
96
98
100 virtual bool AllowSeek( PlaybackSchedule &schedule );
101
103 virtual bool Done( PlaybackSchedule &schedule,
104 unsigned long outputFrames
105 );
106
108
111 virtual double OffsetSequenceTime( PlaybackSchedule &schedule, double offset );
112
114
116 virtual std::chrono::milliseconds
117 SleepInterval( PlaybackSchedule &schedule );
118
120 virtual PlaybackSlice GetPlaybackSlice( PlaybackSchedule &schedule,
121 size_t available
122 );
123
125
135 virtual std::pair<double, double>
136 AdvancedTrackTime( PlaybackSchedule &schedule,
137 double trackTime, size_t nSamples );
138
139 using Mixers = std::vector<std::unique_ptr<Mixer>>;
140
142
145 virtual bool RepositionPlayback(
146 PlaybackSchedule &schedule, const Mixers &playbackMixers,
147 size_t frames,
148 size_t available
149 );
150
152
153 virtual bool Looping( const PlaybackSchedule &schedule ) const;
154
155protected:
156 double mRate = 0;
157};
158
159
160struct AUDIO_IO_API PlaybackSchedule {
162 double mT0;
164 double mT1;
169 std::atomic<double> mTime;
170
175
180
181 // mWarpedTime and mWarpedLength are irrelevant when scrubbing,
182 // else they are used in updating mTime,
183 // and when not scrubbing or playing looped, mTime is also used
184 // in the test for termination of playback.
185
186 // with ComputeWarpedLength, it is now possible the calculate the warped length with 100% accuracy
187 // (ignoring accumulated rounding errors during playback) which fixes the 'missing sound at the end' bug
188
190
207 class AUDIO_IO_API TimeQueue {
208 public:
209
211 TimeQueue(const TimeQueue&) = delete;
212 TimeQueue& operator=(const TimeQueue&) = delete;
213
214
216
217 void Clear();
218 void Init(size_t size);
219
221
223 void Producer( PlaybackSchedule &schedule, PlaybackSlice slice );
224
226 double GetLastTime() const;
227
228 void SetLastTime(double time);
229
231
233 double Consumer( size_t nSamples, double rate );
234
236
238
239 void Prime( double time );
240
241 private:
242 double mLastTime {};
243
249 struct Node final
250 {
251 struct Record final {
252 double timeValue;
253 // More fields to come
254 };
255
256 std::vector<Record> records;
257 std::atomic<int> head { 0 };
258 std::atomic<int> tail { 0 };
261 std::atomic<Node*> next{};
262
266 std::atomic_flag active { ATOMIC_FLAG_INIT };
267
269 size_t offset { 0 };
271 size_t written { 0 };
272
273 };
274
275 Node* mConsumerNode {};
276 Node* mProducerNode {};
277
281 std::vector<std::unique_ptr<Node>> mNodePool;
282
283 } mTimeQueue;
284
285
286 PlaybackPolicy &GetPolicy();
287 const PlaybackPolicy &GetPolicy() const;
288
289 void Init(
290 double t0, double t1,
291 const AudioIOStartStreamOptions &options,
292 const RecordingSchedule *pRecordingSchedule );
293
303 double ComputeWarpedLength(double t0, double t1) const;
304
312 double SolveWarpedLength(double t0, double length) const;
313
315 bool ReversedTime() const
316 {
317 return mT1 < mT0;
318 }
319
324 double GetSequenceTime() const
325 { return mTime.load(std::memory_order_relaxed); }
326
329 void SetSequenceTime( double time )
330 { mTime.store(time, std::memory_order_relaxed); }
331
332 void ResetMode() {
333 mPolicyValid.store(false, std::memory_order_release);
334 }
335
336 // Convert time between mT0 and argument to real duration, according to
337 // time track if one is given; result is always nonnegative
338 double RealDuration(double trackTime1) const;
339
340 // Convert time between mT0 and argument to real duration, according to
341 // time track if one is given; may be negative
342 double RealDurationSigned(double trackTime1) const;
343
344 // How much real time left?
345 double RealTimeRemaining() const;
346
347 // Advance the real time position
348 void RealTimeAdvance( double increment );
349
350 // Determine starting duration within the first pass -- sometimes not
351 // zero
352 void RealTimeInit( double trackTime );
353
354 void RealTimeRestart();
355
356private:
357 std::unique_ptr<PlaybackPolicy> mpPlaybackPolicy;
358 std::atomic<bool> mPolicyValid{ false };
359};
360#endif
std::vector< std::vector< float > > PRCrossfadeData
Definition: AudioIOBase.h:38
int min(int a, int b)
constexpr size_t TimeQueueGrainSize
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
Functions for doing the mixdown of the tracks.
Definition: Mix.h:31
Directs which parts of tracks to fetch for playback.
std::vector< std::unique_ptr< Mixer > > Mixers
virtual ~PlaybackPolicy()=0
std::chrono::duration< double > Duration
std::vector< std::unique_ptr< Node > > mNodePool
TimeQueue & operator=(const TimeQueue &)=delete
TimeQueue(const TimeQueue &)=delete
STL namespace.
struct holding stream options, including a pointer to the time warp info and AudioIOListener and whet...
Definition: AudioIOBase.h:46
Immutable structure is an argument to Mixer's constructor.
Definition: MixerOptions.h:56
Times are in seconds.
Duration latency
Try not to let ring buffer contents fall below this.
Duration ringBufferDelay
Length of ring buffer.
Duration batchSize
Try to put at least this much into the ring buffer in each pass.
std::unique_ptr< PlaybackPolicy > mpPlaybackPolicy
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...
bool ReversedTime() const
True if the end time is before the start time.
const BoundedEnvelope * mEnvelope
void SetSequenceTime(double time)
Set current track time value, unadjusted.
double GetSequenceTime() const
Get current track time value, unadjusted.
std::atomic< double > mTime
Describes an amount of contiguous (but maybe time-warped) data to be extracted from tracks to play.
const size_t toProduce
Not more than frames; the difference will be trailing silence.
PlaybackSlice(size_t available, size_t frames_, size_t toProduce_)
Constructor enforces some invariants.
const size_t frames
Total number of frames to be buffered.
double TotalCorrection() const
double ToDiscard() const
double ToConsume() const
double Consumed() const
PRCrossfadeData mCrossfadeData