comparison sdk/RealTime.cpp @ 0:6479539d1b32

* Importing first cut of Sonic Visualiser's Vamp plugin format SDK
author cannam
date Fri, 31 Mar 2006 14:21:51 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:6479539d1b32
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Vamp
5
6 An API for audio analysis and feature extraction plugins.
7
8 Centre for Digital Music, Queen Mary, University of London.
9 Copyright 2006 Chris Cannam.
10
11 Permission is hereby granted, free of charge, to any person
12 obtaining a copy of this software and associated documentation
13 files (the "Software"), to deal in the Software without
14 restriction, including without limitation the rights to use, copy,
15 modify, merge, publish, distribute, sublicense, and/or sell copies
16 of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be
20 included in all copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 Except as contained in this notice, the names of the Centre for
31 Digital Music; Queen Mary, University of London; and Chris Cannam
32 shall not be used in advertising or otherwise to promote the sale,
33 use or other dealings in this Software without prior written
34 authorization.
35 */
36
37 /*
38 This is a modified version of a source file from the
39 Rosegarden MIDI and audio sequencer and notation editor.
40 This file copyright 2000-2006 Chris Cannam; relicensed as detailed above
41 */
42
43 #include <iostream>
44
45 #if (__GNUC__ < 3)
46 #include <strstream>
47 #define stringstream strstream
48 #else
49 #include <sstream>
50 #endif
51
52 using std::cerr;
53 using std::endl;
54
55 #include "RealTime.h"
56 #include "sys/time.h"
57
58 namespace Vamp {
59
60 // A RealTime consists of two ints that must be at least 32 bits each.
61 // A signed 32-bit int can store values exceeding +/- 2 billion. This
62 // means we can safely use our lower int for nanoseconds, as there are
63 // 1 billion nanoseconds in a second and we need to handle double that
64 // because of the implementations of addition etc that we use.
65 //
66 // The maximum valid RealTime on a 32-bit system is somewhere around
67 // 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
68
69 #define ONE_BILLION 1000000000
70
71 RealTime::RealTime(int s, int n) :
72 sec(s), nsec(n)
73 {
74 if (sec == 0) {
75 while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
76 while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
77 } else if (sec < 0) {
78 while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
79 while (nsec > 0) { nsec -= ONE_BILLION; ++sec; }
80 } else {
81 while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
82 while (nsec < 0) { nsec += ONE_BILLION; --sec; }
83 }
84 }
85
86 RealTime
87 RealTime::fromSeconds(double sec)
88 {
89 return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION));
90 }
91
92 RealTime
93 RealTime::fromMilliseconds(int msec)
94 {
95 return RealTime(msec / 1000, (msec % 1000) * 1000000);
96 }
97
98 RealTime
99 RealTime::fromTimeval(const struct timeval &tv)
100 {
101 return RealTime(tv.tv_sec, tv.tv_usec * 1000);
102 }
103
104 std::ostream &operator<<(std::ostream &out, const RealTime &rt)
105 {
106 if (rt < RealTime::zeroTime) {
107 out << "-";
108 } else {
109 out << " ";
110 }
111
112 int s = (rt.sec < 0 ? -rt.sec : rt.sec);
113 int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
114
115 out << s << ".";
116
117 int nn(n);
118 if (nn == 0) out << "00000000";
119 else while (nn < (ONE_BILLION / 10)) {
120 out << "0";
121 nn *= 10;
122 }
123
124 out << n << "R";
125 return out;
126 }
127
128 std::string
129 RealTime::toString() const
130 {
131 std::stringstream out;
132 out << *this;
133
134 #if (__GNUC__ < 3)
135 out << std::ends;
136 #endif
137
138 std::string s = out.str();
139
140 // remove trailing R
141 return s.substr(0, s.length() - 1);
142 }
143
144 std::string
145 RealTime::toText(bool fixedDp) const
146 {
147 if (*this < RealTime::zeroTime) return "-" + (-*this).toText();
148
149 std::stringstream out;
150
151 if (sec >= 3600) {
152 out << (sec / 3600) << ":";
153 }
154
155 if (sec >= 60) {
156 out << (sec % 3600) / 60 << ":";
157 }
158
159 if (sec >= 10) {
160 out << ((sec % 60) / 10);
161 }
162
163 out << (sec % 10);
164
165 int ms = msec();
166
167 if (ms != 0) {
168 out << ".";
169 out << (ms / 100);
170 ms = ms % 100;
171 if (ms != 0) {
172 out << (ms / 10);
173 ms = ms % 10;
174 } else if (fixedDp) {
175 out << "0";
176 }
177 if (ms != 0) {
178 out << ms;
179 } else if (fixedDp) {
180 out << "0";
181 }
182 } else if (fixedDp) {
183 out << ".000";
184 }
185
186 #if (__GNUC__ < 3)
187 out << std::ends;
188 #endif
189
190 std::string s = out.str();
191
192 return s;
193 }
194
195
196 RealTime
197 RealTime::operator/(int d) const
198 {
199 int secdiv = sec / d;
200 int secrem = sec % d;
201
202 double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
203
204 return RealTime(secdiv, int(nsecdiv + 0.5));
205 }
206
207 double
208 RealTime::operator/(const RealTime &r) const
209 {
210 double lTotal = double(sec) * ONE_BILLION + double(nsec);
211 double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
212
213 if (rTotal == 0) return 0.0;
214 else return lTotal/rTotal;
215 }
216
217 long
218 RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
219 {
220 if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
221
222 // We like integers. The last term is always zero unless the
223 // sample rate is greater than 1MHz, but hell, you never know...
224
225 long frame =
226 time.sec * sampleRate +
227 (time.msec() * sampleRate) / 1000 +
228 ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 +
229 ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000;
230
231 return frame;
232 }
233
234 RealTime
235 RealTime::frame2RealTime(long frame, unsigned int sampleRate)
236 {
237 if (frame < 0) return -frame2RealTime(-frame, sampleRate);
238
239 RealTime rt;
240 rt.sec = frame / long(sampleRate);
241 frame -= rt.sec * long(sampleRate);
242 rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000);
243 return rt;
244 }
245
246 const RealTime RealTime::zeroTime(0,0);
247
248 }