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		fFirstEntry = fLastEntry;
66		return;
67	}
68
69	// add entry
70	bigtime_t performanceTime = fPerformanceTimeBase
71		+ bigtime_t((frames - fFrameBase) * fUsecsPerFrame);
72	_AddEntry(realTime, performanceTime);
73
74	// Update performance time and drift. We don't use the given
75	// performance time directly, but average it with the estimated
76	// performance time.
77	fPerformanceTime = (performanceTime + estimatedPerformanceTime) / 2;
78
79	Entry& entry = fEntries[fFirstEntry];
80	fDrift = double(fPerformanceTime - entry.performanceTime)
81		/ double(fRealTime - entry.realTime);
82}
83
84
85void
86TimeComputer::_AddEntry(bigtime_t realTime, bigtime_t performanceTime)
87{
88	fLastEntry = (fLastEntry + 1) % kEntryCount;
89	Entry& entry = fEntries[fLastEntry];
90	entry.realTime = realTime;
91	entry.performanceTime = performanceTime;
92
93	if (fLastEntry == fFirstEntry)
94		fFirstEntry = (fFirstEntry + 1) % kEntryCount;
95}
96