xref: /haiku/src/add-ons/media/media-add-ons/multi_audio/TimeComputer.cpp (revision 424086eeefcb2026c58138bc3818278266a2d8a6)
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 
TimeComputer()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
Init(float frameRate,bigtime_t realBaseTime)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
SetFrameRate(float frameRate)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
AddTimeStamp(bigtime_t realTime,uint64 frames)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 
56cb007542SIngo Weinhold 	fRealTime = realTime;
57cb007542SIngo Weinhold 
58cb007542SIngo Weinhold 	if (fResetTimeBase) {
59cb007542SIngo Weinhold 		// use the extrapolated performance time at the given real time
60cb007542SIngo Weinhold 		fPerformanceTime = estimatedPerformanceTime;
61cb007542SIngo Weinhold 		fPerformanceTimeBase = estimatedPerformanceTime;
62cb007542SIngo Weinhold 		fFrameBase = frames;
63cb007542SIngo Weinhold 		fResetTimeBase = false;
64cb007542SIngo Weinhold 		_AddEntry(fRealTime, fPerformanceTime);
65cf238ffcSMichael Lotz 		fFirstEntry = fLastEntry;
66cb007542SIngo Weinhold 		return;
67cb007542SIngo Weinhold 	}
68cb007542SIngo Weinhold 
69cb007542SIngo Weinhold 	// add entry
70cb007542SIngo Weinhold 	bigtime_t performanceTime = fPerformanceTimeBase
71cb007542SIngo Weinhold 		+ bigtime_t((frames - fFrameBase) * fUsecsPerFrame);
72cb007542SIngo Weinhold 	_AddEntry(realTime, performanceTime);
73cb007542SIngo Weinhold 
74cb007542SIngo Weinhold 	// Update performance time and drift. We don't use the given
75cb007542SIngo Weinhold 	// performance time directly, but average it with the estimated
76cb007542SIngo Weinhold 	// performance time.
77cb007542SIngo Weinhold 	fPerformanceTime = (performanceTime + estimatedPerformanceTime) / 2;
78cb007542SIngo Weinhold 
79cb007542SIngo Weinhold 	Entry& entry = fEntries[fFirstEntry];
80cb007542SIngo Weinhold 	fDrift = double(fPerformanceTime - entry.performanceTime)
81cb007542SIngo Weinhold 		/ double(fRealTime - entry.realTime);
82cb007542SIngo Weinhold }
83cb007542SIngo Weinhold 
84cb007542SIngo Weinhold 
85cb007542SIngo Weinhold void
_AddEntry(bigtime_t realTime,bigtime_t performanceTime)86cb007542SIngo Weinhold TimeComputer::_AddEntry(bigtime_t realTime, bigtime_t performanceTime)
87cb007542SIngo Weinhold {
88cb007542SIngo Weinhold 	fLastEntry = (fLastEntry + 1) % kEntryCount;
89cb007542SIngo Weinhold 	Entry& entry = fEntries[fLastEntry];
90cb007542SIngo Weinhold 	entry.realTime = realTime;
91cb007542SIngo Weinhold 	entry.performanceTime = performanceTime;
92cb007542SIngo Weinhold 
93cb007542SIngo Weinhold 	if (fLastEntry == fFirstEntry)
94cb007542SIngo Weinhold 		fFirstEntry = (fFirstEntry + 1) % kEntryCount;
95cb007542SIngo Weinhold }
96