xref: /haiku/src/add-ons/media/media-add-ons/multi_audio/TimeComputer.cpp (revision 220d04022750f40f8bac8f01fa551211e28d04f2)
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 
10 TimeComputer::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 
26 void
27 TimeComputer::Init(float frameRate, bigtime_t realBaseTime)
28 {
29 	fRealTime = realBaseTime;
30 	fPerformanceTime = 0;
31 	fDrift = 1;
32 	SetFrameRate(frameRate);
33 }
34 
35 
36 void
37 TimeComputer::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 
50 void
51 TimeComputer::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 
84 void
85 TimeComputer::_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