Mercurial > hg > svcore
comparison base/RealTime.cpp @ 0:da6937383da8
initial import
author | Chris Cannam |
---|---|
date | Tue, 10 Jan 2006 16:33:16 +0000 |
parents | |
children | d86891498eef |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:da6937383da8 |
---|---|
1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 A waveform viewer and audio annotation editor. | |
5 Chris Cannam, Queen Mary University of London, 2005 | |
6 | |
7 This is experimental software. Not for distribution. | |
8 */ | |
9 | |
10 /* | |
11 This is a modified version of a source file from the | |
12 Rosegarden MIDI and audio sequencer and notation editor. | |
13 This file copyright 2000-2005 Chris Cannam. | |
14 */ | |
15 | |
16 #include <iostream> | |
17 | |
18 #if (__GNUC__ < 3) | |
19 #include <strstream> | |
20 #define stringstream strstream | |
21 #else | |
22 #include <sstream> | |
23 #endif | |
24 | |
25 using std::cerr; | |
26 using std::endl; | |
27 | |
28 #include "base/RealTime.h" | |
29 | |
30 // A RealTime consists of two ints that must be at least 32 bits each. | |
31 // A signed 32-bit int can store values exceeding +/- 2 billion. This | |
32 // means we can safely use our lower int for nanoseconds, as there are | |
33 // 1 billion nanoseconds in a second and we need to handle double that | |
34 // because of the implementations of addition etc that we use. | |
35 // | |
36 // The maximum valid RealTime on a 32-bit system is somewhere around | |
37 // 68 years: 999999999 nanoseconds longer than the classic Unix epoch. | |
38 | |
39 #define ONE_BILLION 1000000000 | |
40 | |
41 RealTime::RealTime(int s, int n) : | |
42 sec(s), nsec(n) | |
43 { | |
44 if (sec == 0) { | |
45 while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; } | |
46 while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; } | |
47 } else if (sec < 0) { | |
48 while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; } | |
49 while (nsec > 0) { nsec -= ONE_BILLION; ++sec; } | |
50 } else { | |
51 while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; } | |
52 while (nsec < 0) { nsec += ONE_BILLION; --sec; } | |
53 } | |
54 } | |
55 | |
56 | |
57 std::ostream &operator<<(std::ostream &out, const RealTime &rt) | |
58 { | |
59 if (rt < RealTime::zeroTime) { | |
60 out << "-"; | |
61 } else { | |
62 out << " "; | |
63 } | |
64 | |
65 int s = (rt.sec < 0 ? -rt.sec : rt.sec); | |
66 int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec); | |
67 | |
68 out << s << "."; | |
69 | |
70 int nn(n); | |
71 if (nn == 0) out << "00000000"; | |
72 else while (nn < (ONE_BILLION / 10)) { | |
73 out << "0"; | |
74 nn *= 10; | |
75 } | |
76 | |
77 out << n << "R"; | |
78 return out; | |
79 } | |
80 | |
81 std::string | |
82 RealTime::toString() const | |
83 { | |
84 std::stringstream out; | |
85 out << *this; | |
86 | |
87 #if (__GNUC__ < 3) | |
88 out << std::ends; | |
89 #endif | |
90 | |
91 std::string s = out.str(); | |
92 | |
93 // remove trailing R | |
94 return s.substr(0, s.length() - 1); | |
95 } | |
96 | |
97 std::string | |
98 RealTime::toText(bool fixedDp) const | |
99 { | |
100 if (*this < RealTime::zeroTime) return "-" + (-*this).toText(); | |
101 | |
102 std::stringstream out; | |
103 | |
104 if (sec >= 3600) { | |
105 out << (sec / 3600) << ":"; | |
106 } | |
107 | |
108 if (sec >= 60) { | |
109 out << (sec % 3600) / 60 << ":"; | |
110 } | |
111 | |
112 if (sec >= 10) { | |
113 out << ((sec % 60) / 10); | |
114 } | |
115 | |
116 out << (sec % 10); | |
117 | |
118 int ms = msec(); | |
119 | |
120 if (ms != 0) { | |
121 out << "."; | |
122 out << (ms / 100); | |
123 ms = ms % 100; | |
124 if (ms != 0) { | |
125 out << (ms / 10); | |
126 ms = ms % 10; | |
127 } else if (fixedDp) { | |
128 out << "0"; | |
129 } | |
130 if (ms != 0) { | |
131 out << ms; | |
132 } else if (fixedDp) { | |
133 out << "0"; | |
134 } | |
135 } else if (fixedDp) { | |
136 out << ".000"; | |
137 } | |
138 | |
139 #if (__GNUC__ < 3) | |
140 out << std::ends; | |
141 #endif | |
142 | |
143 std::string s = out.str(); | |
144 | |
145 return s; | |
146 } | |
147 | |
148 | |
149 RealTime | |
150 RealTime::operator/(int d) const | |
151 { | |
152 int secdiv = sec / d; | |
153 int secrem = sec % d; | |
154 | |
155 double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d; | |
156 | |
157 return RealTime(secdiv, int(nsecdiv + 0.5)); | |
158 } | |
159 | |
160 double | |
161 RealTime::operator/(const RealTime &r) const | |
162 { | |
163 double lTotal = double(sec) * ONE_BILLION + double(nsec); | |
164 double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec); | |
165 | |
166 if (rTotal == 0) return 0.0; | |
167 else return lTotal/rTotal; | |
168 } | |
169 | |
170 long | |
171 RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate) | |
172 { | |
173 if (time < zeroTime) return -realTime2Frame(-time, sampleRate); | |
174 | |
175 // We like integers. The last term is always zero unless the | |
176 // sample rate is greater than 1MHz, but hell, you never know... | |
177 | |
178 long frame = | |
179 time.sec * sampleRate + | |
180 (time.msec() * sampleRate) / 1000 + | |
181 ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 + | |
182 ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000; | |
183 | |
184 return frame; | |
185 } | |
186 | |
187 RealTime | |
188 RealTime::frame2RealTime(long frame, unsigned int sampleRate) | |
189 { | |
190 if (frame < 0) return -frame2RealTime(-frame, sampleRate); | |
191 | |
192 RealTime rt; | |
193 rt.sec = frame / long(sampleRate); | |
194 frame -= rt.sec * long(sampleRate); | |
195 rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000); | |
196 return rt; | |
197 } | |
198 | |
199 const RealTime RealTime::zeroTime(0,0); | |
200 |