xref: /haiku/src/add-ons/media/media-add-ons/multi_audio/TimeComputer.cpp (revision 372b901dfeada686207d00bbcce456f748bbda12)
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 		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 
85 void
86 TimeComputer::_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