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