diff --git a/common/JackAudioDriver.cpp b/common/JackAudioDriver.cpp index ee4af8d2..47b4902d 100644 --- a/common/JackAudioDriver.cpp +++ b/common/JackAudioDriver.cpp @@ -185,12 +185,12 @@ int JackAudioDriver::Process() int JackAudioDriver::ProcessNull() { - JackDriver::CycleTakeTime(); + JackDriver::CycleTakeBeginTime(); int wait_time_usec = (int((float(fEngineControl->fBufferSize) / (float(fEngineControl->fSampleRate))) * 1000000.0f)); JackSleep(wait_time_usec); - if (!fEngine->Process(fLastWaitUst)) // fLastWaitUst is set in the "low level" layer + if (!fEngine->Process(fBeginDateUst, fEndDateUst)) // fBeginDateUst is set in the "low level" layer, fEndDateUst is from previous cycle jack_error("JackAudioDriver::ProcessNull Process error"); fGraphManager->ResumeRefNum(fClientControl, fSynchroTable); if (ProcessSlaves() < 0) @@ -219,7 +219,8 @@ int JackAudioDriver::ProcessAsync() } if (fIsMaster) { - if (!fEngine->Process(fLastWaitUst)) // fLastWaitUst is set in the "low level" layer + // fBeginDateUst is set in the "low level" layer, fEndDateUst is from previous cycle + if (!fEngine->Process(fBeginDateUst, fEndDateUst)) jack_error("JackAudioDriver::ProcessAsync Process error"); fGraphManager->ResumeRefNum(fClientControl, fSynchroTable); if (ProcessSlaves() < 0) @@ -227,6 +228,9 @@ int JackAudioDriver::ProcessAsync() } else { fGraphManager->ResumeRefNum(fClientControl, fSynchroTable); } + + // Keep end cycle time + CycleTakeEndTime(); return 0; } @@ -245,7 +249,8 @@ int JackAudioDriver::ProcessSync() if (fIsMaster) { - if (fEngine->Process(fLastWaitUst)) { // fLastWaitUst is set in the "low level" layer + // fBeginDateUst is set in the "low level" layer, fEndDateUst is from previous cycle + if (fEngine->Process(fBeginDateUst, fEndDateUst)) { fGraphManager->ResumeRefNum(fClientControl, fSynchroTable); if (ProcessSlaves() < 0) jack_error("JackAudioDriver::ProcessSync ProcessSlaves error, engine may now behave abnormally!!"); @@ -264,6 +269,9 @@ int JackAudioDriver::ProcessSync() } else { fGraphManager->ResumeRefNum(fClientControl, fSynchroTable); } + + // Keep end cycle time + CycleTakeEndTime(); return 0; } diff --git a/common/JackDriver.cpp b/common/JackDriver.cpp index cf6737ed..597641d8 100644 --- a/common/JackDriver.cpp +++ b/common/JackDriver.cpp @@ -51,7 +51,7 @@ JackDriver::JackDriver(const char* name, const char* alias, JackLockedEngine* en strcpy(fAliasName, alias); fEngine = engine; fGraphManager = NULL; - fLastWaitUst = 0; + fBeginDateUst = 0; fDelayedUsecs = 0.f; fIsMaster = true; } @@ -62,7 +62,7 @@ JackDriver::JackDriver() fClientControl = NULL; fEngine = NULL; fGraphManager = NULL; - fLastWaitUst = 0; + fBeginDateUst = 0; fIsMaster = true; } @@ -181,12 +181,18 @@ bool JackDriver::IsRealTime() const void JackDriver::CycleIncTime() { - fEngineControl->CycleIncTime(fLastWaitUst); + fEngineControl->CycleIncTime(fBeginDateUst); } -void JackDriver::CycleTakeTime() + +void JackDriver::CycleTakeBeginTime() +{ + fBeginDateUst = GetMicroSeconds(); // Take callback date here + fEngineControl->CycleIncTime(fBeginDateUst); +} + +void JackDriver::CycleTakeEndTime() { - fLastWaitUst = GetMicroSeconds(); // Take callback date here - fEngineControl->CycleIncTime(fLastWaitUst); + fEndDateUst = GetMicroSeconds(); // Take end date here } JackClientControl* JackDriver::GetClientControl() const @@ -194,9 +200,9 @@ JackClientControl* JackDriver::GetClientControl() const return fClientControl; } -void JackDriver::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs) +void JackDriver::NotifyXRun(jack_time_t cur_cycle_begin, float delayed_usecs) { - fEngine->NotifyXRun(callback_usecs, delayed_usecs); + fEngine->NotifyXRun(cur_cycle_begin, delayed_usecs); } void JackDriverClient::SetMaster(bool onoff) diff --git a/common/JackDriver.h b/common/JackDriver.h index 859806c0..367530dc 100644 --- a/common/JackDriver.h +++ b/common/JackDriver.h @@ -130,7 +130,8 @@ class EXPORT JackDriver : public JackDriverClient char fAliasName[JACK_CLIENT_NAME_SIZE + 1]; jack_nframes_t fCaptureLatency; jack_nframes_t fPlaybackLatency; - jack_time_t fLastWaitUst; + jack_time_t fBeginDateUst; + jack_time_t fEndDateUst; float fDelayedUsecs; JackLockedEngine* fEngine; JackGraphManager* fGraphManager; @@ -141,7 +142,8 @@ class EXPORT JackDriver : public JackDriverClient JackClientControl* GetClientControl() const; void CycleIncTime(); - void CycleTakeTime(); + void CycleTakeBeginTime(); + void CycleTakeEndTime(); public: diff --git a/common/JackDummyDriver.cpp b/common/JackDummyDriver.cpp index 4bab1da7..9e6f517f 100644 --- a/common/JackDummyDriver.cpp +++ b/common/JackDummyDriver.cpp @@ -65,9 +65,9 @@ int JackDummyDriver::Open(jack_nframes_t nframes, int JackDummyDriver::Process() { - JackDriver::CycleTakeTime(); + JackDriver::CycleTakeBeginTime(); JackAudioDriver::Process(); - JackSleep(std::max(0L, long(fWaitTime - (GetMicroSeconds() - fLastWaitUst)))); + JackSleep(std::max(0L, long(fWaitTime - (GetMicroSeconds() - fBeginDateUst)))); return 0; } diff --git a/common/JackEngine.cpp b/common/JackEngine.cpp index c19b2081..ac4a625c 100644 --- a/common/JackEngine.cpp +++ b/common/JackEngine.cpp @@ -133,41 +133,41 @@ void JackEngine::ReleaseRefnum(int ref) // Graph management //------------------ -void JackEngine::ProcessNext(jack_time_t callback_usecs) +void JackEngine::ProcessNext(jack_time_t cur_cycle_begin) { - fLastSwitchUsecs = callback_usecs; + fLastSwitchUsecs = cur_cycle_begin; if (fGraphManager->RunNextGraph()) // True if the graph actually switched to a new state fChannel.Notify(ALL_CLIENTS, kGraphOrderCallback, 0); - fSignal.SignalAll(); // Signal for threads waiting for next cycle + fSignal.SignalAll(); // Signal for threads waiting for next cycle } -void JackEngine::ProcessCurrent(jack_time_t callback_usecs) +void JackEngine::ProcessCurrent(jack_time_t cur_cycle_begin) { - if (callback_usecs < fLastSwitchUsecs + 2 * fEngineControl->fPeriodUsecs) // Signal XRun only for the first failing cycle - CheckXRun(callback_usecs); + if (cur_cycle_begin < fLastSwitchUsecs + 2 * fEngineControl->fPeriodUsecs) // Signal XRun only for the first failing cycle + CheckXRun(cur_cycle_begin); fGraphManager->RunCurrentGraph(); } -bool JackEngine::Process(jack_time_t callback_usecs) +bool JackEngine::Process(jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end) { bool res = true; // Cycle begin - fEngineControl->CycleBegin(fClientTable, fGraphManager, callback_usecs); + fEngineControl->CycleBegin(fClientTable, fGraphManager, cur_cycle_begin, prev_cycle_end); // Graph if (fGraphManager->IsFinishedGraph()) { - ProcessNext(callback_usecs); + ProcessNext(cur_cycle_begin); res = true; } else { jack_log("Process: graph not finished!"); - if (callback_usecs > fLastSwitchUsecs + fEngineControl->fTimeOutUsecs) { - jack_log("Process: switch to next state delta = %ld", long(callback_usecs - fLastSwitchUsecs)); - ProcessNext(callback_usecs); + if (cur_cycle_begin > fLastSwitchUsecs + fEngineControl->fTimeOutUsecs) { + jack_log("Process: switch to next state delta = %ld", long(cur_cycle_begin - fLastSwitchUsecs)); + ProcessNext(cur_cycle_begin); res = true; } else { - jack_log("Process: waiting to switch delta = %ld", long(callback_usecs - fLastSwitchUsecs)); - ProcessCurrent(callback_usecs); + jack_log("Process: waiting to switch delta = %ld", long(cur_cycle_begin - fLastSwitchUsecs)); + ProcessCurrent(cur_cycle_begin); res = false; } } diff --git a/common/JackEngine.h b/common/JackEngine.h index 36a45276..64bd54ec 100644 --- a/common/JackEngine.h +++ b/common/JackEngine.h @@ -108,7 +108,7 @@ class EXPORT JackEngine int PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst); // Graph - bool Process(jack_time_t callback_usecs); + bool Process(jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end); // Notifications void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs); diff --git a/common/JackEngineControl.cpp b/common/JackEngineControl.cpp index 85b4c32d..83472289 100644 --- a/common/JackEngineControl.cpp +++ b/common/JackEngineControl.cpp @@ -37,14 +37,17 @@ void JackEngineControl::CycleIncTime(jack_time_t callback_usecs) fFrameTimer.IncFrameTime(fBufferSize, callback_usecs, fPeriodUsecs); } -void JackEngineControl::CycleBegin(JackClientInterface** table, JackGraphManager* manager, jack_time_t callback_usecs) +void JackEngineControl::CycleBegin(JackClientInterface** table, + JackGraphManager* manager, + jack_time_t cur_cycle_begin, + jack_time_t prev_cycle_end) { // Transport - fTransport.CycleBegin(fSampleRate, callback_usecs); + fTransport.CycleBegin(fSampleRate, cur_cycle_begin); // Timing - GetTimeMeasure(table, manager, callback_usecs); - CalcCPULoad(table, manager); + //GetTimeMeasure(table, manager, callback_usecs); + CalcCPULoad(table, manager, cur_cycle_begin, prev_cycle_end); } void JackEngineControl::CycleEnd(JackClientInterface** table) @@ -57,9 +60,9 @@ void JackEngineControl::InitFrameTime() fFrameTimer.InitFrameTime(); } -void JackEngineControl::ResetFrameTime(jack_time_t callback_usecs) +void JackEngineControl::ResetFrameTime(jack_time_t cur_cycle_begin) { - fFrameTimer.ResetFrameTime(fSampleRate, callback_usecs, fPeriodUsecs); + fFrameTimer.ResetFrameTime(fSampleRate, cur_cycle_begin, fPeriodUsecs); } void JackEngineControl::ReadFrameTime(JackTimer* timer) @@ -77,38 +80,41 @@ inline jack_time_t MAX(jack_time_t a, jack_time_t b) #define MAX(a,b) std::max((a),(b)) #endif -void JackEngineControl::CalcCPULoad(JackClientInterface** table, JackGraphManager* manager) +void JackEngineControl::CalcCPULoad(JackClientInterface** table, + JackGraphManager* manager, + jack_time_t cur_cycle_begin, + jack_time_t prev_cycle_end) { - jack_time_t lastCycleEnd = fLastProcessTime; - - for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) { - JackClientInterface* client = table[i]; - JackClientTiming* timing = manager->GetClientTiming(i); - if (client && client->GetClientControl()->fActive && timing->fStatus == Finished) { - lastCycleEnd = MAX(lastCycleEnd, timing->fFinishedAt); + fPrevCycleTime = fCurCycleTime; + fCurCycleTime = cur_cycle_begin; + jack_time_t last_cycle_end = prev_cycle_end; + + // In Asynchronous mode, last cycle end is the max of client end dates + if (!fSyncMode) { + for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) { + JackClientInterface* client = table[i]; + JackClientTiming* timing = manager->GetClientTiming(i); + if (client && client->GetClientControl()->fActive && timing->fStatus == Finished) + last_cycle_end = MAX(last_cycle_end, timing->fFinishedAt); } } - /* store the execution time for later averaging */ - fRollingClientUsecs[fRollingClientUsecsIndex++] = lastCycleEnd - fLastTime; - - if (fRollingClientUsecsIndex >= JACK_ENGINE_ROLLING_COUNT) { + // Store the execution time for later averaging + fRollingClientUsecs[fRollingClientUsecsIndex++] = last_cycle_end - fPrevCycleTime; + if (fRollingClientUsecsIndex >= JACK_ENGINE_ROLLING_COUNT) fRollingClientUsecsIndex = 0; - } - - /* every so often, recompute the current maximum use over the - last JACK_ENGINE_ROLLING_COUNT client iterations. - */ - + + // Every so often, recompute the current maximum use over the + // last JACK_ENGINE_ROLLING_COUNT client iterations. + if (++fRollingClientUsecsCnt % fRollingInterval == 0) { - jack_time_t maxUsecs = 0; - for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) { - maxUsecs = MAX(fRollingClientUsecs[i], maxUsecs); - } - - fMaxUsecs = MAX(fMaxUsecs, maxUsecs); - fSpareUsecs = jack_time_t((maxUsecs < fPeriodUsecs) ? fPeriodUsecs - maxUsecs : 0); + jack_time_t max_usecs = 0; + for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) + max_usecs = MAX(fRollingClientUsecs[i], max_usecs); + + fMaxUsecs = MAX(fMaxUsecs, max_usecs); + fSpareUsecs = jack_time_t((max_usecs < fPeriodUsecs) ? fPeriodUsecs - max_usecs : 0); fCPULoad = ((1.f - (float(fSpareUsecs) / float(fPeriodUsecs))) * 50.f + (fCPULoad * 0.5f)); } } @@ -119,48 +125,7 @@ void JackEngineControl::ResetRollingUsecs() fRollingClientUsecsIndex = 0; fRollingClientUsecsCnt = 0; fSpareUsecs = 0; - fRollingInterval = (int)floor((JACK_ENGINE_ROLLING_INTERVAL * 1000.f) / fPeriodUsecs); -} - -void JackEngineControl::GetTimeMeasure(JackClientInterface** table, JackGraphManager* manager, jack_time_t callback_usecs) -{ - int pos = (++fAudioCycle) % TIME_POINTS; - - fLastTime = fCurTime; - fCurTime = callback_usecs; - - fLastProcessTime = fProcessTime; - fProcessTime = GetMicroSeconds(); - - if (fLastTime > 0) { - fMeasure[pos].fEngineTime = fLastTime; - fMeasure[pos].fAudioCycle = fAudioCycle; - - for (int i = 0; i < CLIENT_NUM; i++) { - JackClientInterface* client = table[i]; - JackClientTiming* timing = manager->GetClientTiming(i); - if (client && client->GetClientControl()->fActive) { - fMeasure[pos].fClientTable[i].fRefNum = i; - fMeasure[pos].fClientTable[i].fSignaledAt = timing->fSignaledAt; - fMeasure[pos].fClientTable[i].fAwakeAt = timing->fAwakeAt; - fMeasure[pos].fClientTable[i].fFinishedAt = timing->fFinishedAt; - fMeasure[pos].fClientTable[i].fStatus = timing->fStatus; - } - } - } -} - -void JackEngineControl::ClearTimeMeasures() -{ - for (int i = 0; i < TIME_POINTS; i++) { - for (int j = 0; j < CLIENT_NUM; j++) { - fMeasure[i].fClientTable[j].fRefNum = 0; - fMeasure[i].fClientTable[j].fSignaledAt = 0; - fMeasure[i].fClientTable[j].fAwakeAt = 0; - fMeasure[i].fClientTable[j].fFinishedAt = 0; - } - } - fLastTime = fCurTime = 0; + fRollingInterval = int(floor((JACK_ENGINE_ROLLING_INTERVAL * 1000.f) / fPeriodUsecs)); } void JackEngineControl::NotifyXRun(float delayed_usecs) diff --git a/common/JackEngineControl.h b/common/JackEngineControl.h index f67b5408..7f469d4a 100644 --- a/common/JackEngineControl.h +++ b/common/JackEngineControl.h @@ -33,34 +33,9 @@ namespace Jack class JackClientInterface; class JackGraphManager; -#define TIME_POINTS 1000 #define JACK_ENGINE_ROLLING_COUNT 32 #define JACK_ENGINE_ROLLING_INTERVAL 1024 -/*! -\brief Timing stucture for a client. -*/ - -struct JackTimingMeasureClient -{ - int fRefNum; - jack_time_t fSignaledAt; - jack_time_t fAwakeAt; - jack_time_t fFinishedAt; - jack_client_state_t fStatus; -}; - -/*! -\brief Timing stucture for a table of clients. -*/ - -struct JackTimingMeasure -{ - unsigned int fAudioCycle; - jack_time_t fEngineTime; - JackTimingMeasureClient fClientTable[CLIENT_NUM]; -}; - /*! \brief Engine control in shared memory. */ @@ -83,15 +58,11 @@ struct EXPORT JackEngineControl : public JackShmMem JackTransportEngine fTransport; bool fVerbose; - // Timing - JackTimingMeasure fMeasure[TIME_POINTS]; - jack_time_t fLastTime; - jack_time_t fCurTime; - jack_time_t fProcessTime; - jack_time_t fLastProcessTime; + // CPU Load + jack_time_t fPrevCycleTime; + jack_time_t fCurCycleTime; jack_time_t fSpareUsecs; jack_time_t fMaxUsecs; - unsigned int fAudioCycle; jack_time_t fRollingClientUsecs[JACK_ENGINE_ROLLING_COUNT]; int fRollingClientUsecsCnt; int fRollingClientUsecsIndex; @@ -118,14 +89,10 @@ struct EXPORT JackEngineControl : public JackShmMem fRealTime = rt; fPriority = priority; fVerbose = verbose; - fLastTime = 0; - fCurTime = 0; - fProcessTime = 0; - fLastProcessTime = 0; + fPrevCycleTime = 0; + fCurCycleTime = 0; fSpareUsecs = 0; fMaxUsecs = 0; - fAudioCycle = 0; - ClearTimeMeasures(); ResetRollingUsecs(); snprintf(fServerName, sizeof(fServerName), server_name); fPeriod = 0; @@ -139,7 +106,7 @@ struct EXPORT JackEngineControl : public JackShmMem // Cycle void CycleIncTime(jack_time_t callback_usecs); - void CycleBegin(JackClientInterface** table, JackGraphManager* manager, jack_time_t callback_usecs); + void CycleBegin(JackClientInterface** table, JackGraphManager* manager, jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end); void CycleEnd(JackClientInterface** table); // Timer @@ -152,9 +119,7 @@ struct EXPORT JackEngineControl : public JackShmMem void ResetXRun(); // Private - void CalcCPULoad(JackClientInterface** table, JackGraphManager* manager); - void GetTimeMeasure(JackClientInterface** table, JackGraphManager* manager, jack_time_t callback_usecs); - void ClearTimeMeasures(); + void CalcCPULoad(JackClientInterface** table, JackGraphManager* manager, jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end); void ResetRollingUsecs(); }; diff --git a/common/JackEngineTiming.cpp b/common/JackEngineTiming.cpp new file mode 100644 index 00000000..5663ec82 --- /dev/null +++ b/common/JackEngineTiming.cpp @@ -0,0 +1,75 @@ +/* +Copyright (C) 2003 Paul Davis +Copyright (C) 2004-2008 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#include "JackEngineTiming.h" +#include "JackGraphManager.h" +#include "JackClientControl.h" +#include "JackClientInterface.h" +#include "JackTime.h" + +namespace Jack +{ + +void JackEngineTiming::GetTimeMeasure(JackClientInterface** table, + JackGraphManager* manager, + jack_time_t cur_cycle_begin, + jack_time_t prev_cycle_end) +{ + int pos = (++fAudioCycle) % TIME_POINTS; + + fPrevCycleTime = fCurCycleTime; + fCurCycleTime = cur_cycle_begin; + + if (fPrevCycleTime > 0) { + fMeasure[pos].fEngineTime = fPrevCycleTime; + fMeasure[pos].fAudioCycle = fAudioCycle; + + for (int i = 0; i < CLIENT_NUM; i++) { + JackClientInterface* client = table[i]; + JackClientTiming* timing = manager->GetClientTiming(i); + if (client && client->GetClientControl()->fActive) { + fMeasure[pos].fClientTable[i].fRefNum = i; + fMeasure[pos].fClientTable[i].fSignaledAt = timing->fSignaledAt; + fMeasure[pos].fClientTable[i].fAwakeAt = timing->fAwakeAt; + fMeasure[pos].fClientTable[i].fFinishedAt = timing->fFinishedAt; + fMeasure[pos].fClientTable[i].fStatus = timing->fStatus; + } + } + } +} + +void JackEngineTiming::ClearTimeMeasures() +{ + for (int i = 0; i < TIME_POINTS; i++) { + for (int j = 0; j < CLIENT_NUM; j++) { + fMeasure[i].fClientTable[j].fRefNum = 0; + fMeasure[i].fClientTable[j].fSignaledAt = 0; + fMeasure[i].fClientTable[j].fAwakeAt = 0; + fMeasure[i].fClientTable[j].fFinishedAt = 0; + } + } + fPrevCycleTime = fCurCycleTime = 0; +} + +} // end of namespace diff --git a/common/JackEngineTiming.h b/common/JackEngineTiming.h new file mode 100644 index 00000000..5c0a9b18 --- /dev/null +++ b/common/JackEngineTiming.h @@ -0,0 +1,87 @@ +/* +Copyright (C) 2003 Paul Davis +Copyright (C) 2004-2008 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __JackEngineTiming__ +#define __JackEngineTiming__ + +#include "types.h" +#include "JackTypes.h" +#include "JackConstants.h" + +namespace Jack +{ + +#define TIME_POINTS 1000 + +/*! +\brief Timing stucture for a client. +*/ + +struct JackTimingMeasureClient +{ + int fRefNum; + jack_time_t fSignaledAt; + jack_time_t fAwakeAt; + jack_time_t fFinishedAt; + jack_client_state_t fStatus; +}; + +/*! +\brief Timing stucture for a table of clients. +*/ + +struct JackTimingMeasure +{ + unsigned int fAudioCycle; + jack_time_t fEngineTime; + JackTimingMeasureClient fClientTable[CLIENT_NUM]; +}; + +/*! +\brief Client timing. +*/ + +class JackClientInterface; +class JackGraphManager; + +class JackEngineTiming +{ + + private: + + JackTimingMeasure fMeasure[TIME_POINTS]; + unsigned int fAudioCycle; + jack_time_t fPrevCycleTime; + jack_time_t fCurCycleTime; + + public: + + JackEngineTiming():fAudioCycle(0),fPrevCycleTime(0),fCurCycleTime(0) + {} + ~JackEngineTiming() + {} + + void GetTimeMeasure(JackClientInterface** table, JackGraphManager* manager, jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end); + void ClearTimeMeasures(); +}; + +} // end of namespace + +#endif diff --git a/common/JackFreewheelDriver.cpp b/common/JackFreewheelDriver.cpp index 2e4eec77..68c9165a 100644 --- a/common/JackFreewheelDriver.cpp +++ b/common/JackFreewheelDriver.cpp @@ -37,8 +37,8 @@ int JackFreewheelDriver::Process() { if (fIsMaster) { jack_log("JackFreewheelDriver::Process master %lld", fEngineControl->fTimeOutUsecs); - JackDriver::CycleTakeTime(); - fEngine->Process(fLastWaitUst); + JackDriver::CycleTakeBeginTime(); + fEngine->Process(fBeginDateUst, fEndDateUst); fGraphManager->ResumeRefNum(fClientControl, fSynchroTable); // Signal all clients if (fGraphManager->SuspendRefNum(fClientControl, fSynchroTable, FREEWHEEL_DRIVER_TIMEOUT * 1000000) < 0) { // Wait for all clients to finish for 10 sec jack_error("JackFreewheelDriver::ProcessSync SuspendRefNum error"); diff --git a/common/JackLockedEngine.h b/common/JackLockedEngine.h index 52395e36..12f62170 100644 --- a/common/JackLockedEngine.h +++ b/common/JackLockedEngine.h @@ -146,17 +146,17 @@ class EXPORT JackLockedEngine : public JackLockAble } // Graph - bool Process(jack_time_t callback_usecs) + bool Process(jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end) { // RT : no lock - return fEngine.Process(callback_usecs); + return fEngine.Process(cur_cycle_begin, prev_cycle_end); } // Notifications - void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs) + void NotifyXRun(jack_time_t cur_cycle_begin, float delayed_usecs) { // RT : no lock - fEngine.NotifyXRun(callback_usecs, delayed_usecs); + fEngine.NotifyXRun(cur_cycle_begin, delayed_usecs); } void NotifyXRun(int refnum) diff --git a/common/JackNetDriver.cpp b/common/JackNetDriver.cpp index ed4d544a..1e29eb13 100644 --- a/common/JackNetDriver.cpp +++ b/common/JackNetDriver.cpp @@ -475,7 +475,7 @@ namespace Jack } while ( !rx_bytes && ( rx_head->fDataType != 's' ) ); - JackDriver::CycleTakeTime(); + JackDriver::CycleTakeBeginTime(); //audio, midi or sync if driver is late if ( fParams.fSendMidiChannels || fParams.fSendAudioChannels ) diff --git a/linux/alsa/JackAlsaDriver.cpp b/linux/alsa/JackAlsaDriver.cpp index 371b1098..e6d04b34 100644 --- a/linux/alsa/JackAlsaDriver.cpp +++ b/linux/alsa/JackAlsaDriver.cpp @@ -1343,7 +1343,7 @@ JackAlsaDriver::alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *stat poll_ret = jack_get_microseconds (); // steph - fLastWaitUst = poll_ret; + fBeginDateUst = poll_ret; if (extra_fd < 0) { if (driver->poll_next && poll_ret > driver->poll_next) { @@ -2291,7 +2291,7 @@ int JackAlsaDriver::Read() * clients about the delay. */ jack_log("ALSA XRun"); - NotifyXRun(fLastWaitUst, fDelayedUsecs); + NotifyXRun(fBeginDateUst, fDelayedUsecs); return -1; } diff --git a/linux/firewire/JackFFADODriver.cpp b/linux/firewire/JackFFADODriver.cpp index 569a924b..95b26a00 100644 --- a/linux/firewire/JackFFADODriver.cpp +++ b/linux/firewire/JackFFADODriver.cpp @@ -301,7 +301,7 @@ JackFFADODriver::ffado_driver_wait (ffado_driver_t *driver, int extra_fd, int *s return 0; } - fLastWaitUst = wait_ret; + fBeginDateUst = wait_ret; printExit(); return driver->period_size; @@ -398,7 +398,7 @@ JackFFADODriver::ffado_driver_new (const char *name, /* prepare all parameters */ driver->sample_rate = params->sample_rate; driver->period_size = params->period_size; - fLastWaitUst = 0; + fBeginDateUst = 0; driver->period_usecs = (jack_time_t) floor ((((float) driver->period_size) * 1000000.0f) / driver->sample_rate); @@ -743,7 +743,7 @@ int JackFFADODriver::Read() * clients about the delay. */ jack_log("FFADO XRun"); - NotifyXRun(fLastWaitUst, fDelayedUsecs); + NotifyXRun(fBeginDateUst, fDelayedUsecs); return -1; } diff --git a/linux/freebob/JackFreebobDriver.cpp b/linux/freebob/JackFreebobDriver.cpp index af153bd2..9f8fecbe 100644 --- a/linux/freebob/JackFreebobDriver.cpp +++ b/linux/freebob/JackFreebobDriver.cpp @@ -195,7 +195,7 @@ JackFreebobDriver::freebob_driver_wait (freebob_driver_t *driver, int extra_fd, } *status = 0; - fLastWaitUst = wait_ret; + fBeginDateUst = wait_ret; // FIXME: this should do something more usefull *delayed_usecs = 0; @@ -316,7 +316,7 @@ JackFreebobDriver::freebob_driver_new (char *name, /* prepare all parameters */ driver->sample_rate = params->sample_rate; driver->period_size = params->period_size; - fLastWaitUst = 0; + fBeginDateUst = 0; driver->period_usecs = (jack_time_t) floor ((((float) driver->period_size) * 1000000.0f) / driver->sample_rate); @@ -875,7 +875,7 @@ int JackFreebobDriver::Read() * clients about the delay. */ jack_log("FreeBoB XRun"); - NotifyXRun(fLastWaitUst, fDelayedUsecs); + NotifyXRun(fBeginDateUst, fDelayedUsecs); return -1; } diff --git a/macosx/JackCoreAudioDriver.cpp b/macosx/JackCoreAudioDriver.cpp index 1d8fa0e3..9ab5441e 100644 --- a/macosx/JackCoreAudioDriver.cpp +++ b/macosx/JackCoreAudioDriver.cpp @@ -177,7 +177,7 @@ OSStatus JackCoreAudioDriver::Render(void *inRefCon, driver->fActionFags = ioActionFlags; driver->fCurrentTime = (AudioTimeStamp *)inTimeStamp; driver->fDriverOutputData = ioData; - driver->CycleTakeTime(); + driver->CycleTakeBeginTime(); return driver->Process(); } @@ -258,7 +258,7 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, case kAudioDeviceProcessorOverload: jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload"); jack_time_t cur_time = GetMicroSeconds(); - driver->NotifyXRun(cur_time, float(cur_time - driver->fLastWaitUst)); // Better this value than nothing... + driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst)); // Better this value than nothing... break; case kAudioDevicePropertyStreamConfiguration: diff --git a/macosx/Jackdmp.xcodeproj/project.pbxproj b/macosx/Jackdmp.xcodeproj/project.pbxproj index 7df9abce..a40f3cb6 100644 --- a/macosx/Jackdmp.xcodeproj/project.pbxproj +++ b/macosx/Jackdmp.xcodeproj/project.pbxproj @@ -482,6 +482,8 @@ 4B80D7EB0BA0D17400F035BB /* JackMidiPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B80D7E50BA0D17400F035BB /* JackMidiPort.h */; }; 4B80D7EC0BA0D17400F035BB /* JackMidiPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80D7E60BA0D17400F035BB /* JackMidiPort.cpp */; }; 4B80D7ED0BA0D17400F035BB /* JackMidiAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80D7E70BA0D17400F035BB /* JackMidiAPI.cpp */; }; + 4B8F3D4B0E06C4A10096D19C /* JackEngineTiming.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8F3D490E06C4A10096D19C /* JackEngineTiming.cpp */; }; + 4B8F3D4C0E06C4A10096D19C /* JackEngineTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B8F3D4A0E06C4A10096D19C /* JackEngineTiming.h */; }; 4B95BCAC0D913064000F7695 /* JackControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B95BCAB0D913064000F7695 /* JackControl.cpp */; }; 4B95BCAE0D913073000F7695 /* control.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B95BCAD0D913073000F7695 /* control.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B978DED0A31D099009E2DD1 /* JackPortAudioDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B978DEB0A31D099009E2DD1 /* JackPortAudioDriver.h */; }; @@ -1241,6 +1243,8 @@ 4B869D7F08C9CB00001CF041 /* JackDriverLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackDriverLoader.cpp; path = ../common/JackDriverLoader.cpp; sourceTree = SOURCE_ROOT; }; 4B89B759076B731100D170DE /* JackRPCClientUser.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = JackRPCClientUser.c; path = RPC/JackRPCClientUser.c; sourceTree = SOURCE_ROOT; }; 4B89B769076B74D200D170DE /* JackRPCEngineUser.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = JackRPCEngineUser.c; path = RPC/JackRPCEngineUser.c; sourceTree = SOURCE_ROOT; }; + 4B8F3D490E06C4A10096D19C /* JackEngineTiming.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackEngineTiming.cpp; path = ../common/JackEngineTiming.cpp; sourceTree = SOURCE_ROOT; }; + 4B8F3D4A0E06C4A10096D19C /* JackEngineTiming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackEngineTiming.h; path = ../common/JackEngineTiming.h; sourceTree = SOURCE_ROOT; }; 4B940B9B06DDDE5B00D77F60 /* AudioHardware.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AudioHardware.h; path = /System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/AudioHardware.h; sourceTree = ""; }; 4B95BCAB0D913064000F7695 /* JackControl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackControl.cpp; path = ../common/JackControl.cpp; sourceTree = SOURCE_ROOT; }; 4B95BCAD0D913073000F7695 /* control.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = control.h; path = ../common/jack/control.h; sourceTree = SOURCE_ROOT; }; @@ -2288,6 +2292,8 @@ 4B2C28F908DAD01E00249230 /* JackGlobals.cpp */, 4BF8D2190834F03D00C94B91 /* JackEngineControl.h */, 4B6F7AEC0CD0CDBD00F48A9D /* JackEngineControl.cpp */, + 4B8F3D4A0E06C4A10096D19C /* JackEngineTiming.h */, + 4B8F3D490E06C4A10096D19C /* JackEngineTiming.cpp */, 4BD4B4D409BACD9600750C0F /* JackTransportEngine.h */, 4BD4B4D509BACD9600750C0F /* JackTransportEngine.cpp */, 4BF8D2220834F05C00C94B91 /* JackServer.h */, @@ -3034,6 +3040,7 @@ 4B5F253E0DEE9B8F0041E486 /* JackLockedEngine.h in Headers */, 4BBC93BB0DF9736C002DF220 /* JackWaitThreadedDriver.h in Headers */, 4B4CA9750E02CF9600F4BFDA /* JackRestartThreadedDriver.h in Headers */, + 4B8F3D4C0E06C4A10096D19C /* JackEngineTiming.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5631,6 +5638,7 @@ 4B4F9C8C0DC20C0400706CB0 /* JackMessageBuffer.cpp in Sources */, 4BBC93BA0DF9736C002DF220 /* JackWaitThreadedDriver.cpp in Sources */, 4B4CA9760E02CF9600F4BFDA /* JackRestartThreadedDriver.cpp in Sources */, + 4B8F3D4B0E06C4A10096D19C /* JackEngineTiming.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/windows/JackPortAudioDriver.cpp b/windows/JackPortAudioDriver.cpp index f4135f9d..372aab11 100644 --- a/windows/JackPortAudioDriver.cpp +++ b/windows/JackPortAudioDriver.cpp @@ -227,7 +227,7 @@ int JackPortAudioDriver::Render(const void* inputBuffer, void* outputBuffer, driver->fOutputBuffer = (float**)outputBuffer; // Setup threadded based log function set_threaded_log_function(); - driver->CycleTakeTime(); + driver->CycleTakeBeginTime(); return (driver->Process() == 0) ? paContinue : paAbort; }