1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
#pragma once
#include <QTime>
#include <QMap>
#include <QAtomicPointer>
#include "util/performancetimer.h"
#include "control/controlvalue.h"
class ControlProxy;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
typedef void VSyncThread;
#else
class VSyncThread;
#endif
// This class is for synchronizing the sound device DAC time with the waveforms, displayed on the
// graphic device, using the CPU time
//
// DAC: ------|--------------|-------|-------------------|-----------------------|-----
// ^Audio Callback Entry | | ^Last Sample to DAC
// | ^Buffer prepared ^Waveform sample X
// | ^First sample transferred to DAC
// CPU: ------|-------------------------------------------------------------------------
// ^Start m_timeInfoTime |
// |
// GPU: ---------|----------------------------------- |--|-------------------------------
// ^Render Waveform sample X | ^VSync (New waveform is displayed
// by use usFromTimerToNextSync ^swap Buffer
class VisualPlayPositionData {
public:
PerformanceTimer m_referenceTime;
int m_callbackEntrytoDac; // Time from Audio Callback Entry to first sample of Buffer is transferred to DAC
double m_enginePlayPos; // Play position of fist Sample in Buffer
double m_rate;
double m_positionStep;
double m_slipPosition;
double m_slipRate;
double m_tempoTrackSeconds; // total track time, taking the current tempo into account
double m_audioBufferMicroS;
};
class VisualPlayPosition : public QObject {
Q_OBJECT
public:
VisualPlayPosition(const QString& m_key);
virtual ~VisualPlayPosition();
// WARNING: Not thread safe. This function must be called only from the
// engine thread.
void set(
double playPos,
double rate,
double positionStep,
double slipPosition,
double slipRate,
double tempoTrackSeconds,
double audioBufferMicroS);
double getAtNextVSync(VSyncThread* pVSyncThread);
void getPlaySlipAtNextVSync(VSyncThread* pVSyncThread,
double* playPosition,
double* slipPosition);
double getEnginePlayPos();
void getTrackTime(double* pPlayPosition, double* pTempoTrackSeconds);
// WARNING: Not thread safe. This function must only be called from the main
// thread.
static QSharedPointer<VisualPlayPosition> getVisualPlayPosition(const QString& group);
// This is called by SoundDevicePortAudio just after the callback starts.
static void setCallbackEntryToDacSecs(double secs, const PerformanceTimer& time);
void setInvalid() { m_valid = false; };
bool isValid() const {
return m_valid;
}
private:
double calcOffsetAtNextVSync(VSyncThread* pVSyncThread, const VisualPlayPositionData& data);
ControlValueAtomic<VisualPlayPositionData> m_data;
bool m_valid;
QString m_key;
static QMap<QString, QWeakPointer<VisualPlayPosition>> m_listVisualPlayPosition;
// Time info from the Sound device, updated just after audio callback is called
static double m_dCallbackEntryToDacSecs;
// Time stamp for m_timeInfo in main CPU time
static PerformanceTimer m_timeInfoTime;
};
|