Skip to content

Commit

Permalink
Move CHighPrecisionTimer to util
Browse files Browse the repository at this point in the history
  • Loading branch information
pljones committed May 22, 2022
1 parent 537c83c commit a84ab11
Show file tree
Hide file tree
Showing 16 changed files with 282 additions and 286 deletions.
186 changes: 0 additions & 186 deletions src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,192 +24,6 @@

#include "server.h"

// CHighPrecisionTimer implementation ******************************************
#ifdef _WIN32
CHighPrecisionTimer::CHighPrecisionTimer ( const bool bNewUseDoubleSystemFrameSize ) : bUseDoubleSystemFrameSize ( bNewUseDoubleSystemFrameSize )
{
// add some error checking, the high precision timer implementation only
// supports 64 and 128 samples frame size at 48 kHz sampling rate
# if ( SYSTEM_FRAME_SIZE_SAMPLES != 64 ) && ( DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES != 128 )
# error "Only system frame size of 64 and 128 samples is supported by this module"
# endif
# if ( SYSTEM_SAMPLE_RATE_HZ != 48000 )
# error "Only a system sample rate of 48 kHz is supported by this module"
# endif

// Since QT only supports a minimum timer resolution of 1 ms but for our
// server we require a timer interval of 2.333 ms for 128 samples
// frame size at 48 kHz sampling rate.
// To support this interval, we use a timer with 2 ms resolution for 128
// samples frame size and 1 ms resolution for 64 samples frame size.
// Then we fire the actual frame timer if the error to the actual
// required interval is minimum.
veciTimeOutIntervals.Init ( 3 );

// for 128 sample frame size at 48 kHz sampling rate with 2 ms timer resolution:
// actual intervals: 0.0 2.666 5.333 8.0
// quantized to 2 ms: 0 2 6 8 (0)
// for 64 sample frame size at 48 kHz sampling rate with 1 ms timer resolution:
// actual intervals: 0.0 1.333 2.666 4.0
// quantized to 2 ms: 0 1 3 4 (0)
veciTimeOutIntervals[0] = 0;
veciTimeOutIntervals[1] = 1;
veciTimeOutIntervals[2] = 0;

Timer.setTimerType ( Qt::PreciseTimer );

// connect timer timeout signal
QObject::connect ( &Timer, &QTimer::timeout, this, &CHighPrecisionTimer::OnTimer );
}

void CHighPrecisionTimer::Start()
{
// reset position pointer and counter
iCurPosInVector = 0;
iIntervalCounter = 0;

if ( bUseDoubleSystemFrameSize )
{
// start internal timer with 2 ms resolution for 128 samples frame size
Timer.start ( 2 );
}
else
{
// start internal timer with 1 ms resolution for 64 samples frame size
Timer.start ( 1 );
}
}

void CHighPrecisionTimer::Stop()
{
// stop timer
Timer.stop();
}

void CHighPrecisionTimer::OnTimer()
{
// check if maximum number of high precision timer intervals are
// finished
if ( veciTimeOutIntervals[iCurPosInVector] == iIntervalCounter )
{
// reset interval counter
iIntervalCounter = 0;

// go to next position in vector, take care of wrap around
iCurPosInVector++;
if ( iCurPosInVector == veciTimeOutIntervals.Size() )
{
iCurPosInVector = 0;
}

// minimum time error to actual required timer interval is reached,
// emit signal for server
emit timeout();
}
else
{
// next high precision timer interval
iIntervalCounter++;
}
}
#else // Mac and Linux
CHighPrecisionTimer::CHighPrecisionTimer ( const bool bUseDoubleSystemFrameSize ) : bRun ( false )
{
// calculate delay in ns
uint64_t iNsDelay;

if ( bUseDoubleSystemFrameSize )
{
iNsDelay = ( (uint64_t) DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES * 1000000000 ) / (uint64_t) SYSTEM_SAMPLE_RATE_HZ; // in ns
}
else
{
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 = 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() + Delay;
# else
clock_gettime ( CLOCK_MONOTONIC, &NextEnd );

NextEnd.tv_nsec += Delay;
if ( NextEnd.tv_nsec >= 1000000000L )
{
NextEnd.tv_sec++;
NextEnd.tv_nsec -= 1000000000L;
}
# endif

// start thread
QThread::start ( QThread::TimeCriticalPriority );
}
}

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

//### TODO: BEGIN ###//
// by emit a signal we leave the high priority thread -> maybe use some
// other connection type to have something like a true callback, e.g.
// "Qt::DirectConnection" -> Can this work?
emit timeout();
//### TODO: END ###//

// 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 );

NextEnd += Delay;
# else
clock_nanosleep ( CLOCK_MONOTONIC, TIMER_ABSTIME, &NextEnd, NULL );

NextEnd.tv_nsec += Delay;
if ( NextEnd.tv_nsec >= 1000000000L )
{
NextEnd.tv_sec++;
NextEnd.tv_nsec -= 1000000000L;
}
# endif
}
}
#endif

// CServer implementation ******************************************************
CServer::CServer ( const int iNewMaxNumChan,
const QString& strLoggingFileName,
Expand Down
66 changes: 0 additions & 66 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#pragma once

#include <QObject>
#include <QTimer>
#include <QDateTime>
#include <QHostAddress>
#include <QFileInfo>
Expand All @@ -52,71 +51,6 @@
#define INVALID_CHANNEL_ID ( MAX_NUM_CHANNELS + 1 )

/* Classes ********************************************************************/
#if ( defined( WIN32 ) || defined( _WIN32 ) )
// using QTimer for Windows
class CHighPrecisionTimer : public QObject
{
Q_OBJECT

public:
CHighPrecisionTimer ( const bool bNewUseDoubleSystemFrameSize );

void Start();
void Stop();
bool isActive() const { return Timer.isActive(); }

protected:
QTimer Timer;
CVector<int> veciTimeOutIntervals;
int iCurPosInVector;
int iIntervalCounter;
bool bUseDoubleSystemFrameSize;

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 ( const bool bUseDoubleSystemFrameSize );

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
long Delay;
timespec NextEnd;
# endif

signals:
void timeout();
};
#endif

template<unsigned int slotId>
class CServerSlots : public CServerSlots<slotId - 1>
{
Expand Down
9 changes: 4 additions & 5 deletions src/sound/jack/sound.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@
#include <stdio.h>
#include <QThread>
#include <string.h>
#include "../../util.h"
#include "../soundbase.h"
#include "../../global.h"

#if WITH_JACK
# include <jack/jack.h>
# include <jack/midiport.h>
#endif

#include "../../global.h"
#include "../../util.h"
#include "../soundbase.h"

/* Definitions ****************************************************************/
#define NUM_IN_OUT_CHANNELS 2 // always stereo

Expand Down Expand Up @@ -116,7 +116,6 @@ class CSound : public CSoundBase
};
#else
// no sound -> dummy class definition
# include "server.h"
class CSound : public CSoundBase
{
Q_OBJECT
Expand Down
Binary file modified src/translation/translation_de_DE.qm
Binary file not shown.
Binary file modified src/translation/translation_es_ES.qm
Binary file not shown.
Binary file modified src/translation/translation_fr_FR.qm
Binary file not shown.
Binary file modified src/translation/translation_it_IT.qm
Binary file not shown.
Binary file modified src/translation/translation_nl_NL.qm
Binary file not shown.
Binary file modified src/translation/translation_pl_PL.qm
Binary file not shown.
Binary file modified src/translation/translation_pt_BR.qm
Binary file not shown.
Binary file modified src/translation/translation_pt_PT.qm
Binary file not shown.
Binary file modified src/translation/translation_sk_SK.qm
Binary file not shown.
Binary file modified src/translation/translation_sv_SE.qm
Binary file not shown.
Binary file modified src/translation/translation_zh_CN.qm
Binary file not shown.
Loading

0 comments on commit a84ab11

Please sign in to comment.