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 ******************************************
|
// CHighPrecisionTimer implementation ******************************************
|
||||||
#if defined ( __APPLE__ ) || defined ( __MACOSX )
|
#ifdef _WIN32
|
||||||
#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
|
|
||||||
CHighPrecisionTimer::CHighPrecisionTimer()
|
CHighPrecisionTimer::CHighPrecisionTimer()
|
||||||
{
|
{
|
||||||
// add some error checking, the high precision timer implementation only
|
// add some error checking, the high precision timer implementation only
|
||||||
|
@ -94,7 +34,7 @@ CHighPrecisionTimer::CHighPrecisionTimer()
|
||||||
#if ( SYSTEM_FRAME_SIZE_SAMPLES != 128 )
|
#if ( SYSTEM_FRAME_SIZE_SAMPLES != 128 )
|
||||||
# error "Only system frame size of 128 samples is supported by this module"
|
# error "Only system frame size of 128 samples is supported by this module"
|
||||||
#endif
|
#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"
|
# error "Only a system sample rate of 48 kHz is supported by this module"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -160,6 +100,82 @@ void CHighPrecisionTimer::OnTimer()
|
||||||
iIntervalCounter++;
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
67
src/server.h
67
src/server.h
|
@ -43,36 +43,10 @@
|
||||||
// no valid channel number
|
// no valid channel number
|
||||||
#define INVALID_CHANNEL_ID ( MAX_NUM_CHANNELS + 1 )
|
#define INVALID_CHANNEL_ID ( MAX_NUM_CHANNELS + 1 )
|
||||||
|
|
||||||
// minimum timer precision
|
|
||||||
#define MIN_TIMER_RESOLUTION_MS 1 // ms
|
|
||||||
|
|
||||||
|
|
||||||
/* Classes ********************************************************************/
|
/* Classes ********************************************************************/
|
||||||
#if defined ( __APPLE__ ) || defined ( __MACOSX )
|
#if ( defined ( WIN32 ) || defined ( _WIN32 ) )
|
||||||
// using mach timers for Mac
|
// using QTimer for Windows
|
||||||
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
|
|
||||||
class CHighPrecisionTimer : public QObject
|
class CHighPrecisionTimer : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -93,6 +67,43 @@ protected:
|
||||||
public slots:
|
public slots:
|
||||||
void OnTimer();
|
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:
|
signals:
|
||||||
void timeout();
|
void timeout();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue