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