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
|
#pragma once
#include <QMutex>
#include <QTime>
#include <QMap>
#include <QAtomicPointer>
#include "util/performancetimer.h"
#include "control/controlvalue.h"
class ControlProxy;
class VSyncThread;
// 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_tempoTrackSeconds; // total track time, taking the current tempo into account
};
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 tempoTrackSeconds);
double getAtNextVSync(VSyncThread* vsyncThread);
void getPlaySlipAtNextVSync(VSyncThread* vSyncThread, 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 slots:
void slotAudioBufferSizeChanged(double sizeMs);
private:
ControlValueAtomic<VisualPlayPositionData> m_data;
ControlProxy* m_audioBufferSize;
int m_audioBufferMicros; // Audio buffer size in µs
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;
};
|