git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2655 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.90
@@ -1237,10 +1237,12 @@ EXPORT jack_nframes_t jack_frames_since_cycle_start(const jack_client_t* ext_cli | |||||
#endif | #endif | ||||
JackTimer timer; | JackTimer timer; | ||||
JackEngineControl* control = GetEngineControl(); | JackEngineControl* control = GetEngineControl(); | ||||
if (!control) | |||||
if (control) { | |||||
control->ReadFrameTime(&timer); | |||||
return timer.FramesSinceCycleStart(GetMicroSeconds(), control->fSampleRate); | |||||
} else { | |||||
return 0; | return 0; | ||||
control->ReadFrameTime(&timer); | |||||
return (jack_nframes_t) floor((((float)control->fSampleRate) / 1000000.0f) * (GetMicroSeconds() - timer.fCurrentCallback)); | |||||
} | |||||
} | } | ||||
EXPORT jack_time_t jack_get_time() | EXPORT jack_time_t jack_get_time() | ||||
@@ -1260,13 +1262,9 @@ EXPORT jack_time_t jack_frames_to_time(const jack_client_t* ext_client, jack_nfr | |||||
} else { | } else { | ||||
JackTimer timer; | JackTimer timer; | ||||
JackEngineControl* control = GetEngineControl(); | JackEngineControl* control = GetEngineControl(); | ||||
if (!control) | |||||
return 0; | |||||
control->ReadFrameTime(&timer); | |||||
if (timer.fInitialized) { | |||||
return timer.fCurrentWakeup + | |||||
(long) rint(((double) ((frames - timer.fFrames)) * | |||||
((jack_time_t)(timer.fNextWakeUp - timer.fCurrentWakeup))) / control->fBufferSize); | |||||
if (control) { | |||||
control->ReadFrameTime(&timer); | |||||
return timer.Frames2Time(frames, control->fBufferSize); | |||||
} else { | } else { | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -1285,13 +1283,9 @@ EXPORT jack_nframes_t jack_time_to_frames(const jack_client_t* ext_client, jack_ | |||||
} else { | } else { | ||||
JackTimer timer; | JackTimer timer; | ||||
JackEngineControl* control = GetEngineControl(); | JackEngineControl* control = GetEngineControl(); | ||||
if (!control) | |||||
return 0; | |||||
control->ReadFrameTime(&timer); | |||||
if (timer.fInitialized) { | |||||
return timer.fFrames + | |||||
(long) rint(((double) ((time - timer.fCurrentWakeup)) / | |||||
((jack_time_t)(timer.fNextWakeUp - timer.fCurrentWakeup))) * control->fBufferSize); | |||||
if (control) { | |||||
control->ReadFrameTime(&timer); | |||||
return timer.Time2Frames(time, control->fBufferSize); | |||||
} else { | } else { | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -1312,7 +1306,7 @@ EXPORT jack_nframes_t jack_last_frame_time(const jack_client_t* ext_client) | |||||
JackEngineControl* control = GetEngineControl(); | JackEngineControl* control = GetEngineControl(); | ||||
if (control) { | if (control) { | ||||
control->ReadFrameTime(&timer); | control->ReadFrameTime(&timer); | ||||
return timer.fFrames; | |||||
return timer.CurFrame(); | |||||
} else { | } else { | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -126,16 +126,16 @@ namespace Jack | |||||
return (res < 0) ? 1 : res; | return (res < 0) ? 1 : res; | ||||
} | } | ||||
jack_time_t CurFrame2Time() | |||||
jack_nframes_t CurFrame() | |||||
{ | { | ||||
return fCurrentWakeup; | |||||
return fFrames; | |||||
} | } | ||||
jack_nframes_t CurTime2Frame() | |||||
jack_time_t CurTime() | |||||
{ | { | ||||
return fFrames; | |||||
return fCurrentWakeup; | |||||
} | } | ||||
}; | }; | ||||
class JackAtomicDelayLockedLoop : public JackAtomicState<JackDelayLockedLoop> | class JackAtomicDelayLockedLoop : public JackAtomicState<JackDelayLockedLoop> | ||||
@@ -40,18 +40,41 @@ JackTimer::JackTimer() | |||||
fSecondOrderIntegrator = 0.0f; | fSecondOrderIntegrator = 0.0f; | ||||
} | } | ||||
jack_nframes_t JackTimer::Time2Frames(jack_time_t time, jack_nframes_t buffer_size) | |||||
{ | |||||
if (fInitialized) { | |||||
return fFrames + (long)rint(((double) ((time - fCurrentWakeup)) / ((jack_time_t)(fNextWakeUp - fCurrentWakeup))) * buffer_size); | |||||
} else { | |||||
return 0; | |||||
} | |||||
} | |||||
jack_time_t JackTimer::Frames2Time(jack_nframes_t frames, jack_nframes_t buffer_size) | |||||
{ | |||||
if (fInitialized) { | |||||
return fCurrentWakeup + (long)rint(((double) ((frames - fFrames)) * ((jack_time_t)(fNextWakeUp - fCurrentWakeup))) / buffer_size); | |||||
} else { | |||||
return 0; | |||||
} | |||||
} | |||||
jack_nframes_t JackTimer::FramesSinceCycleStart(jack_time_t cur_time, jack_nframes_t frames_rate) | |||||
{ | |||||
return (jack_nframes_t) floor((((float)frames_rate) / 1000000.0f) * (cur_time - fCurrentCallback)); | |||||
} | |||||
void JackFrameTimer::InitFrameTime() | void JackFrameTimer::InitFrameTime() | ||||
{ | { | ||||
fFirstWakeUp = true; | fFirstWakeUp = true; | ||||
} | } | ||||
void JackFrameTimer::IncFrameTime(jack_nframes_t nframes, jack_time_t callback_usecs, jack_time_t period_usecs) | |||||
void JackFrameTimer::IncFrameTime(jack_nframes_t buffer_size, jack_time_t callback_usecs, jack_time_t period_usecs) | |||||
{ | { | ||||
if (fFirstWakeUp) { | if (fFirstWakeUp) { | ||||
InitFrameTimeAux(callback_usecs, period_usecs); | InitFrameTimeAux(callback_usecs, period_usecs); | ||||
fFirstWakeUp = false; | fFirstWakeUp = false; | ||||
} else { | } else { | ||||
IncFrameTimeAux(nframes, callback_usecs, period_usecs); | |||||
IncFrameTimeAux(buffer_size, callback_usecs, period_usecs); | |||||
} | } | ||||
} | } | ||||
@@ -97,13 +120,13 @@ void JackFrameTimer::InitFrameTimeAux(jack_time_t callback_usecs, jack_time_t pe | |||||
TrySwitchState(); // always succeed since there is only one writer | TrySwitchState(); // always succeed since there is only one writer | ||||
} | } | ||||
void JackFrameTimer::IncFrameTimeAux(jack_nframes_t nframes, jack_time_t callback_usecs, jack_time_t period_usecs) | |||||
void JackFrameTimer::IncFrameTimeAux(jack_nframes_t buffer_size, jack_time_t callback_usecs, jack_time_t period_usecs) | |||||
{ | { | ||||
JackTimer* timer = WriteNextStateStart(); | JackTimer* timer = WriteNextStateStart(); | ||||
float delta = (int64_t)callback_usecs - (int64_t)timer->fNextWakeUp; | float delta = (int64_t)callback_usecs - (int64_t)timer->fNextWakeUp; | ||||
timer->fCurrentWakeup = timer->fNextWakeUp; | timer->fCurrentWakeup = timer->fNextWakeUp; | ||||
timer->fCurrentCallback = callback_usecs; | timer->fCurrentCallback = callback_usecs; | ||||
timer->fFrames += nframes; | |||||
timer->fFrames += buffer_size; | |||||
timer->fSecondOrderIntegrator += 0.5f * timer->fFilterCoefficient * delta; | timer->fSecondOrderIntegrator += 0.5f * timer->fFilterCoefficient * delta; | ||||
timer->fNextWakeUp = timer->fCurrentWakeup + period_usecs + (int64_t) floorf((timer->fFilterCoefficient * (delta + timer->fSecondOrderIntegrator))); | timer->fNextWakeUp = timer->fCurrentWakeup + period_usecs + (int64_t) floorf((timer->fFilterCoefficient * (delta + timer->fSecondOrderIntegrator))); | ||||
timer->fInitialized = true; | timer->fInitialized = true; | ||||
@@ -32,22 +32,40 @@ namespace Jack | |||||
\brief A structure used for time management. | \brief A structure used for time management. | ||||
*/ | */ | ||||
struct EXPORT JackTimer | |||||
class EXPORT JackTimer | |||||
{ | { | ||||
jack_nframes_t fFrames; | |||||
jack_time_t fCurrentWakeup; | |||||
jack_time_t fCurrentCallback; | |||||
jack_time_t fNextWakeUp; | |||||
float fSecondOrderIntegrator; | |||||
bool fInitialized; | |||||
/* not accessed by clients */ | |||||
float fFilterCoefficient; /* set once, never altered */ | |||||
JackTimer(); | |||||
~JackTimer() | |||||
{} | |||||
friend class JackFrameTimer; | |||||
private: | |||||
jack_nframes_t fFrames; | |||||
jack_time_t fCurrentWakeup; | |||||
jack_time_t fCurrentCallback; | |||||
jack_time_t fNextWakeUp; | |||||
float fSecondOrderIntegrator; | |||||
bool fInitialized; | |||||
float fFilterCoefficient; /* set once, never altered */ | |||||
public: | |||||
JackTimer(); | |||||
~JackTimer() | |||||
{} | |||||
jack_nframes_t Time2Frames(jack_time_t time, jack_nframes_t buffer_size); | |||||
jack_time_t Frames2Time(jack_nframes_t frames, jack_nframes_t buffer_size); | |||||
jack_nframes_t FramesSinceCycleStart(jack_time_t cur_time, jack_nframes_t frames_rate); | |||||
jack_nframes_t CurFrame() | |||||
{ | |||||
return fFrames; | |||||
} | |||||
jack_time_t CurTime() | |||||
{ | |||||
return fCurrentWakeup; | |||||
} | |||||
}; | }; | ||||
@@ -57,10 +75,11 @@ struct EXPORT JackTimer | |||||
class JackFrameTimer : public JackAtomicState<JackTimer> | class JackFrameTimer : public JackAtomicState<JackTimer> | ||||
{ | { | ||||
private: | private: | ||||
bool fFirstWakeUp; | bool fFirstWakeUp; | ||||
void IncFrameTimeAux(jack_nframes_t nframes, jack_time_t callback_usecs, jack_time_t period_usecs); | |||||
void IncFrameTimeAux(jack_nframes_t buffer_size, jack_time_t callback_usecs, jack_time_t period_usecs); | |||||
void InitFrameTimeAux(jack_time_t callback_usecs, jack_time_t period_usecs); | void InitFrameTimeAux(jack_time_t callback_usecs, jack_time_t period_usecs); | ||||
public: | public: | ||||
@@ -72,7 +91,7 @@ class JackFrameTimer : public JackAtomicState<JackTimer> | |||||
void InitFrameTime(); | void InitFrameTime(); | ||||
void ResetFrameTime(jack_nframes_t frames_rate, jack_time_t callback_usecs, jack_time_t period_usecs); | void ResetFrameTime(jack_nframes_t frames_rate, jack_time_t callback_usecs, jack_time_t period_usecs); | ||||
void IncFrameTime(jack_nframes_t nframes, jack_time_t callback_usecs, jack_time_t period_usecs); | |||||
void IncFrameTime(jack_nframes_t buffer_size, jack_time_t callback_usecs, jack_time_t period_usecs); | |||||
void ReadFrameTime(JackTimer* timer); | void ReadFrameTime(JackTimer* timer); | ||||
}; | }; | ||||