00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "JackFrameTimer.h"
00022 #include "JackError.h"
00023 #include <math.h>
00024
00025 namespace Jack
00026 {
00027
00028 JackTimer::JackTimer()
00029 {
00030 fInitialized = false;
00031 fFrames = 0;
00032 fCurrentWakeup = 0;
00033 fCurrentCallback = 0;
00034 fNextWakeUp = 0;
00035 fFilterCoefficient = 0.01f;
00036 fSecondOrderIntegrator = 0.0f;
00037 }
00038
00039 void JackFrameTimer::InitFrameTime()
00040 {
00041 fFirstWakeUp = true;
00042 }
00043
00044 void JackFrameTimer::IncFrameTime(jack_nframes_t nframes, jack_time_t callback_usecs, jack_time_t period_usecs)
00045 {
00046 if (fFirstWakeUp) {
00047 InitFrameTimeAux(callback_usecs, period_usecs);
00048 fFirstWakeUp = false;
00049 } else {
00050 IncFrameTimeAux(nframes, callback_usecs, period_usecs);
00051 }
00052 }
00053
00054 void JackFrameTimer::ResetFrameTime(jack_nframes_t frames_rate, jack_time_t callback_usecs, jack_time_t period_usecs)
00055 {
00056 if (!fFirstWakeUp) {
00057 JackTimer* timer = WriteNextStateStart();
00058 jack_nframes_t period_size_guess = (jack_nframes_t)(frames_rate * ((timer->fNextWakeUp - timer->fCurrentWakeup) / 1000000.0));
00059 timer->fFrames += ((callback_usecs - timer->fNextWakeUp) / period_size_guess) * period_size_guess;
00060 timer->fCurrentWakeup = callback_usecs;
00061 timer->fCurrentCallback = callback_usecs;
00062 timer->fNextWakeUp = callback_usecs + period_usecs;
00063 WriteNextStateStop();
00064 TrySwitchState();
00065 }
00066 }
00067
00068
00069
00070
00071
00072
00073 void JackFrameTimer::ReadFrameTime(JackTimer* timer)
00074 {
00075 UInt16 next_index = GetCurrentIndex();
00076 UInt16 cur_index;
00077 do {
00078 cur_index = next_index;
00079 memcpy(timer, ReadCurrentState(), sizeof(JackTimer));
00080 next_index = GetCurrentIndex();
00081 } while (cur_index != next_index);
00082 }
00083
00084
00085
00086 void JackFrameTimer::InitFrameTimeAux(jack_time_t callback_usecs, jack_time_t period_usecs)
00087 {
00088 JackTimer* timer = WriteNextStateStart();
00089 timer->fSecondOrderIntegrator = 0.0f;
00090 timer->fCurrentCallback = callback_usecs;
00091 timer->fNextWakeUp = callback_usecs + period_usecs;
00092 WriteNextStateStop();
00093 TrySwitchState();
00094 }
00095
00096 void JackFrameTimer::IncFrameTimeAux(jack_nframes_t nframes, jack_time_t callback_usecs, jack_time_t period_usecs)
00097 {
00098 JackTimer* timer = WriteNextStateStart();
00099 float delta = (int64_t)callback_usecs - (int64_t)timer->fNextWakeUp;
00100 timer->fCurrentWakeup = timer->fNextWakeUp;
00101 timer->fCurrentCallback = callback_usecs;
00102 timer->fFrames += nframes;
00103 timer->fSecondOrderIntegrator += 0.5f * timer->fFilterCoefficient * delta;
00104 timer->fNextWakeUp = timer->fCurrentWakeup + period_usecs + (int64_t) floorf((timer->fFilterCoefficient * (delta + timer->fSecondOrderIntegrator)));
00105 timer->fInitialized = true;
00106 WriteNextStateStop();
00107 TrySwitchState();
00108 }
00109
00110 }
00111