use better high precision timer for Linux
This commit is contained in:
parent
478fd285be
commit
91548aacf6
2 changed files with 117 additions and 90 deletions
140
src/server.cpp
140
src/server.cpp
|
@ -26,67 +26,7 @@
|
|||
|
||||
|
||||
// CHighPrecisionTimer implementation ******************************************
|
||||
#if defined ( __APPLE__ ) || defined ( __MACOSX )
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_error.h>
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
CHighPrecisionTimer::CHighPrecisionTimer() :
|
||||
bRun ( false )
|
||||
{
|
||||
// calculate delay in mach absolute time
|
||||
const uint64_t iNsDelay =
|
||||
( (uint64_t) SYSTEM_FRAME_SIZE_SAMPLES * 1000000000 ) /
|
||||
(uint64_t) SYSTEM_SAMPLE_RATE_HZ; // in ns
|
||||
|
||||
struct mach_timebase_info timeBaseInfo;
|
||||
mach_timebase_info ( &timeBaseInfo );
|
||||
|
||||
iMachDelay = ( iNsDelay * (uint64_t) timeBaseInfo.denom ) /
|
||||
(uint64_t) timeBaseInfo.numer;
|
||||
}
|
||||
|
||||
void CHighPrecisionTimer::Start()
|
||||
{
|
||||
// only start if not already running
|
||||
if ( !bRun )
|
||||
{
|
||||
// set run flag
|
||||
bRun = true;
|
||||
|
||||
// set initial end time
|
||||
iNextEnd = mach_absolute_time() + iMachDelay;
|
||||
|
||||
// start thread
|
||||
QThread::start();
|
||||
}
|
||||
}
|
||||
|
||||
void CHighPrecisionTimer::Stop()
|
||||
{
|
||||
// set flag so that thread can leave the main loop
|
||||
bRun = false;
|
||||
|
||||
// give thread some time to terminate
|
||||
wait ( 5000 );
|
||||
}
|
||||
|
||||
void CHighPrecisionTimer::run()
|
||||
{
|
||||
// loop until the thread shall be terminated
|
||||
while ( bRun )
|
||||
{
|
||||
// call processing routine by fireing signal
|
||||
emit timeout();
|
||||
|
||||
// now wait until the next buffer shall be processed (we
|
||||
// use the "increment method" to make sure we do not introduce
|
||||
// a timing drift)
|
||||
mach_wait_until(iNextEnd);
|
||||
iNextEnd += iMachDelay;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
CHighPrecisionTimer::CHighPrecisionTimer()
|
||||
{
|
||||
// add some error checking, the high precision timer implementation only
|
||||
|
@ -94,7 +34,7 @@ CHighPrecisionTimer::CHighPrecisionTimer()
|
|||
#if ( SYSTEM_FRAME_SIZE_SAMPLES != 128 )
|
||||
# error "Only system frame size of 128 samples is supported by this module"
|
||||
#endif
|
||||
#if SYSTEM_SAMPLE_RATE_HZ != 48000
|
||||
#if ( SYSTEM_SAMPLE_RATE_HZ != 48000 )
|
||||
# error "Only a system sample rate of 48 kHz is supported by this module"
|
||||
#endif
|
||||
|
||||
|
@ -160,6 +100,82 @@ void CHighPrecisionTimer::OnTimer()
|
|||
iIntervalCounter++;
|
||||
}
|
||||
}
|
||||
#else // Mac and Linux
|
||||
CHighPrecisionTimer::CHighPrecisionTimer() :
|
||||
bRun ( false )
|
||||
{
|
||||
// calculate delay in ns
|
||||
const uint64_t iNsDelay =
|
||||
( (uint64_t) SYSTEM_FRAME_SIZE_SAMPLES * 1000000000 ) /
|
||||
(uint64_t) SYSTEM_SAMPLE_RATE_HZ; // in ns
|
||||
|
||||
#if defined ( __APPLE__ ) || defined ( __MACOSX )
|
||||
// calculate delay in mach absolute time
|
||||
struct mach_timebase_info timeBaseInfo;
|
||||
mach_timebase_info ( &timeBaseInfo );
|
||||
|
||||
Delay = ( iNsDelay * (uint64_t) timeBaseInfo.denom ) /
|
||||
(uint64_t) timeBaseInfo.numer;
|
||||
#else
|
||||
// set delay
|
||||
Delay.tv_sec = 0;
|
||||
Delay.tv_nsec = iNsDelay;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CHighPrecisionTimer::Start()
|
||||
{
|
||||
// only start if not already running
|
||||
if ( !bRun )
|
||||
{
|
||||
// set run flag
|
||||
bRun = true;
|
||||
|
||||
// set initial end time
|
||||
#if defined ( __APPLE__ ) || defined ( __MACOSX )
|
||||
NextEnd = mach_absolute_time();
|
||||
#else
|
||||
clock_gettime ( CLOCK_MONOTONIC, NextEnd );
|
||||
#endif
|
||||
NextEnd += Delay;
|
||||
|
||||
// start thread
|
||||
QThread::start();
|
||||
}
|
||||
}
|
||||
|
||||
void CHighPrecisionTimer::Stop()
|
||||
{
|
||||
// set flag so that thread can leave the main loop
|
||||
bRun = false;
|
||||
|
||||
// give thread some time to terminate
|
||||
wait ( 5000 );
|
||||
}
|
||||
|
||||
void CHighPrecisionTimer::run()
|
||||
{
|
||||
// loop until the thread shall be terminated
|
||||
while ( bRun )
|
||||
{
|
||||
// call processing routine by fireing signal
|
||||
emit timeout();
|
||||
|
||||
// now wait until the next buffer shall be processed (we
|
||||
// use the "increment method" to make sure we do not introduce
|
||||
// a timing drift)
|
||||
#if defined ( __APPLE__ ) || defined ( __MACOSX )
|
||||
mach_wait_until ( NextEnd );
|
||||
#else
|
||||
clock_nanosleep ( CLOCK_MONOTONIC,
|
||||
TIMER_ABSTIME,
|
||||
NextEnd,
|
||||
NULL );
|
||||
#endif
|
||||
|
||||
NextEnd += Delay;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
|
67
src/server.h
67
src/server.h
|
@ -43,36 +43,10 @@
|
|||
// no valid channel number
|
||||
#define INVALID_CHANNEL_ID ( MAX_NUM_CHANNELS + 1 )
|
||||
|
||||
// minimum timer precision
|
||||
#define MIN_TIMER_RESOLUTION_MS 1 // ms
|
||||
|
||||
|
||||
/* Classes ********************************************************************/
|
||||
#if defined ( __APPLE__ ) || defined ( __MACOSX )
|
||||
// using mach timers for Mac
|
||||
class CHighPrecisionTimer : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CHighPrecisionTimer();
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
bool isActive() { return bRun; }
|
||||
|
||||
protected:
|
||||
virtual void run();
|
||||
|
||||
bool bRun;
|
||||
uint64_t iMachDelay;
|
||||
uint64_t iNextEnd;
|
||||
|
||||
signals:
|
||||
void timeout();
|
||||
};
|
||||
#else
|
||||
// using QTimer for Windows and Linux
|
||||
#if ( defined ( WIN32 ) || defined ( _WIN32 ) )
|
||||
// using QTimer for Windows
|
||||
class CHighPrecisionTimer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -93,6 +67,43 @@ protected:
|
|||
public slots:
|
||||
void OnTimer();
|
||||
|
||||
signals:
|
||||
void timeout();
|
||||
};
|
||||
#else
|
||||
// using mach timers for Mac and nanosleep for Linux
|
||||
#if defined ( __APPLE__ ) || defined ( __MACOSX )
|
||||
# include <mach/mach.h>
|
||||
# include <mach/mach_error.h>
|
||||
# include <mach/mach_time.h>
|
||||
#else
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
class CHighPrecisionTimer : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CHighPrecisionTimer();
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
bool isActive() { return bRun; }
|
||||
|
||||
protected:
|
||||
virtual void run();
|
||||
|
||||
bool bRun;
|
||||
|
||||
#if defined ( __APPLE__ ) || defined ( __MACOSX )
|
||||
uint64_t Delay;
|
||||
uint64_t NextEnd;
|
||||
#else
|
||||
timespec Delay;
|
||||
timespec NextEnd;
|
||||
#endif
|
||||
|
||||
signals:
|
||||
void timeout();
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue