1/*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "TimeComputer.h"
8
9
10TimeComputer::TimeComputer()
11	:
12	fRealTime(0),
13	fPerformanceTime(0),
14	fDrift(1),
15	fFrameRate(1000000),
16	fUsecsPerFrame(1),
17	fPerformanceTimeBase(0),
18	fFrameBase(0),
19	fResetTimeBase(true),
20	fFirstEntry(0),
21	fLastEntry(0)
22{
23}
24
25
26void
27TimeComputer::Init(float frameRate, bigtime_t realBaseTime)
28{
29	fRealTime = realBaseTime;
30	fPerformanceTime = 0;
31	fDrift = 1;
32	SetFrameRate(frameRate);
33}
34
35
36void
37TimeComputer::SetFrameRate(float frameRate)
38{
39	if (frameRate == fFrameRate)
40		return;
41
42	fFrameRate = frameRate;
43	fUsecsPerFrame = (double)1000000 / fFrameRate;
44	fResetTimeBase = true;
45	fFirstEntry = 0;
46	fLastEntry = 0;
47}
48
49
50void
51TimeComputer::AddTimeStamp(bigtime_t realTime, uint64 frames)
52{
53	bigtime_t estimatedPerformanceTime = fPerformanceTime
54		+ bigtime_t((realTime - fRealTime) * fDrift);
55
56	fRealTime = realTime;
57
58	if (fResetTimeBase) {
59		// use the extrapolated performance time at the given real time
60		fPerformanceTime = estimatedPerformanceTime;
61		fPerformanceTimeBase = estimatedPerformanceTime;
62		fFrameBase = frames;
63		fResetTimeBase = false;
64		_AddEntry(fRealTime, fPerformanceTime);
65		return;
66	}
67
68	// add entry
69	bigtime_t performanceTime = fPerformanceTimeBase
70		+ bigtime_t((frames - fFrameBase) * fUsecsPerFrame);
71	_AddEntry(realTime, performanceTime);
72
73	// Update performance time and drift. We don't use the given
74	// performance time directly, but average it with the estimated
75	// performance time.
76	fPerformanceTime = (performanceTime + estimatedPerformanceTime) / 2;
77
78	Entry& entry = fEntries[fFirstEntry];
79	fDrift = double(fPerformanceTime - entry.performanceTime)
80		/ double(fRealTime - entry.realTime);
81}
82
83
84void
85TimeComputer::_AddEntry(bigtime_t realTime, bigtime_t performanceTime)
86{
87	fLastEntry = (fLastEntry + 1) % kEntryCount;
88	Entry& entry = fEntries[fLastEntry];
89	entry.realTime = realTime;
90	entry.performanceTime = performanceTime;
91
92	if (fLastEntry == fFirstEntry)
93		fFirstEntry = (fFirstEntry + 1) % kEntryCount;
94}
95